Math Prolog给定x的所有可能表达式

Math Prolog给定x的所有可能表达式,math,prolog,logic,dcg,arithmetic-expressions,Math,Prolog,Logic,Dcg,Arithmetic Expressions,我有一个具有给定语法的prolog程序: sum --> [+], mult, sum | mult | num. mult --> [*], num, xer. xer --> [x] | [^], [x], num. num --> [2] | [3] ... etc 我的表达式有一个抽象的树表示。例如:mul(num(2),var(x))等于[*,2,x]是有效的。 我希望能够创建满足给定x和解的所有表达式。使用 allExpressions(Tree, X, S

我有一个具有给定语法的prolog程序:

sum --> [+], mult, sum | mult | num.
mult --> [*], num, xer.
xer --> [x] | [^], [x], num.
num --> [2] | [3] ... etc
我的表达式有一个抽象的树表示。例如:
mul(num(2),var(x))
等于
[*,2,x]
是有效的。 我希望能够创建满足给定x和解的所有表达式。使用

allExpressions(Tree, X, Solution).
例如:

?- allExpressions(Tree, 2, 6)
Tree = mul(num(3),x)
Tree = sum(num(2),mul(num(2),var(x))
etc.
根据我的语法,这显然不是一个无限的方程组。 我已经编写了一个
评估(Tree,X,Solution)
,它计算给定X变量的答案。所以我需要帮助的是为给定的x变量和解生成可能的方程组


对我如何处理这个问题有什么想法吗?谢谢

这很简单:因为所有的算术运算只能增加表达式的值,所以在搜索解时限制深度很简单。简单地归纳描述解决方案的外观。例如,您可以使用SWI Prolog的有限域加法和乘法约束来执行此操作,如下所示:

:- use_module(library(clpfd)).

expression(var(x), X, X).
expression(num(N), _, N) :- phrase(num, [N]).
expression(mul(A,B), X, N) :-
        N1 * N2 #= N,
        N1 #> 1,
        N2 #> 1,
        expression(A, X, N1),
        expression(B, X, N2).
expression(sum(A,B), X, N) :-
        N1 + N2 #= N,
        N1 #> 1,
        N2 #> 1,
        expression(A, X, N1),
        expression(B, X, N2).
我把其他操作留作练习

示例查询和一些结果:

?- expression(Tree, 2, 6).
Tree = mul(var(x), num(3)) ;
Tree = mul(num(2), num(3)) ;
    [...solutions omitted...]
Tree = sum(num(2), mul(num(2), var(x))) ;
Tree = sum(num(2), mul(num(2), num(2))) ;
    [...solutions omitted...]
Tree = sum(sum(num(2), num(2)), num(2)) ;
false.

+1用于对表达式树使用干净、非默认的表示(
var(x)
num(N)
等),它允许您在进行推理时使用模式匹配。

感谢您给出了一个很好的答案,这似乎非常符合逻辑。但是,在实现此操作时,
?-expression(Tree,2,6)。
只给我一个答案
Tree=num(6)。
我使用了附加的[^]运算符实现。知道我做错了什么吗?事实上,-Tree=mult(var(x),num(3))是我唯一得到的,请在编辑中检查我的代码!您可能没有使用SWI Prolog的最新git版本。对于旧版本,必须将约束
N1#
添加到求幂子句中,以使约束解算器知道
N1
小于
N
。在最近的版本中,它不再需要这个提示,而是自己推断出来的。一旦您将此附加约束添加到上一个子句中或升级SWI版本,它就应该适用于您。如下所述,它可以根据需要使用更新版本的SWI Prolog。要使其适用于旧版本,请在求幂子句的前几行中添加约束
N1#
。@mat我添加了这一行,但对于每个测试用例,我的输出仍然只有一行。你觉得有什么不对吗?另外,你知道一个简单的方法让num对所有大于等于2的整数都有效,而不是像2 | 3 | 4 | 5那样声明它们。。。等等?它适用于我的SWI>=6.5.2以及您现在显示的代码。当然,在第一个解决方案之后,您必须按空格以获取其他解决方案。你可以很容易地用
num-->[N],{between(2,5,N)}来描述DCG中的具体整数。
。非常感谢,我的错误是在我表示num的方式上,between工作得很好!