Мне было интересно, можно ли в прологе заставить его переборщить все возможные вычисления для чего-то вроде этого:
6 is Z + Q
Z = 1 Q = 5
Z = 2 Q = 4
Z = 3 Q = 3
Мне было интересно, можно ли в прологе заставить его переборщить все возможные вычисления для чего-то вроде этого:
6 is Z + Q
Z = 1 Q = 5
Z = 2 Q = 4
Z = 3 Q = 3
Подход «генерируй и тестируй» также работает. Конечно, вам все еще нужны некоторые ограничения, например:
?- between(1, 6, X), % X is an integer between 1 and 6
between(1, 6, Y), % Y is an integer between 1 and 6
X =< Y, % X is not larger than Y
X + Y =:= 6. % the sum is 6
X = 1, Y = 5 ;
X = 2, Y = 4 ;
X = Y, Y = 3 ;
false.
Порядок подзапросов имеет значение, так что вы могли бы также назвать его «сгенерировать-затем-тестировать». Если вы не боитесь жестко закодировать некоторые ограничения, могут быть способы избежать генерации некоторых значений и сделать некоторые тесты ненужными, например:
?- between(1, 6, X), % X is an integer between 1 and 6
between(X, 6, Y), % Y is an integer between X and 6
X + Y =:= 6. % the sum is 6
X = 1, Y = 5 ;
X = 2, Y = 4 ;
X = Y, Y = 3 ;
false.
Вы должны понимать, что пойти по этому пути достаточно далеко — это примерно то же самое, что реализовать решатель ограничений, такой как, например, CLP (FD).
Я предлагаю использовать, если ваш Пролог поддерживает его, решатель конечной области.
Я обычно использую GProlog, и я могу получить то, что вы просите, с помощью чего-то вроде
fd_domain([A, B], 1, 100),
6 #= A + B,
fd_labeling([A, B]),
где fd_domain/3
задает домен для переменных A
и B
(от 1
до 100
), 6 #= A + B
задает ограничение (A + B
равно 6) и fd_labelling/1
получает все возможные вычисления.
В Swi-Prolog немного иначе.
Прежде всего, вы должны загрузить библиотеку CLP(FD) с помощью
:- use_module(library(clpfd)).
Чтобы установить переменные и домен, вы можете написать
Vars = [A, B],
Vars ins 1..100,
Установка ограничения равна
6 #= A + B,
и чтобы получить все возможные комбинации, вы можете написать
label(Vars),