8

Czy ktoś może podać prosty przykład ograniczeń dotyczących channelingu?Przykładowe ograniczenia dotyczące przesyłania danych ECLiPSe

Wiązania wiązania służą do łączenia punktów widzenia problemu z więzami. Handbook of Constraint Programming daje dobre wyjaśnienie, jak to działa i dlaczego może być użyteczne:

Zmiennymi wyszukiwania mogą być zmienne jednego z punktów widzenia, na przykład X1 (omówiono to poniżej). Po przeprowadzeniu wyszukiwania, rozprzestrzenianie się więzów C1 usuwa wartości z domen zmiennych w X1. Ograniczenia channelingu mogą następnie umożliwić usunięcie wartości z domen zmiennych w X2. Propagowanie tych delecji wartości przy użyciu ograniczeń C2, C2, może usunąć dalsze wartości z tych zmiennych i ponownie te przeniesienia z powrotem do pierwszego punktu widzenia mogą być przekształcone przez ograniczenia kanałowe. Wynik netto może być taki, że więcej wartości zostanie usuniętych w punkcie widzenia V1 niż samym ograniczeniu, co prowadzi do skrócenia wyszukiwania.

Nie rozumiem, w jaki sposób jest to realizowane. Jakie dokładnie są te ograniczenia, jak wyglądają w prawdziwym problemie? Prosty przykład byłby bardzo pomocny.

+3

Ładne pytanie! Podręcznik zawiera ponad 900 stron, nie mogę znaleźć akapitu, który cytujesz. Czy możesz podać podpowiedź? – CapelliC

+0

@CapelliC Cholera, lepiej późno niż wcale, strona 392 na dole. – Stanko

Odpowiedz

4

Jak stwierdzono w Podwójne heurystyki widzenia dla Problemów satysfakcji Binary Ograniczenie (PA Geelen):

kanalizowania ograniczeń dwóch różnych modeli pozwala na wyrażanie relacji między dwoma zbiorami zmiennych, po jednym każdego Model.

Oznacza to zadania w jednym z punktów widzenia, może być tłumaczony na zadania w drugiej i vice versa, jak również, gdy inicjuje wyszukiwanie, wartości wykluczone z jednego modelu można wykluczyć od siebie, jak również.

Pozwól mi rzucić przykład, który zaimplementowałem jakiś czas temu, pisząc narzędzie do rozwiązywania sudoku.

klasyczny punkt widzenia

Tu zinterpretować ten problem w taki sam sposób człowiek będzie: za pomocą liczby całkowite od 1 do 9 i definicji, że wszystkie wiersze, kolumny i bloki musi zawierać każdą liczbę całkowitą dokładnie raz.

Możemy łatwo stwierdzić to w Eclipse przy użyciu coś jak:

% Domain 
dim(Sudoku,[N,N]), 
Sudoku[1..N,1..N] :: 1..N 

% For X = rows, cols, blocks 
alldifferent(X) 

I to jest jeszcze wystarczające, aby rozwiązać zagadkę Sudoku.

Binary logiczna widzenia

Można by jednak wybrać do reprezentowania liczb całkowitych przez ich binarnych tablic logicznych (pokazanych w answer przez @jschimpf). W przypadku, gdy nie jest jasne, co to jest, za mały przykład poniżej (jest to wbudowany w funkcjonalności!):

?­ ic_global:bool_channeling(Digit, [0,0,0,1,0], 1). 
    Digit = 4 
    Yes (0.00s cpu) 
?­ ic_global:bool_channeling(Digit, [A,B,C,D], 1), C = 1. 
    Digit = 3 
    A = 0 
    B = 0 
    C = 1 
    D = 0 
    Yes (0.00s cpu) 

Jeśli użyjemy tego modelu do reprezentowania Sudoku, każdy numer zostanie zastąpiony przez jego binarnej wartości logicznej tablica i odpowiednie ograniczenia mogą być zapisane.Będąc trywialnym dla tej odpowiedzi, nie będę zawierał całego kodu dla ograniczeń, ale ograniczenie pojedynczej sumy wystarczy, aby rozwiązać zagadkę sudoku w jej binarnej reprezentacji boolowskiej.

Channeling

Mając te dwa punkty widzenia z odpowiednimi ograniczonych modeli daje teraz możliwość kanał między nimi i sprawdzić, czy wszelkie ulepszenia zostały wykonane.

Ponieważ oba modele są nadal tylko płytą NxN, nie ma różnicy w wymiarze reprezentacji, a channeling staje się naprawdę łatwy.

Pozwól mi najpierw dać ostatni przykład co blok wypełniony liczbami całkowitymi 1..9 będzie wyglądać w obu naszych modeli:

