Как мне работать с уравнениями, которые передаются в цели / запросе пролога?

У меня есть этот сценарий, в котором я получаю линейное уравнение в запросе Пролога, как показано ниже:

?- myquery( 3X + 5Y = 10, Result).

Поэтому мой запрос имеет уравнение 3X + 5Y = 10, которое в общем случае принимает форму AX + BY = C, где A=3, B=5 и C=10.

Теперь в моей программе прологов я пытаюсь определить предикат, который может принимать выражение, упомянутое в запросе выше. То есть я каким-то образом хочу получить значения A, B и C, а также соответствующий оператор (в вышеупомянутом случае оператор плюс), сохраненный и затем используемый в логике, которую я определяю в рамках программы. Мне интересно, как это можно сделать.

Чтобы быть более общим, вопрос заключается в том, как определить константы и операторы, участвующие в уравнении, которое передается через цель / запрос?

4 ответа

Решение

Следующая стенограмма может оказаться полезной:

32 ?- Term = (3*_X + 5*_Y = 10), functor(Term,F,A).

Term = 3*_G527+5*_G530=10
F = =
A = 2 

33 ?- Term = (3*_X + 5*_Y = 10), arg(Arg,Term,Val).

Term = 3*_G459+5*_G462=10
Arg = 1
Val = 3*_G459+5*_G462 ; % user pressed ';' interactively

Term = 3*_G459+5*_G462=10
Arg = 2
Val = 10 ; % user pressed ';' interactively

No
35 ?- Term = (3*_X + 5*_Y = 10), arg(1,Term,Val1), functor(Val1,F1,A1),
      arg(2,Val1,Val12).

Term = 3*_G693+5*_G696=10
Val1 = 3*_G693+5*_G696
F1 = +
A1 = 2
Val12 = 5*_G696 

Последний запрос гласит: для Term как дано, 1-й arg из Term является Val1функтор Val1 является F1 с остротой A1 (то есть A1 args - subparts - сама), а 2nd arg термина в Val1 хранится под Val12 название. Для пояснения, любые символические данные в Прологе имеют вид fff(aa,bb,cc,...) где fff какое-то имя, называемое functor, и "аргументы" в этом выражении могут быть доступны через arg вызов.

Это означает, что оригинальное выражение (3*_X + 5*_Y = 10) на самом деле хранится в Прологе как '='( '+'( '*'(3,_X), '*'(5,_Y)), 10), Когда вы доберетесь до атомарных частей (функторы с арностью 0), вы можете проверить их дальше:

47 ?- arg(1,(3*X),V), functor(V,F,A), number(V).

X = _G441
V = 3
F = 3
A = 0 

Yes

РЕДАКТИРОВАТЬ: чтобы ответить на ваш другой вопрос (из комментариев):

1 ?- (3*_X + 5*_Y = 10) = (A*X + B*Y = C).

A = 3
X = _G412
B = 5
Y = _G415
C = 10 

Yes

Если вы настаиваете на том, чтобы не выписывать знак умножения * в явном виде вам придется представлять свои термины в виде строк и анализировать эту строку. Это было бы гораздо более сложной задачей.

РЕДАКТИРОВАТЬ: еще одна вещь, чтобы попробовать =.. Предикат, называемый "Univ":

4 ?- (3*_X + 5*_Y = 10) =.. X.

X = [=, 3*_G454+5*_G457, 10] 

Yes
5 ?- (3*_X + 5*_Y = 10) =.. X, X=[X1,X2,X3], X2 =.. Y.

X = [=, 3*_G545+5*_G548, 10]
X1 = =
X2 = 3*_G545+5*_G548
X3 = 10
Y = [+, 3*_G545, 5*_G548] 

Yes

SWI-Prolog имеет библиотеку ограничений clp(Q,R), которая решает на символическом уровне эти уравнения:

[debug]  ?- [library(clpq)].
% library(clpq) compiled into clpq 0,27 sec, 992 clauses
true.

?- {3 * X + 5 * Y = 10}.
{Y=2-3 rdiv 5*X}.

У Eclipse наверняка будет что-то более продвинутое. Эти библиотеки не простые, жесткие...

Интересно, что в качестве основного языка используется синтаксис Prolog, поэтому обычные встроенные функции можно применять для идентификации переменных, констант и тому подобного.

Например, вы можете использовать предикаты проверки термина: arg/3, functor/3, var/1, (=..)/2 и т. Д.

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

Вот глава (минус 1 страница) из книги "Положение и эффект", которая может оказаться полезной: " Положение и эффект" - глава шестая: переписывание терминов

Другой из Искусства Пролога: передовые методы программирования 23 Решатель уравнений

Программирование в Прологе также имеет раздел (7.11) по символическому дифференцированию.

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