Otrzymałem zadanie, aby rozwiązać zagadkę zebry za pomocą wybranego przeze mnie narzędzia ograniczającego, a spróbowałem go używając Prolog clpfd library.Układanie puzzle Zebra (aka puzzle Einsteina) przy pomocy biblioteki clpfd Prolog
Mam świadomość, że istnieją inne, bardziej idiomatyczne sposoby rozwiązania tego problemu w Prologu, ale to pytanie dotyczy pakietu clpfd
!
Tak specyficzna odmiana puzzli (biorąc pod uwagę, że istnieje wiele z nich) próbuję rozwiązać jest to jedno:
Istnieje pięć domów
- życiu Englishman w czerwonym domu
- szwedzka właścicielem psa
- Duński lubi pić herbatę
- zielona h ouse pozostało do białego domu
- Właściciel zielonego napojów kawiarni
- Osoba, która pali Pall Mall posiada ptaka
- mleko jest pijany w środku domu
- Właściciel żółtego domu pali Dunhill
- Norweg mieszka w pierwszym domu
- palacz Marlboro mieszka obok właściciela kota
- Właściciel konia mieszka obok osoby, która pali Dunhill
- The Winfield palacz lubi pić piwo
- Norweg mieszka obok niebieskiego domu
- niemieckiego pali rothmanns
- Marlboro palacz ma sąsiada, który pije wodę
próbowałem go rozwiązać z następujące podejście:
Each attribute a house can have is modeled as a variable, e.g. "British", "Dog", "Green", etc. The attributes can take values from 1 to 5, depending on the house in which they occur, e.g. if the variable "Dog" takes the value 3, the dog lives in the third house.
Takie podejście ułatwia modelowanie ograniczeń sąsiada tak:
def neighbor(X, Y) :-
(X #= Y-1) #\/ (X #= Y+1).
Ale jakoś, pakiet clpfd
nie przynosi rozwiązanie, choć (IMO) problem wzorowany jest poprawnie (użyłem dokładnie tego samego modelu z Choco constraint solver a wynik był prawidłowy).
Oto kompletny kod:
:- use_module(library(clpfd)).
neighbor(X, Y) :-
(X #= (Y - 1)) #\/ (X #= (Y + 1)).
solve([British, Swedish, Danish, Norwegian, German], Fish) :-
Nationalities = [British, Swedish, Danish, Norwegian, German],
Colors = [Red, Green, Blue, White, Yellow],
Beverages = [Tea, Coffee, Milk, Beer, Water],
Cigarettes = [PallMall, Marlboro, Dunhill, Winfield, Rothmanns],
Pets = [Dog, Bird, Cat, Horse, Fish],
all_different(Nationalities),
all_different(Colors),
all_different(Beverages),
all_different(Cigarettes),
all_different(Pets),
Nationalities ins 1..5,
Colors ins 1..5,
Beverages ins 1..5,
Cigarettes ins 1..5,
Pets ins 1..5,
British #= Red, % Hint 1
Swedish #= Dog, % Hint 2
Danish #= Tea, % Hint 3
Green #= White - 1 , % Hint 4
Green #= Coffee, % Hint 5,
PallMall #= Bird, % Hint 6
Milk #= 3, % Hint 7
Yellow #= Dunhill, % Hint 8,
Norwegian #= 1, % Hint 9
neighbor(Marlboro, Cat), % Hint 10
neighbor(Horse, Dunhill), % Hint 11
Winfield #= Beer, % Hint 12
neighbor(Norwegian, Blue), % Hint 13
German #= Rothmanns, % Hint 14,
neighbor(Marlboro, Water). % Hint 15
Czy ja rozumieją pojęcie zasięgu clpfd
, albo ja po prostu brakuje czegoś oczywiste tutaj? Jeśli to pomoże, here można znaleźć takie samo podejście realizowane za pomocą Choco i Scala.
Edit: Powodem dlaczego uważam, że Solver nie jest w stanie rozwiązać problemu ist że nigdy nie wyjdzie z określonych wartości dla zmiennych, ale tylko z zakresami, np "Ryba 1..3 \/5".
Użyj etykiety (Vars) lub etykietowania (Options, Vars) tro rozwiązać problem. – joel76
"Etykieta" działa tylko wtedy, gdy istnieje określony wynik, natomiast to, co otrzymuję dla każdej zmiennej, to tylko zakresy (jak wyjaśniono w edycji). – fresskoma
Jeśli twój CLP (FD) miałby "Expr in Set", wtedy można sformalizować sąsiada (X, Y): - X - Y w [-1,1]. –