% Classic viewpoint 
1 2 3 
4 5 6 
7 8 9 

% Binary Boolean Viewpoint 
[](1,0,0,0,0,0,0,0,0) [](0,1,0,0,0,0,0,0,0) [](0,0,1,0,0,0,0,0,0) 
[](0,0,0,1,0,0,0,0,0) [](0,0,0,0,1,0,0,0,0) [](0,0,0,0,0,1,0,0,0) 
[](0,0,0,0,0,0,1,0,0) [](0,0,0,0,0,0,0,1,0) [](0,0,0,0,0,0,0,0,1) 

Teraz wyraźnie widać związek między modelami i po prostu napisz kod, aby skierować nasze zmienne decyzyjne. Korzystanie Sudoku i BinBools jako naszych płyt, kod będzie wyglądał mniej więcej tak:

(multifor([Row,Col],1,N), param(Sudoku,BinBools,N) 
do 
    Value is Sudoku[Row,Col], 
    ValueBools is BinBools[Row,Col,1..N], 
    ic_global:bool_channeling(Value,ValueBools,1) 
). 

W tym momencie mamy przekazywany model, w którym, w trakcie poszukiwań, jeśli wartości są oczyszczone w jednym z modeli, jego wpływ nastąpi również w drugim modelu. To może oczywiście prowadzić do dalszej ogólnej propagacji ograniczeń.

Rozumowanie

Aby wyjaśnić przydatność binarnym modelu logicznego dla Sudoku, musimy najpierw rozróżnić niektórych przewidzianych alldifferent/1 wdrożeń przez Eclipse:

Reasoning of alldifferent/1

Co to oznacza w praktyka może być pokazana w następujący sposób:

?­ [A, B, C] :: [0..1], ic:alldifferent([A, B, C]). 
    A = A{[0, 1]} 
    B = B{[0, 1]} 
    C = C{[0, 1]} 
    There are 3 delayed goals. 
    Yes (0.00s cpu) 

?­ [A, B, C] :: [0..1], ic_global:alldifferent([A, B, C]). 
    No (0.00s cpu) 

Ponieważ nie było jeszcze żadnych przydziałów przy użyciu sprawdzania przekazywania (biblioteka ic), nieważność kwerendy nie została jeszcze wykryta, natomiast wersja zgodna Bound natychmiast to zauważa. Takie zachowanie może prowadzić do znacznych różnic w propagacji ograniczeń podczas przeszukiwania i przechodzenia przez mocno ograniczone modele.

Na górze tych dwóch bibliotek znajduje się biblioteka ic_global_gac przeznaczona do globalnych ograniczeń, dla których zachowana jest uogólniona spójność łuku (nazywana również konsystencją hiper łuku lub spójnością domeny). To wyjątkowe ograniczenie/1 zapewnia jeszcze więcej możliwości przycinania niż spójne, jednoznaczne, , ale zachowanie pełnej spójności domeny ma swój koszt, a korzystanie z tej biblioteki w mocno ograniczonych modelach generalnie prowadzi do utraty wydajności działania.

Z tego powodu odkryłem, że interesująca dla Sudoku jest próba pracy z spójną (ic_global) implementacją alldifferent w celu zmaksymalizowania wydajności, a następnie samodzielne podejście do spójności domeny przez channeling binarnego modelu boolowskiego.

Experiment results

Poniżej znajdują się wyniki BackTrack dla Sudoku 'platinumblonde' (wskazanej jako najtrudniejszy, najbardziej chaotyczny Sudoku łamigłówka do rozwiązania w The Chaos Within Sudoku, M. i Z. Toroczkai ErcseyRavasz), stosując odpowiednio naprzód sprawdzenie, spójność granic, spójność domeny, autonomiczną binarnego modelu logiczną i wreszcie, kierowane model:

 (ic) (ic_global) (ic_global_gac) (bin_bools) (channelled) 
BT 6 582  43    29    143   30 

Jak widać, nasza kierowana modelu (przy użyciu Granice obszaru spójności (ic_global)) musi jeszcze jeden backtrack więcej niż spójna implementacja domeny, ale zdecydowanie działa lepiej niż samodzielna wersja spójna.

Kiedy przyjrzymy się teraz czasowi działania (wyniki są wynikiem obliczenia średniej z wielu wykonań, aby uniknąć ekstremów), z wyjątkiem sprawdzania sprawdzania postępu, ponieważ udowodniono, że nie jest już interesujący w rozwiązywaniu zagadek sudoku:

  (ic_global) (ic_global_gac) (bin_bools) (channelled) 
Time(ms)  180ms   510ms   100ms  220ms 

Patrząc na te wyniki, myślę, że możemy z powodzeniem zakończyć eksperyment (wyniki te zostały potwierdzone przez ponad 20 innych przypadkach Sudoku):

