Почему мое правило не может решить для X в простом алгебраическом уравнении?

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

Это мое правило:

solve(X) :- A = B, A is (7 * (X - 2)), B is (3 * (X + 4)).

Очевидно, правильный ответ здесь 6.5, Если я передам это Прологу, это подтвердит:

| ?- solve(6.5).

yes

Однако, если я попрошу Пролог сделать грязную работу, он выдаст ошибку:

| ?- solve(X).
uncaught exception: error(instantiation_error,(is)/2)

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

3 ответа

Решение

Для этого вы можете использовать библиотеку, доступную как минимум в SWI-Prolog: library(clpr) и library(clpq).

Вот с верхнего уровня для Реалов:

?- use_module(library(clpr)).
true.

?- {7 * (X - 2) = 3 * (X + 4)}.
X = 6.5 ;
false.

Или, если вы используете Rationals:

?- use_module(library(clpq)).
true.

?- {7 * (X - 2) = 3 * (X + 4)}, R is float(X).
X = 13 rdiv 2,
R = 6.5.

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

...,
(   ground(X)
->  7 * (X - 2) =:= 3 * (X + 4)
;   X is (3*4 + 2*7) / (7 - 3)
),
...

Кстати, что вы делаете: A = B, A is ..., B is ..., Это немного опасно, например:

?- A = B, A is 3 - 2, B is sin(pi/2).
false.

?- 3 - 2 =:=  sin(pi/2).
true.

3 - 2 оценивает в целое число 1; затем, sin(pi/2) вычисляется до числа с плавающей точкой 1.0, и это не объединяется с целым числом 1. Итак, первый запрос не выполняется!

?- 1 = 1.0.
false.

В Прологе is является оператором арифметической оценки. Он вычисляет результат выражения с правой стороны и присваивает его переменной с левой стороны.

Выражение, которое должно быть оценено, должно содержать только числа и арифметические операторы / функции. Другими словами, чтобы оценить выражение, is уже должен знать все цифры в нем.

Еще один способ сказать, что это is является "однонаправленным", в отличие от = который является двунаправленным. Что ты и ожидал. И это означает ошибку, которую вы получили.

Решение таких уравнений - ограничений - это работа для решения ограничений.

Пролог работает путем объединения. Он пытается сделать структуры одинаковыми.

Так, например, если я попытаюсь унифицировать [3, X, 5] с [3, 4, 5] это прекрасно работает и X = 4,

В своем коде вы сначала говорите A = B, Это нормально, как изначально A а также B не созданы, так что вы в основном связываете их судьбы друг с другом - если A позже создается тогда B автоматически тоже или наоборот.

Тогда вы продолжаете спрашивать A is (7 * (X - 2)), Теперь, если вы уже объединились X с 6.5 тогда это можно оценить - A затем объединяется с 7 * (6.5 - 2) или же 31.5, Но помни это A был уже объединен с B, так B сейчас также 31.5,

Теперь вы говорите B is (3 * (X + 4)), Так с X объединено в 6.5 а также B объединенный с 31.5 это так же, как 31.5 is (3 * (6.5 + 4)), Правая сторона 31.5 так что это 31.5 is 31.5 что является правдой.

Итак, решение для solve(6.5) работает.

Однако, если вы попытаетесь решить для X тогда первый предикат работает просто отлично. Но второй нет. Это как я спрашиваю: "Сколько раз в 7 раз меньше числа, о котором я думаю?" Если я не скажу вам число, о котором я думаю, вы не сможете дать мне ответ. То же самое для Пролога. Он застревает и сообщает об ошибке.

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