Prolog Beginner: как объединиться с операторами арифметического сравнения или как получить переменную set для диапазона значений

Я новичок в Prolog. Мне нужно написать целочисленный сумматор, который добавит числа от 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 ......

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

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


person sixtyfootersdude    schedule 05.06.2010    source источник


Ответы (3)


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

:- 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», поскольку это означало бы направление, но предикат действительно описывает, когда отношение выполняется, и, таким образом, является более общим.

person mat    schedule 06.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 сообщает вам, является ли переменная неинтересной или нет), но это звучит очень болезненно.

person Frank Shearar    schedule 05.06.2010
comment
Да, это не работает из-за того, что вы описали в своем ответе. - person sixtyfootersdude; 06.06.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.
person sixtyfootersdude    schedule 05.06.2010