1

我有这种情况,其中我在 Prolog 查询中得到一个线性方程,如下所示:

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

所以我的查询有一个方程 3X + 5Y = 10,它通常采用 AX + BY = C 的形式,其中 A=3、B=5 和 C=10。

现在,在我的 prolog 程序中,我试图定义一个谓词,它可以接受上面查询中提到的表达式。也就是说,我想以某种方式获取 A、B 和 C 值以及所涉及的运算符(在上述情况下为加号运算符),然后将其用于我在程序中定义的逻辑。我想知道如何做到这一点。

更通用地说,问题是我如何识别通过目标/查询传递的方程中涉及的常量和运算符?

4

4 回答 4

2

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 语法被用作宿主语言,因此可以应用通常的内置函数来识别变量、常量等。

于 2012-02-05T16:50:46.013 回答
1

以下成绩单可能证明很有启发性:

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给定的,第arg一个Termis Val1, is 的函子Val1F1arity A1(意思是,它具有A1args - 子部分 - 本身),并且arg术语 inVal1的第二个存储在Val12name 下。为了澄清,Prolog 中的任何符号数据都采用fff(aa,bb,cc,...)where fffis some name 的形式,称为functor,并且可以通过arg调用访问该表达式中的“参数”。

这意味着原始表达式(3*_X + 5*_Y = 10)实际上存储在 Prolog 中为'='( '+'( '*'(3,_X), '*'(5,_Y)), 10). 当您到达原子部分(具有 arity 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
于 2012-02-04T21:29:34.073 回答
1

例如,您可以使用术语检查谓词:arg/3、functor/3、var/1、(=..)/2 等。

于 2012-02-04T18:11:14.350 回答
0

您可能想查看使用术语重写规则实现的符号区分的示例;他们处理这样的表达。

以下是条款和效果一书中的一章(减一页),您可能会发现它很有用: 条款和效果 - 第六章:术语重写

另一个来自 Prolog 的艺术:高级编程技术 23 方程求解器

Prolog 中的编程也有一节(7.11)关于符号微分。

于 2012-02-04T20:52:48.207 回答