【问题标题】:How do I work with equations that are passed on in the goal/query of prolog?如何处理在 prolog 的目标/查询中传递的方程?
【发布时间】:2012-02-04 17:51:15
【问题描述】:

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

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

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

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

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

【问题讨论】:

  • 您使用的是什么 prolog 实现?看来在 swi-prolog 中你不能有你描述的形式的参数 (3X + 5Y = 10)
  • 我正在寻找 eclipse prolog,但应该没问题,我只需要正确理解概念即可。

标签: prolog predicate equation clpq


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    以下文字记录可能很有启发性:

    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 
    

    最后一个查询内容为:对于给定的TermTerm 的第一个argVal1Val1 的函子是F1 与arity A1(意思是,它有@987654329 @ args - 子部分 - 本身),并且 Val1 中术语的第二个 arg 存储在 Val12 名称下。澄清一下,Prolog 中的任何符号数据都采用fff(aa,bb,cc,...) 的形式,其中fff 是某个名称,称为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
    

    编辑:回答您的其他问题(来自 cmets):

    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
    

    【讨论】:

    • 感谢您的编辑。我现在似乎明白了逻辑。让我试试看。
    • @kallakafar 顺便说一句,如果您不知道,在 Stackoverflow 中,您可以接受一个答案,如果/您认为回答了您的问题,请点击大的空白绿色旁边的复选标记(V 形)。它会给作者一些声望点(15?)。此外,可以对答案进行“投票”,从而获得 10 分。 SO 经验的一部分。 :)
    • 是的,我确实试图支持这个答案,但后来它说我自己需要 15 分才能做到这一点,不幸的是我没有。我没有将其标记为已回答,以便我可以自己尝试一下,也许可以发布后续问题。 :) 我会的,一旦我完成了……当然!谢谢,威尔。
    • @kallakafar 我在答案中添加了更多示例代码,请查看。 :)
    • 谢谢你,@Will Ness。我仍在尝试您的解决方案,但我想我明白了您的意思。如果我还有问题,我会更新这篇文章。谢谢!
    【解决方案3】:

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

    【讨论】:

    • Umm.. 您能否详细说明如何将 3 存储在 A1、x 作为 A2、5 作为 B1、Y 作为 B2 和 10 作为 C(来自我在主要问题中给出的示例) ..?对于我引用的示例,我仍在为如何使用 arg(或就此而言 functor/3、var/1 等)而苦苦挣扎。谢谢!
    【解决方案4】:

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

    以下是《条款和效果》一书中的一章(减一页),您可能会发现它很有用: Clause and Effect - Chapter Six: Term Rewriting

    Prolog 的艺术中的另一个:高级编程技术 23 An equation solver

    Programming in Prolog 也有一节 (7.11) 关于符号微分。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-05-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-06
      • 2020-05-26
      • 1970-01-01
      相关资源
      最近更新 更多