Почему мое правило не может решить для 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 раз меньше числа, о котором я думаю?" Если я не скажу вам число, о котором я думаю, вы не сможете дать мне ответ. То же самое для Пролога. Он застревает и сообщает об ошибке.