Как спросить пролог, если есть только один логический ответ

#prolog

Вопрос:

Я пытаюсь придумать запрос в Прологе, где я спрашиваю, есть ли значение, где x^2=25. Но я хочу, чтобы он возвращался yes только в том случае, если в базе знаний есть только один случай, когда x^2 равно 25.

У меня есть это в моей базе знаний:

 squared(5,25) 
squared((-5),25)
 

Я хочу, чтобы программа вернулась no , потому что есть два ответа x , где x^2=25, когда мне нужен только один.

До сих пор у меня есть это:

 squared(x,25),squared(x,25), x=x.
 

Комментарии:

1. То, что у вас внизу, что оно делает?

Ответ №1:

Вы можете использовать forall/2 следующее:

 squared(X, 25), forall(squared(Y, 25), X = Y).
 

Этот запрос выполняется успешно только в том случае, если все решения squared(X, 25) имеют одинаковое значение.

Чтобы немного уточнить:

 squared(X, 25),                 % we have a single solution, X
forall(squared(Y, 25), X = Y).  % we are asserting all solutions are equal to X
 

Если вы не знакомы с forall/2 :

forall(Condition, Action) преуспевает, если для всех альтернативных привязок Условия Действие может быть доказано. Это эквивалентно (Condition, Action) .

Таким образом, это работает для предикатов, которые имеют корни с множественностью > 1 (это может быть не то, что вы хотите, и в этом случае findall может помочь). Следующее гарантирует, что у вас есть ровно один корень:

 findall(X, squared(X, 25), [_]).
 

Давайте рассмотрим пример X^2 = 0 , который имеет двойной корень в 0:

 squared(0, 0).
squared(0, 0).
 

Так что у вас будет:

 |?- findall(X, squared(X, 0), [_]).               % check for exactly one root
no

|?- squared(X, 0), forall(squared(Y, 0), X = Y).  % same root with any multiplicity
X = 0 ? 
yes
 

Также переменные в прологе начинаются с заглавных букв (или _).

ИЗМЕНИТЬ: более оптимальный поиск

 squared(X, 25), !, forall(squared(Y, 25), X = Y).
 

Разрез после squared(X, 25) гарантирует, что мы пройдем через все корни только один раз. Если forall итерация завершается неудачно, то существует Y с squared(Y, 25) и Y = X . Поэтому нам не нужно проверять наличие каких — либо различий X .

Комментарии:

1. @DavidTonhofer : Да, нужен разрез. Иначе, если у нас будут n неравные корни, а O(n) не у нас будут O(n^2) .

2. Большое вам спасибо, это очень помогло!! Кстати, вы знаете другой способ, которым я мог бы решить эту проблему, не меняя базу знаний.

3. Как изменяется база знаний? Это все еще squared(5, 25). squared(-5, 25). так . Я только предоставил запрос squared(X, 25), forall(squared(Y, 25), X = Y).