Channeling binarne logiczną punkt widzenia na granicach zgodne autonomicznych Implementacja zapewnia nieco mniej silne propagowanie ograniczeń niż w przypadku samodzielnej implementacji w domenie, ale z czasem działania od równie długiego do znacznie szybszego.

EDIT: Próba wyjaśnienia

Wyobraźmy sobie pewną domenę zmienną reprezentującą komórkę na pokładzie Sudoku posiada pozostały domenę 4..9. Wykorzystując spójność granic, gwarantuje się, że zarówno dla wartości 4, jak i 9 można znaleźć inne wartości domeny, które spełniają wszystkie ograniczenia, a tym samym zapewniają spójność. Jednak nie ma wyraźnej gwarancji na inne wartości w domenie (taka jest "spójność domeny").

Korzystanie binarny logiczną modelu, definiujemy dwa następujące ograniczenia Suma:

  • Suma wszystkich binarnym logicznej tablicy jest zawsze równa 1
  • Suma każdego elementu N'th każdej tablicy w każdym wierszu/col/block jest zawsze równy 1

Dodatkowa siła wiązania jest egzekwowana przez drugie ograniczenie, które oprócz ograniczania wiersza, kolumn i bloków również domyślnie mówi: "każda komórka może zawierać tylko co cyfra jeden raz ". To zachowanie nie jest aktywnie wyrażane, gdy stosuje się tylko granice spójne alldifferent/1 constraint!

Wnioski

Oczywiste jest, że skierowanie może być bardzo przydatne do poprawy autonomicznego ograniczony model, jednak czy nowy model jest ograniczenie się wytrzymałości jest słabszy niż w obecnym modelu, oczywiście, żadnych ulepszeń będzie być zrobione. Zauważ też, że posiadanie bardziej ograniczonego modelu nie musi koniecznie oznaczać ogólnej lepszej wydajności!Dodanie większej liczby ograniczeń zmniejszy ilość backtracków potrzebnych do rozwiązania problemu, ale może również wydłużyć czas działania programu, jeśli konieczne będzie więcej sprawdzeń ograniczeń.

+1

Świetne napisy, +1! Dziękujemy za dodanie tych przykładów. – mat

1

Oto prosty przykład, pracuje w SWI-Prolog, ale powinien również pracować w Eclipse Prolog (w później trzeba użyć (::)/2 zamiast (in)/2):

Wiązanie C1:

?- Y in 0..100. 
Y in 0..100. 

Ograniczenie C2:

?- X in 0..100. 
X in 0..100. 

pośredni Wiązanie:

?- 2*X #= 3*Y+5. 
2*X#=3*Y+5. 

Wszystko razem:

?- Y in 0..100, X in 0..100, 2*X #= 3*Y+5. 
Y in 1..65, 
2*X#=3*Y+5, 
X in 4..100. 

więc ograniczenie kanału działa w obu kierunkach, to zmniejsza domenę C1 oraz domenę C2.

Niektóre systemy używają metod iteracyjnych, w wyniku czego ten channeling może zająć trochę czasu, tutaj jest przykładem, który potrzebuje około 1 minutę, aby obliczyć w SWI-Prolog:

