Prolog Beginner: как объединить с помощью операторов арифметического сравнения или как получить набор переменных для диапазона значений - PullRequest
5 голосов
/ 05 июня 2010

Я новичок в Прологе. Мне нужно написать целочисленный сумматор, который сложит числа от 0-9 до других чисел 0-9 и даст решение 0-18. Вот что я хочу сделать:

% pseudo code
add(in1, in2, out) :-
    in1 < 10,
    in2 < 10,
    out < 18.

Я бы хотел назвать это так:

Чтобы проверить, действительно ли это дополнение:

?- add(1,2,3).
true.
?- add(1,2,4).
false.

С одной отсутствующей переменной:

?- add(X,2,3).
X = 1.
?- add(1,4,X).
X = 5.

С несколькими пропущенными переменными:

?- add(X,Y,Z).
% Some output that would make sense.  Some examples could be:
X=1, Y=1, Z=2 ;
X=2, Y=1, Z=3 ......

Я понимаю, что это, вероятно, довольно упрощенный вопрос, и, вероятно, он очень прост. Однако, согласно Прологу я использую:

«В отличие от операторов арифметического сравнения операторы не могут использоваться для присвоения значений переменной. Они могут быть оценены только тогда, когда были созданы все члены на каждой стороне».

Ответы [ 3 ]

6 голосов
/ 06 июня 2010

Все современные системы Prolog предоставляют конечные доменные ограничения, которые являются истинными отношениями, которые могут (в отличие от более низкоуровневых арифметических предикатов, таких как is / 2 и> / 2) использоваться во всех направлениях. В SWI-Прологе:

:- use_module(library(clpfd)).

plus(X, Y, Z) :-
        [X,Y] ins 0..9,
        X + Y #= Z.

Результаты для ваших примеров:

?- plus(1,2,3).
true.

?- plus(1,2,4).
false.

?- plus(X,2,3).
X = 1.

?- plus(1,4,X).
X = 5.

?- plus(X,Y,Z).
X in 0..9,
X+Y#=Z,
Y in 0..9,
Z in 0..18.

Поскольку предикат можно использовать во всех направлениях, больше не имеет смысла называть его «add / 3», поскольку это будет означать направление, но предикат действительно описывает, когда отношение выполняется и, таким образом, является более общим.

1 голос
/ 06 июня 2010

Что насчет этого?:

add(X,Y,Z) :-
        Z is X + Y,
        X < 10,
        Y < 10,
        Z < 19.

Проблема: это хорошо работает для запросов вида add(1,1,X), потому что Z создается до вызова <, но завершается неудачно, когда вы спрашиваете add(X,1,2). Вы могли бы использовать var/1, чтобы различать тип запроса (var/1 сообщает вам, является ли переменная необработанной или нет), но это звучит как большая боль.

0 голосов
/ 05 июня 2010

Решение:

lessThanTen(9).
lessThanTen(8).
lessThanTen(7).
lessThanTen(6).
lessThanTen(5).
lessThanTen(4).
lessThanTen(3).
lessThanTen(2).
lessThanTen(1).
lessThanTen(0).

addSimple(Add1,Add2,Sol) :-
    lessThanTen(Add1),
    lessThanTen(Add2),
    Sol is Add1+Add2.
...