Продолжайте получать сообщение об ошибке "Аргументы не достаточно созданы" не могу понять, почему

Продолжайте получать ошибку Arguments are not sufficiently instantiated для умножения по правилу сложения я написал, как показано ниже.

mult(_, 0, 0).                                   %base case for multiplying by 0
mult(X, 1, X).                                   % another base case
mult(X, Y, Z) :-
   Y > 1,
   Y1 is Y - 1,
   mult(X, Y1, Z1),
   Z is X + Z1. 

Я новичок в Прологе и действительно борюсь даже с такими простыми проблемами.

Любые рекомендации для книг или онлайн-учебников были бы отличными.

Я запускаю его на SWI-Prolog в Ubuntu Linux.

2 ответа

Решение

Я думаю, что вы получили два последних звонка в обратном порядке. Разве вы не имеете в виду:

mult(X,Y,Z):- Y>1,Y1 is Y-1, Z1 is X+Z, mult(X,Y1,Z1).

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

Что касается того, почему происходит эта ошибка, мне нужно знать, как вы вызываете предикат. Можете ли вы привести пример ввода?

Правильный способ вызова вашего предиката mult(+X, +Y, ?Z):

?- mult(5,0,X).
X = 0

?- mult(5,1,X).
X = 5

?- mult(5,5,X).
X = 25

?- mult(4,4,16).
yes

?- mult(3,3,10).
no

и т. д. Вызов его со свободной переменной в первых двух аргументах вызовет эту ошибку, потому что один из них будет использоваться в правой части is или по обе стороны от < и эти предикаты ожидают, что основные условия будут успешными.

В вашем определении mult/3 первые два аргумента должны быть известны. Если один из них все еще является переменной, произойдет ошибка создания экземпляра. Например. mult(2, X, 6) приведет к ошибке инстанцирования, хотя X = 3 правильный ответ; на самом деле единственный ответ.

У вас есть несколько вариантов:

арифметика-преемник, ограничения или мета-логические предикаты.

Вот отправная точка с арифметикой преемника:

add(0,Y,Y).
add(s(X),Y,s(Z)) :- add(X,Y,Z).

Другой подход заключается в использовании ограничений на целые числа. YAP и SWI имеют library(clpfd) это можно использовать очень гибко: как для обычных целочисленных вычислений, так и для более общих ограничений. Конечно, умножение уже предопределено:

? - A * B # = C.
A * B # = С.?- A * B #= C, C = 6.
С = 6,
А в -6.. -1\/1..6,
A*B#=6,
B в -6.. -1\/1..6.?- A * B #= C, C = 6, A = 2.
А = 2,
B = 3,
С = 6.

Метатологические предикаты: я не могу рекомендовать этот вариант, в котором вы бы использовали var/1, nonvar/1, ground/1 различать разные случаи и обращаться с ними по-разному. Это настолько подвержено ошибкам, что я редко видел правильную программу, использующую их. На самом деле даже очень известные учебники содержат серьезные ошибки!

Другие вопросы по тегам