?- time(([U,V] ins 0..1_000_000_000, 36_641*U-24 #= 394_479_375*V)). 
% 9,883,559 inferences, 53.616 CPU in 53.721 seconds 
(100% CPU, 184341 Lips) 
U in 346688814..741168189, 
36641*U#=394479375*V+24, 
V in 32202..68843. 

Z drugiej strony zaćmienie Prolog ręka robi to w mgnieniu:

[eclipse]: U::0..1000000000, V::0..1000000000, 
       36641*U-24 #= 394479375*V. 
U = U{346688814 .. 741168189} 
V = V{32202 .. 68843} 
Delayed goals: 
    -394479375 * V{32202 .. 68843} + 
    36641 * U{346688814 .. 741168189} #= 24 
Yes (0.11s cpu) 

Bye

+1

Podanie jakiegoś arbitralnego przypadku do porównania nie daje dużego wglądu. Weź "2 # = 3 * (A + A * A)." Czy nadal jest zapętlony w ECLiPSe? Dodaj dekoracje zgodnie z Twoim wyobrażeniem. – false

+2

Dobra właściwość w 'clpfd' użytkownika SWI: Zawsze się kończy. I owszem, czasami oznacza to czekanie, aż nasz wszechświat się rozpadnie, i będzie odnosił się do czasu X-lecia: "abs (X) # <7^7^7, X * X # false

+0

W Jekejeke Minlog wszystko to nigdy się nie zdarza, ponieważ nie zaimplementowałem dwukierunkowego channelingu, tylko channeling kierunkowy: http://jekejeke.ch/idatab/doclet/prod/en/docs/15_min/10_docu/02_reference/07_theory/03_finite/02_set.html –

3

kanalizowania ograniczenia są stosowane, gdy w modelu aspekty problemu są reprezentowane na więcej niż jeden sposób. Są one następnie konieczne do zsynchronizowania tych wielu reprezentacji, nawet jeśli same nie modelują aspektu problemu.

Zwykle podczas modelowania problemu z ograniczeniami istnieje kilka sposobów wybierania zmiennych.Na przykład, w problemie szeregowania, można zdecydować się na

  • zmienną całkowitą dla każdego zadania (ze wskazaniem, które maszyna spełnia swoje zadanie)
  • zmienną całkowitą dla każdego urządzenia (ze wskazaniem, które zadanie to wykonuje)
  • matrycy wartości logicznych (ze wskazaniem, które uruchamia zadanie, w którym maszyna)
  • lub coś bardziej egzotyczne

W dość proste problemu wybrać reprezentację, która sprawia, że ​​najłatwiej formu spóźnione ograniczenia problemu. Jednak w rzeczywistych problemach z wieloma heterogenicznymi ograniczeniami często niemożliwe jest znalezienie takiej jednej najlepszej reprezentacji: niektóre ograniczenia najlepiej reprezentuje jeden typ zmiennej, a inne - inny.

W takich przypadkach można użyć wielu zestawów zmiennych i sformułować poszczególne ograniczenia problemu za pomocą najwygodniejszego zestawu zmiennych. Oczywiście, wtedy kończy się wiele niezależnych podproblemów, a ich rozwiązanie w izolacji nie da ci rozwiązania dla całego problemu. Ale przez dodanie ograniczeń dotyczących kanałów zestawy zmiennych mogą być zsynchronizowane, a podproblemy w ten sposób ponownie połączone. Wynik jest wtedy prawidłowym modelem dla całego problemu.

Jak wskazano w cytacie z podręcznika, w takim sformułowaniu wystarczy przeszukiwanie tylko jednego ze zbiorów zmiennych ("punktów widokowych"), ponieważ wartości pozostałych są implikowane przez ograniczenia channelingu.

Niektóre powszechne przykłady skierowanie dwóch reprezentacje:

zmiennej całkowitej i zakres wartości logicznych: Rozważmy zmiennej całkowitej T co wskazuje szczelinę czasową 1..N gdy zdarzenie ma miejsce, a tablica Booleans tak, że Bs[T] = 1 iff wydarzenie odbywa się w przedziale czasowym T. W Eclipse:

T #:: 1..N, 
    dim(Bs, [N]), Bs #:: 0..1, 

kanalizowania pomiędzy dwoma reprezentacjami można następnie skonfigurować z

(for(I,1,N), param(T,Bs) do Bs[I] #= (T#=I)) 

która będzie propagować informacji zarówno sposoby, między T i Bs. Innym sposobem implementacji tego channelingu jest ograniczenie celu specjalnego o nazwie bool_channeling/3.

zmienne Start/End całkowitymi i Array logicznych (harmonogramem): Mamy zmiennych całkowitych S,E wskazujący czas rozpoczęcia i zakończenia działalności. Z drugiej strony tablica Booleans taka, że ​​Bs[T] = 1 iff działanie ma miejsce w czasie T.W Eclipse:

[S,E] #:: 1..N, 
    dim(Bs, [N]), Bs #:: 0..1, 

Channeling można osiągnąć poprzez

(for(I,1,N), param(S,E,Bs) do Bs[I] #= (S#=<I and I#=<E)). 

podwójnej reprezentacji zmiennych Praca/Maszyna całkowitych: Tutaj Js[J] = M Oznacza to zadanie J jest wykonywany na maszynie M, podczas podwójnej formułowania Ms[M] = J oznacza, że ​​maszyna M wykonuje zadanie J

dim(Js, [NJobs]), Js #:: 0..NMach, 
    dim(Ms, [NMach]), Ms #:: 1..NJobs, 

i rozprowadzanie uzyskuje się poprzez

(multifor([J,M],1,[NJobs,NMach]), param(Js,Ms) do 
     (Js[J] #= M) #= (Ms[M] #= J) 
    ). 

Ustaw zmienną i zakres wartości logicznych: Jeśli używasz solver (takich jak library(ic_sets)), które można bezpośrednio obsługiwać konfiguracji zmienne, mogą one znaleźć odzwierciedlenie w tablica bajtów wskazująca na przynależność elementów do zestawu. Biblioteka zapewnia w tym celu dedykowane ograniczenie membership_booleans/2.