Мне дали задание решить головоломку с зеброй, используя решатель ограничений по моему выбору, и я попробовал его, используя библиотеку Prolog clpfd.
Я знаю, что есть и другие, более идиоматические способы решения этой проблемы в Прологе, но этот вопрос конкретно касается пакета clpfd
!
Итак, конкретный вариант головоломки (учитывая, что их много), который я пытаюсь решить, таков:
Есть пять домов
Я пытался решить ее следующим образом:
Каждый атрибут, который может иметь дом, моделируется как переменная, например "британский", "Собака", "Зеленый" и т.д. Атрибуты могут принимать значения от 1 до 5, в зависимости от дома в котором они происходят, т.е. если переменная «Собака» принимает значение 3, то собака живет в третий дом.
Этот подход упрощает моделирование ограничений соседей следующим образом:
def neighbor(X, Y) :-
(X #= Y-1) #\/ (X #= Y+1).
Но каким-то образом пакет clpfd
не дает решения, хотя (IMO) проблема смоделирована правильно (я использовал точно такая же модель с решателем ограничений Choco, и результат был правильным).
Вот полный код:
:- 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
Я неправильно понял концепцию в clpfd
, или я просто упустил что-то очевидное? Если это поможет, здесьвы можете найти тот же подход, реализованный с использованием Choco и Scala.
Редактировать: Причина, по которой я считаю, что решатель не может решить проблему, заключается в том, что он никогда не дает определенных значений для переменных, а только с диапазонами, например. «Рыба 1..3/5».