File wellmet/simplex.py changed (mode: 100644) (index 4d6d335..b31892c) |
... |
... |
class DefaultDict(dict): |
267 |
267 |
|
|
268 |
268 |
|
|
269 |
269 |
|
|
270 |
|
class _Sense: |
|
|
270 |
|
class _NaiveSense: |
271 |
271 |
|
|
272 |
272 |
def _init(self): |
def _init(self): |
273 |
273 |
# I'll try to use dual name convention here |
# I'll try to use dual name convention here |
|
... |
... |
class _Sense: |
541 |
541 |
|
|
542 |
542 |
|
|
543 |
543 |
|
|
|
544 |
|
FinalizedAxis = namedtuple('FinalizedAxis', ( |
|
545 |
|
'normal', |
|
546 |
|
#'sensitivities', |
|
547 |
|
'separated_simplices' |
|
548 |
|
)) |
|
549 |
|
|
|
550 |
|
|
|
551 |
|
|
|
552 |
|
class _Sense: |
|
553 |
|
|
|
554 |
|
def _init(self): |
|
555 |
|
# I'll try to use dual name convention here |
|
556 |
|
# self for this class, sensibility-related things |
|
557 |
|
# sx for general Triangulation class related attributes |
|
558 |
|
sx = self |
|
559 |
|
|
|
560 |
|
nsim, nvar = sx.tri.points.shape |
|
561 |
|
|
|
562 |
|
|
|
563 |
|
|
|
564 |
|
#self.points = sx.tri.points |
|
565 |
|
#self.failsi = sx.sample_box.failsi |
|
566 |
|
#self.non_failsi = ~self.failsi |
|
567 |
|
#self._point_mask = np.empty_like(self.failsi) |
|
568 |
|
#self._scalars = np.empty(len(self.failsi)) |
|
569 |
|
#self._boolmask = np.empty_like(self.failsi) |
|
570 |
|
|
|
571 |
|
|
|
572 |
|
points = sx.tri.points |
|
573 |
|
failsi = sx.sample_box.failsi |
|
574 |
|
simplices = sx.tri.simplices |
|
575 |
|
|
|
576 |
|
self._local_scope = dict() |
|
577 |
|
#ё сепаратошная |
|
578 |
|
self.separability_solver = SeparationAxis(sx, self._local_scope) |
|
579 |
|
|
|
580 |
|
self._to_parse = set() |
|
581 |
|
self._parsed = set() |
|
582 |
|
|
|
583 |
|
|
|
584 |
|
|
|
585 |
|
self.mixed_mask = mixed_mask = sx.is_mixed(simplices) |
|
586 |
|
|
|
587 |
|
event_ids = np.empty(sx.tri.nsimplex + 1, dtype=np.int8) |
|
588 |
|
event_ids[:-1] = sx.get_events() |
|
589 |
|
event_ids[-1] = -1 |
|
590 |
|
|
|
591 |
|
neighbors = sx.tri.neighbors |
|
592 |
|
neighbors_mask = event_ids[neighbors] == 2 |
|
593 |
|
|
|
594 |
|
#č v těch otačkách budeme potřebovat pořad dokola |
|
595 |
|
self.neighbors_masked = neighbors_masked = dict() #defaultdict(list) |
|
596 |
|
zip_iter = zip(range(len(mixed_mask)), mixed_mask, neighbors, neighbors_mask) |
|
597 |
|
for id, is_mixed, neis, neis_mask in zip_iter: |
|
598 |
|
if not is_mixed: |
|
599 |
|
continue |
|
600 |
|
|
|
601 |
|
neighbors_masked[id] = neis[neis_mask] |
|
602 |
|
|
|
603 |
|
|
|
604 |
|
|
|
605 |
|
def perform_sensitivity_analysis(self): |
|
606 |
|
# I'll try to use dual name convention here |
|
607 |
|
# self for this class, sensitivity-related things |
|
608 |
|
# sx for general Triangulation class related attributes |
|
609 |
|
sx = self |
|
610 |
|
|
|
611 |
|
self._init() |
|
612 |
|
|
|
613 |
|
|
|
614 |
|
mixed_mask = self.mixed_mask |
|
615 |
|
|
|
616 |
|
depths = defaultdict(int) #č hloubka jádra |
|
617 |
|
coverings = defaultdict(int) #č počet separovaných vektorem simplexů |
|
618 |
|
vectors = dict() |
|
619 |
|
|
|
620 |
|
last_scope = self._local_scope |
|
621 |
|
|
|
622 |
|
for simplex_id, is_mixed in zip(range(len(mixed_mask)), mixed_mask): |
|
623 |
|
if not is_mixed: |
|
624 |
|
continue |
|
625 |
|
|
|
626 |
|
depth = depths[simplex_id] |
|
627 |
|
normal = vectors.get(simplex_id, None) |
|
628 |
|
id_before = id(normal) |
|
629 |
|
# we will remain normal for finalized normal |
|
630 |
|
# and vector for just nunpy vector |
|
631 |
|
normal = self.process_simplex(simplex_id, depth, normal) |
|
632 |
|
id_after = id(normal) |
|
633 |
|
|
|
634 |
|
new_depth = last_scope[simplex_id] |
|
635 |
|
covering = len(normal.separated_simplices) |
|
636 |
|
|
|
637 |
|
vectors[simplex_id] = normal |
|
638 |
|
depths[simplex_id] = new_depth |
|
639 |
|
coverings[simplex_id] = covering |
|
640 |
|
|
|
641 |
|
#č na vystupu z process_simplex() musí být finální vektor |
|
642 |
|
#č pokud není stejný, tak má cenu ho přířadit všem simplexům, které pokryvá |
|
643 |
|
#č pokud byť i stejný vektor získal větší hloubku, |
|
644 |
|
#č má cenu projít simplexy, ať přiště nebudou přepsany |
|
645 |
|
#č a ušetří to na neprojděných simplexech kus práce |
|
646 |
|
# |
|
647 |
|
#č zavadíme tady covering. Ale je to jedno. |
|
648 |
|
#č s nim musí to bejt o maliňko líp, bez nej - o maliňko hůř. |
|
649 |
|
#č Procházíme veškeré simplexy i zpětně. |
|
650 |
|
#č Ale je to jedno. Můžeme procházet, můžeme neprocházet. |
|
651 |
|
#č Takto musí to bejt o maliňko líp, bez toho - o maliňko hůř. |
|
652 |
|
if (id_before != id_after) or (new_depth > depth): |
|
653 |
|
for key, key_depth in last_scope.items(): |
|
654 |
|
#č teď povolíme i přepsaní jíž projděných simplexů |
|
655 |
|
if (key_depth >= depths[key]) and (covering >= coverings[key]): |
|
656 |
|
vectors[key] = normal |
|
657 |
|
depths[key] = key_depth |
|
658 |
|
coverings[key] = covering |
|
659 |
|
|
|
660 |
|
|
|
661 |
|
|
|
662 |
|
|
|
663 |
|
probabilities = dict() |
|
664 |
|
mixed_probability = 0 |
|
665 |
|
nvar = sx.sample_box.nvar |
|
666 |
|
global_gradient = np.zeros(nvar) |
|
667 |
|
sensitivities = np.zeros(nvar) |
|
668 |
|
simplices = sx.tri.simplices |
|
669 |
|
|
|
670 |
|
vector = np.empty(nvar) |
|
671 |
|
#sensitivity = np.empty(nvar) |
|
672 |
|
|
|
673 |
|
for simplex_id, normal in vectors.items(): |
|
674 |
|
indices = simplices[simplex_id] |
|
675 |
|
p_mixed = sx.get_simplex_probability(indices) |
|
676 |
|
mixed_probability += p_mixed |
|
677 |
|
probabilities[simplex_id] = p_mixed |
|
678 |
|
|
|
679 |
|
np.multiply(normal.normal, p_mixed, out=vector) |
|
680 |
|
global_gradient += vector |
|
681 |
|
|
|
682 |
|
np.square(normal.normal, out=vector) |
|
683 |
|
vector *= p_mixed |
|
684 |
|
sensitivities += vector |
|
685 |
|
|
|
686 |
|
|
|
687 |
|
sensitivities /= mixed_probability |
|
688 |
|
|
|
689 |
|
return global_gradient, sensitivities, \ |
|
690 |
|
probabilities, depths, vectors , coverings |
|
691 |
|
|
|
692 |
|
|
|
693 |
|
|
|
694 |
|
|
|
695 |
|
|
|
696 |
|
def process_simplex(self, simplex_id, depth, finalized_normal): |
|
697 |
|
# self for this class, sensitivity-related things |
|
698 |
|
# sx for general Triangulation class related attributes |
|
699 |
|
sx = self |
|
700 |
|
|
|
701 |
|
solver = self.separability_solver |
|
702 |
|
solver.reset(simplex_id, finalized_normal) |
|
703 |
|
|
|
704 |
|
local_scope = self._local_scope |
|
705 |
|
local_scope.clear() |
|
706 |
|
local_scope[simplex_id] = 0 |
|
707 |
|
|
|
708 |
|
to_parse = self._to_parse |
|
709 |
|
to_parse.clear() |
|
710 |
|
|
|
711 |
|
parsed = self._parsed |
|
712 |
|
parsed.clear() |
|
713 |
|
|
|
714 |
|
simplices = sx.tri.simplices |
|
715 |
|
neighbors_masked = self.neighbors_masked |
|
716 |
|
|
|
717 |
|
to_parse.update(neighbors_masked[simplex_id]) |
|
718 |
|
|
|
719 |
|
#č nenulový depth může příjít jen spolu s |
|
720 |
|
#č s nějakou finalized_normal. |
|
721 |
|
#č Ta zaručeně bude pokryvat simplexy |
|
722 |
|
#č do hloubky depth. |
|
723 |
|
#č Netřeba nic kontrolovat, ani do solveru nic ukladat |
|
724 |
|
for __i in range(depth): |
|
725 |
|
for key in local_scope.keys(): |
|
726 |
|
local_scope[key] += 1 |
|
727 |
|
|
|
728 |
|
to_parse -= local_scope.keys() |
|
729 |
|
to_parse, parsed = parsed, to_parse |
|
730 |
|
to_parse.clear() |
|
731 |
|
for id in parsed: # meant to be parsed in the cycle's end |
|
732 |
|
to_parse.update(neighbors_masked[id]) |
|
733 |
|
local_scope[id] = 0 |
|
734 |
|
|
|
735 |
|
|
|
736 |
|
assert local_scope[simplex_id] == depth |
|
737 |
|
|
|
738 |
|
#č teď: |
|
739 |
|
#č když byl před tím finalized_normal, |
|
740 |
|
#č tak volaním .add_simplex() solver bude jenom kontrolovat uložený |
|
741 |
|
#č do nej seznam simplexu. Nebude nikde nic ukladat. |
|
742 |
|
#č Až narazí na separabilitu, tak teprve tehdy potřebuje ten local_scope |
|
743 |
|
#č ale i na něj má uloženou referenci. |
|
744 |
|
# |
|
745 |
|
#č Pokud žádný finalized_normal není, |
|
746 |
|
#č tak předchozí smyčka se neuskuteční, |
|
747 |
|
#č local_scope a point skoupy řešiče se rovnoměrně naplňují od nuly. |
|
748 |
|
#č Solver tedy tím is_separable() skutečně mění svůj stav |
|
749 |
|
#č a navíc se předpokládá, že do add_simplex() se budou sypat |
|
750 |
|
#č jen skutečně sousedící simplexy. |
|
751 |
|
# |
|
752 |
|
#č Závěr: použité abstrakce jsou děravé. |
|
753 |
|
#č Tahlensta smyčka je hodně provazana s tím řešičem |
|
754 |
|
#č a teprve dohromady tvoří společný algoritmus. |
|
755 |
|
#č Ale i tak mám velkou radost, že se mi podařilo |
|
756 |
|
#č aspoň nejak ty části odseparovat. |
|
757 |
|
|
|
758 |
|
|
|
759 |
|
#č běh smyčky je podmíněn tím, že má co dělat |
|
760 |
|
to_parse -= local_scope.keys() |
|
761 |
|
while len(to_parse): #č máme co dělat? |
|
762 |
|
|
|
763 |
|
#č projedeme várku simplexu, přídáme je do slovníku, |
|
764 |
|
#č "zapneme" přípojené k ním vzorky |
|
765 |
|
to_parse, parsed = parsed, to_parse |
|
766 |
|
to_parse.clear() |
|
767 |
|
for id in parsed: # meant to be parsed in the cycle's end |
|
768 |
|
if solver.add_neighbor_simplex(id): |
|
769 |
|
#č přídáme do to_parse pouze pokud |
|
770 |
|
#č simplex se uspěšně přídal |
|
771 |
|
local_scope[id] = -1 |
|
772 |
|
to_parse.update(neighbors_masked[id]) |
|
773 |
|
|
|
774 |
|
#č tady je jediné místo, kde řešič použil local_scope |
|
775 |
|
#č narazili jsme na neseparabilitu tzv. jádra |
|
776 |
|
#č teď nám jde o to, abychom vrátili jakékoliv finální vektor |
|
777 |
|
#č Pokud ho zrovna máme v ruce, tak ho jenom vrátíme. |
|
778 |
|
elif solver.finalized_nornal is None: |
|
779 |
|
#č některé simplexy zůstaly s hloubkou -1 |
|
780 |
|
#č poďme je vrátíme do normálu |
|
781 |
|
#č umožní to přepsaní implicitní nulové hodnoty |
|
782 |
|
#č přířadí se jim náš skvělý finální vektor |
|
783 |
|
#č ušetří se tím kousiček práce |
|
784 |
|
for key in parsed: |
|
785 |
|
if key in local_scope: |
|
786 |
|
#č prostě paušalně navysíme o jednu |
|
787 |
|
#č byly tam -1 |
|
788 |
|
local_scope[key] += 1 |
|
789 |
|
return self._continue_search(id) |
|
790 |
|
else: |
|
791 |
|
return solver.finalized_nornal |
|
792 |
|
|
|
793 |
|
|
|
794 |
|
#č pokud jsme tu, tak vzorky byly separabilní, |
|
795 |
|
#č je na čase "navysit" hloubku |
|
796 |
|
for key in local_scope.keys(): |
|
797 |
|
local_scope[key] += 1 |
|
798 |
|
|
|
799 |
|
#č běh smyčky je podmíněn tím, že má co dělat |
|
800 |
|
to_parse -= local_scope.keys() |
|
801 |
|
|
|
802 |
|
|
|
803 |
|
#č šťastné finále, region je plně separabilní |
|
804 |
|
if solver.finalized_nornal is None: |
|
805 |
|
return self.get_finalized(solver.normal, frozenset(local_scope.keys())) |
|
806 |
|
else: |
|
807 |
|
return solver.finalized_nornal |
|
808 |
|
|
|
809 |
|
|
|
810 |
|
@staticmethod |
|
811 |
|
def get_finalized(normal, separated_simplices): |
|
812 |
|
length = np.sqrt(np.inner(normal, normal)) |
|
813 |
|
# scale to unit length |
|
814 |
|
np.divide(normal, length, out=normal) |
|
815 |
|
|
|
816 |
|
#sensitivities = np.square(normal) |
|
817 |
|
|
|
818 |
|
return FinalizedAxis(normal, separated_simplices) |
|
819 |
|
|
|
820 |
|
|
|
821 |
|
# should be only called by process_simplex()! |
|
822 |
|
def _continue_search(self, non_separable_simplex_id): |
|
823 |
|
# self for this class, sensitivity-related things |
|
824 |
|
# sx for general Triangulation class related attributes |
|
825 |
|
sx = self |
|
826 |
|
|
|
827 |
|
solver = self.separability_solver |
|
828 |
|
assert solver.finalized_nornal is None |
|
829 |
|
|
|
830 |
|
|
|
831 |
|
simplices = sx.tri.simplices |
|
832 |
|
neighbors_masked = self.neighbors_masked |
|
833 |
|
|
|
834 |
|
non_separable_simplices = {non_separable_simplex_id} |
|
835 |
|
|
|
836 |
|
#č důležité: běh process_simplex() byl |
|
837 |
|
#č přerušen neseparabilitou. |
|
838 |
|
#č My budeme pokračovat |
|
839 |
|
#č a my víme, že v techto množinách zůstalo |
|
840 |
|
#č to, co máme projít. A pozastavilo se to na parsed |
|
841 |
|
local_scope = self._local_scope |
|
842 |
|
to_parse = self._to_parse |
|
843 |
|
parsed = self._parsed |
|
844 |
|
|
|
845 |
|
for key in parsed: |
|
846 |
|
if key in local_scope: |
|
847 |
|
#č ten klíč jíž byl zpracován, jedeme dál |
|
848 |
|
continue |
|
849 |
|
|
|
850 |
|
if solver.add_neighbor_simplex(key): |
|
851 |
|
#č přídáme do to_parse pouze pokud |
|
852 |
|
#č simplex se uspěšně přídal |
|
853 |
|
#č v této fázi všemu dáváme nulu, |
|
854 |
|
#č hloubku nadale jíž nenavyšujeme |
|
855 |
|
local_scope[key] = 0 |
|
856 |
|
to_parse.update(neighbors_masked[key]) |
|
857 |
|
else: |
|
858 |
|
non_separable_simplices.add(key) |
|
859 |
|
|
|
860 |
|
|
|
861 |
|
|
|
862 |
|
#č naposled množinové operace |
|
863 |
|
to_parse -= local_scope.keys() |
|
864 |
|
to_parse -= non_separable_simplices |
|
865 |
|
while len(to_parse): |
|
866 |
|
key = to_parse.pop() |
|
867 |
|
if (key in local_scope) or (key in non_separable_simplices): |
|
868 |
|
#č ten klíč jíž byl zpracován, jedeme dál |
|
869 |
|
continue |
|
870 |
|
|
|
871 |
|
if solver.add_neighbor_simplex(key): |
|
872 |
|
#č přídáme do to_parse pouze pokud |
|
873 |
|
#č simplex se uspěšně přídal |
|
874 |
|
#č v této fázi všemu dáváme nulu, |
|
875 |
|
#č hloubku nadale jíž nenavyšujeme |
|
876 |
|
local_scope[key] = 0 |
|
877 |
|
to_parse.update(neighbors_masked[key]) |
|
878 |
|
else: |
|
879 |
|
non_separable_simplices.add(key) |
|
880 |
|
|
|
881 |
|
|
|
882 |
|
return self.get_finalized(solver.normal, frozenset(local_scope.keys())) |
|
883 |
|
|
|
884 |
|
|
|
885 |
|
|
|
886 |
|
|
|
887 |
|
|
|
888 |
|
|
|
889 |
|
|
|
890 |
|
|
|
891 |
|
|
|
892 |
|
|
|
893 |
|
|
|
894 |
|
|
|
895 |
|
|
544 |
896 |
|
|
545 |
897 |
#č tohle vůbec není žádná samostatná třída |
#č tohle vůbec není žádná samostatná třída |
546 |
898 |
#č Její jedina instance taky vůbec není samostatná. |
#č Její jedina instance taky vůbec není samostatná. |
|
... |
... |
class SeparationAxis: |
551 |
903 |
#č simplex_scope potřebujeme pouze v jednom místě |
#č simplex_scope potřebujeme pouze v jednom místě |
552 |
904 |
self.simplex_scope = simplex_scope_reference |
self.simplex_scope = simplex_scope_reference |
553 |
905 |
self.point_scope = set() |
self.point_scope = set() |
|
906 |
|
self.non_separable_point_set = set() |
554 |
907 |
self.sx = sx # for sx.get_simplex_normal() |
self.sx = sx # for sx.get_simplex_normal() |
555 |
908 |
|
|
556 |
909 |
self.ED = points = sx.tri.points |
self.ED = points = sx.tri.points |
|
... |
... |
class SeparationAxis: |
573 |
926 |
def reset(self, simplex_id, finalized_nornal): |
def reset(self, simplex_id, finalized_nornal): |
574 |
927 |
self.finalized_nornal = finalized_nornal |
self.finalized_nornal = finalized_nornal |
575 |
928 |
|
|
|
929 |
|
#č to jediné místo, kde vynulujeme point scopes |
|
930 |
|
self.point_scope.clear() |
|
931 |
|
self.non_separable_point_set.clear() |
|
932 |
|
|
576 |
933 |
#č I když se mi nechce semka tahnout get_simplex_normal(), |
#č I když se mi nechce semka tahnout get_simplex_normal(), |
577 |
934 |
#č stejně potřebuji indices pro point_scope |
#č stejně potřebuji indices pro point_scope |
578 |
935 |
if finalized_nornal is None: |
if finalized_nornal is None: |
579 |
|
self.point_scope.clear() |
|
580 |
936 |
indices = self.simplices[simplex_id] |
indices = self.simplices[simplex_id] |
581 |
937 |
self.point_scope.update(indices) |
self.point_scope.update(indices) |
582 |
938 |
#č hloubka je nulová, žádné přípravné otačky konat nebudou. |
#č hloubka je nulová, žádné přípravné otačky konat nebudou. |
|
... |
... |
class SeparationAxis: |
626 |
982 |
self.min_green = min_green |
self.min_green = min_green |
627 |
983 |
|
|
628 |
984 |
|
|
629 |
|
|
|
630 |
|
def is_separable(self, simplex_id): |
|
|
985 |
|
# it's actually something between "is_separable" and "add_simplex" |
|
986 |
|
def add_neighbor_simplex(self, simplex_id): |
631 |
987 |
if self.finalized_nornal is None: |
if self.finalized_nornal is None: |
632 |
988 |
return self._is_non_finalized_separable(simplex_id) |
return self._is_non_finalized_separable(simplex_id) |
633 |
989 |
|
|
|
... |
... |
class SeparationAxis: |
656 |
1012 |
simplices = self.simplices |
simplices = self.simplices |
657 |
1013 |
|
|
658 |
1014 |
point_scope = self.point_scope |
point_scope = self.point_scope |
659 |
|
#č vytvořme platný skoup |
|
660 |
|
point_scope.clear() |
|
|
1015 |
|
#č musí jíž být vyprazdněný v reset() #vytvořme platný skoup |
|
1016 |
|
#point_scope.clear() |
661 |
1017 |
#č jediné místo, kde simplex_scope potřebujeme! |
#č jediné místo, kde simplex_scope potřebujeme! |
662 |
1018 |
for key in self.simplex_scope.keys(): |
for key in self.simplex_scope.keys(): |
663 |
1019 |
point_scope.update(simplices[key]) |
point_scope.update(simplices[key]) |
|
... |
... |
class SeparationAxis: |
680 |
1036 |
if not result.success: #č konec, zde končíme |
if not result.success: #č konec, zde končíme |
681 |
1037 |
if result.status != 2: # Problem appears to be infeasible. |
if result.status != 2: # Problem appears to be infeasible. |
682 |
1038 |
print("Sense: linprog ended with status %s" % result.status) |
print("Sense: linprog ended with status %s" % result.status) |
|
1039 |
|
#č non_separable_point_set zde taky nemusím řešit |
683 |
1040 |
return False #č na finalized_nornal nesáháme |
return False #č na finalized_nornal nesáháme |
684 |
1041 |
|
|
685 |
1042 |
# sucсess! |
# sucсess! |
|
... |
... |
class SeparationAxis: |
687 |
1044 |
#č _set_normal() tu totalní normalu vynulue |
#č _set_normal() tu totalní normalu vynulue |
688 |
1045 |
#self.finalized_nornal = None |
#self.finalized_nornal = None |
689 |
1046 |
|
|
|
1047 |
|
|
690 |
1048 |
#č hned odřízneme poslední složku - |
#č hned odřízneme poslední složku - |
691 |
1049 |
#č bude tam posunutí b aka offcet aka bias |
#č bude tam posunutí b aka offcet aka bias |
692 |
1050 |
#č point_scope jíž máme v pořádku. |
#č point_scope jíž máme v pořádku. |
|
... |
... |
class SeparationAxis: |
701 |
1059 |
#č Zbytek nového simplexu tvoří společná stěna-hyperrovina. |
#č Zbytek nového simplexu tvoří společná stěna-hyperrovina. |
702 |
1060 |
def _is_non_finalized_separable(self, simplex_id): |
def _is_non_finalized_separable(self, simplex_id): |
703 |
1061 |
|
|
704 |
|
#č tady je to opakový opak |
|
705 |
|
#č Pokud vzorek nejde separovat, tak se nesmí dostat do point_scope |
|
706 |
|
#č V každém případě se bude pokračovat až do posledního simplexu |
|
707 |
|
|
|
708 |
|
#č metoda buď přída vzorek do skoupu a vratí None, |
|
709 |
|
#č nebo nepřídá a ho vrátí. Striktně jeden. |
|
710 |
|
non_separable_point = self._is_neighbor_separable(simplex_id) |
|
711 |
|
if non_separable_point is None: |
|
712 |
|
return True |
|
713 |
|
|
|
714 |
|
#č point_scope už máme |
|
715 |
|
point_list = list(self.point_scope) |
|
716 |
|
point_list.add(non_separable_point) |
|
717 |
|
|
|
718 |
|
result = self.get_separation_axis(point_list) |
|
719 |
|
if not result.success: #č konec, zde končíme |
|
720 |
|
if result.status != 2: # Problem appears to be infeasible. |
|
721 |
|
print("Sense: linprog ended with status %s" % result.status) |
|
722 |
|
return False |
|
723 |
|
|
|
724 |
|
# sucсess! |
|
725 |
|
#č dodáme ten diskutovaný pochybný, jíž ospravedlněný vzorek |
|
726 |
|
self.point_scope.add(non_separable_point) |
|
727 |
|
|
|
728 |
|
#č hned odřízneme poslední složku - |
|
729 |
|
#č bude tam posunutí b aka offcet aka bias |
|
730 |
|
self._set_normal(result.x[:-1]) |
|
731 |
|
|
|
732 |
|
return True |
|
733 |
|
|
|
734 |
|
|
|
735 |
|
|
|
736 |
|
#č Pokud zkoušíme separabilitu sousedícího simplexu, |
|
737 |
|
#č tak narazíme na maximálně jeden nový vzorek. |
|
738 |
|
#č Zbytek nového simplexu tvoří společná stěna-hyperrovina. |
|
739 |
|
#č zkusme takhle. V případě, že tamten nový vzorek jde odseparovat, |
|
740 |
|
#č tak vratíme None, jinak číslo toho vzorku pro další kód |
|
741 |
|
def _is_neighbor_separable(self, simplex_id): |
|
742 |
1062 |
#č z logiky volajícího kódu nema cenu kontrolovat simplex_scope |
#č z logiky volajícího kódu nema cenu kontrolovat simplex_scope |
743 |
1063 |
#č ono se ptá na separabilitu pouze toho, co jíž není ve skoupu |
#č ono se ptá na separabilitu pouze toho, co jíž není ve skoupu |
744 |
1064 |
#if simplex_id in self.simplex_scope: |
#if simplex_id in self.simplex_scope: |
|
... |
... |
class SeparationAxis: |
746 |
1066 |
|
|
747 |
1067 |
for point in self.simplices[simplex_id]: |
for point in self.simplices[simplex_id]: |
748 |
1068 |
if point not in self.point_scope: |
if point not in self.point_scope: |
|
1069 |
|
#č jediné místo, kde non_separable_point_set použijeme |
|
1070 |
|
if point in self.non_separable_point_set: |
|
1071 |
|
#č prostě vrácíme False, nic dalšího řešit netřeba |
|
1072 |
|
return False |
749 |
1073 |
value = np.inner(self.normal, self.ED[point]) |
value = np.inner(self.normal, self.ED[point]) |
750 |
1074 |
if self.failsi[point]: |
if self.failsi[point]: |
751 |
1075 |
if value > self.min_green: |
if value > self.min_green: |
752 |
|
return point |
|
|
1076 |
|
#č současná normála to neseparuje. |
|
1077 |
|
#č ale možná bude nějaká jiná? |
|
1078 |
|
return self._is_one_more_point_ever_separable(point) |
753 |
1079 |
elif value > self.max_red: |
elif value > self.max_red: |
754 |
1080 |
self.max_red = value |
self.max_red = value |
755 |
1081 |
self.red_supp = point |
self.red_supp = point |
756 |
1082 |
else: |
else: |
757 |
1083 |
if value < self.max_red: |
if value < self.max_red: |
758 |
|
return point |
|
|
1084 |
|
#č současná normála to neseparuje. |
|
1085 |
|
#č ale možná bude nějaká jiná? |
|
1086 |
|
return self._is_one_more_point_ever_separable(point) |
759 |
1087 |
elif value < self.min_green: |
elif value < self.min_green: |
760 |
1088 |
self.min_green = value |
self.min_green = value |
761 |
1089 |
self.green_supp = point |
self.green_supp = point |
|
... |
... |
class SeparationAxis: |
767 |
1095 |
|
|
768 |
1096 |
#č takovej vzorek, který není ve skoupu |
#č takovej vzorek, který není ve skoupu |
769 |
1097 |
#č u sousedicího simplexu může být maximálně jeden |
#č u sousedicího simplexu může být maximálně jeden |
770 |
|
return None |
|
|
1098 |
|
return True |
|
1099 |
|
|
|
1100 |
|
|
|
1101 |
|
|
|
1102 |
|
|
|
1103 |
|
|
|
1104 |
|
def _is_one_more_point_ever_separable(self, non_separable_point): |
|
1105 |
|
|
|
1106 |
|
#č tady je to opakový opak |
|
1107 |
|
#č Pokud vzorek nejde separovat, tak se nesmí dostat do point_scope |
|
1108 |
|
#č V každém případě se bude pokračovat až do posledního simplexu |
|
1109 |
|
|
|
1110 |
|
#č Pokud zkoušíme separabilitu sousedícího simplexu, |
|
1111 |
|
#č tak narazíme na maximálně jeden nový vzorek. |
|
1112 |
|
#č Zbytek nového simplexu tvoří společná stěna-hyperrovina. |
|
1113 |
|
|
|
1114 |
|
|
|
1115 |
|
#č point_scope už máme |
|
1116 |
|
point_list = list(self.point_scope) |
|
1117 |
|
point_list.append(non_separable_point) |
|
1118 |
|
|
|
1119 |
|
result = self.get_separation_axis(point_list) |
|
1120 |
|
if not result.success: #č konec, zde končíme |
|
1121 |
|
if result.status != 2: # Problem appears to be infeasible. |
|
1122 |
|
print("Sense: linprog ended with status %s" % result.status) |
|
1123 |
|
#č jediné místo, kde něco do non_separable_point_set přídávame |
|
1124 |
|
self.non_separable_point_set.add(non_separable_point) |
|
1125 |
|
return False |
|
1126 |
|
|
|
1127 |
|
# sucсess! |
|
1128 |
|
#č dodáme ten diskutovaný pochybný, jíž ospravedlněný vzorek |
|
1129 |
|
self.point_scope.add(non_separable_point) |
|
1130 |
|
|
|
1131 |
|
#č hned odřízneme poslední složku - |
|
1132 |
|
#č bude tam posunutí b aka offcet aka bias |
|
1133 |
|
self._set_normal(result.x[:-1]) |
|
1134 |
|
|
|
1135 |
|
return True |
|
1136 |
|
|
|
1137 |
|
|
771 |
1138 |
|
|
772 |
1139 |
|
|
773 |
1140 |
#č přes liblinear to taky jde |
#č přes liblinear to taky jde |