我正在尝试在Prolog中实现二叉树,我收到以下错误:
task unzipJar(type: Copy) {
from zipTree('commons-collections-3.2.jar')
into ("$buildDir/libs/commons-collection")
include "**/*.class"
exclude "**/Unmodifiable.class"
}
dependencies {
compile files("$buildDir/libs/commons-collection") {
builtBy "unzipJar"
}
}
我知道发生此错误是因为未正确实例化了/ 2的RHS。 但我发现很难弄清楚如何在第二个tree_eval / 3中实例化我的变量z。
ERROR: is/2: Arithmetic: `z/0' is not a function
如何在此处为z分配值?
提前致谢。
答案 0 :(得分:4)
通过z=Value
,您实际上将变量Value
与原子z
统一起来。如果你的意思是z是变量,你必须把它写成大写字母Z
,因为@vmg指出:
tree_eval(Value,tree(empty,Z,empty),Value):-
Z = Value.
在这种情况下,考虑查询谓词时会发生什么是很有趣的:
?- tree_eval(V,tree(empty,3,empty),E).
E = 3 ? ;
E = V = 3 ? ;
no
第一个解决方案是由您的第一个规则产生的,其中第一个参数有一个匿名变量。第二个解决方案是由您的第二个规则生成的,其中您要求第一个和第三个参数相同。所以基本上你有两个派生路径,两个案例中的值为3。现在让我们看一下稍微大一点的树:
?- tree_eval(V,tree(tree(empty,2,empty),+,tree(empty,3,empty)),E).
E = 5 ? ;
E = 5,
V = 3 ? ;
E = 5,
V = 2 ? ;
no
第一个答案并不令人惊讶,因为树的评估确实为5,但接下来的两个解决方案呢?让我们来看看prolog如何实现这些解决方案:术语
tree(tree(empty,2,empty),+,tree(empty,3,empty))
仅与第三个规则匹配,因为子树不为空。因此,使用子树tree(empty,2,empty)
调用tree_eval / 3并作为第一个解决方案产生:(_,tree(empty,2,empty),2)
然后使用第一个解决方案为子树tree(empty,3,empty)
调用tree_eval / 3:(_,tree(empty,3,empty),3)
现在eval(2,3,+,Eval)
会产生Eval=5
。然而,第一个论点仍然是Value=_
。因此,查询的第一个解决方案是:E=5
。
如果你要求其他答案prolog会尝试进一步解决第三个目标,确定没有,因此回溯到第二个目标:正确的子树,实际上你的第二个规则提供:(3,tree(empty,3,empty),3)
。 eval(2,3,+,Eval)
再次提供Eval=5
,因此是查询的第二个解决方案:E=5, V=3
。
如果您仍然需要更多解决方案,prolog必须进一步回溯到第一个目标:并且您的第二个规则再次提交:(2,tree(empty,2,empty),2)
。现在,您的第二个目标再次与第一个规则匹配:(_,tree(empty,3,empty),3)
,eval / 4再次传递Eval=5
,因此查询的第三个解决方案是:E=5, V=2
再次回溯到目标2 prolog再次尝试第二个规则并失败,因为第一个参数不能同时为2和3。所以查询没有第四种解决方案。
但是,如果使用相同的树结构查询tree_eval / 3但是两个叶子都是2,那么通过上述推理,有4个解决方案并不令人惊讶:
?- tree_eval(V,tree(tree(empty,2,empty),+,tree(empty,2,empty)),E).
E = 4 ? ;
E = 4,
V = 2 ? ;
E = 4,
V = 2 ? ;
E = 4,
V = 2 ? ;
no
看看这些多种解决方案,很明显你的第三个论点是提供正确的解决方案,而你并不真正需要第一个论点。你也可以不用第二条规则。结合@mat建议的一些改进,你的谓词可能看起来像这样:
tree_evaluation(tree(empty,Num,empty),Num).
tree_evaluation(tree(L,Op,R),Val) :-
tree_evaluation(L,LVal),
tree_evaluation(R,RVal),
evaluation(LVal,RVal,Op,Val).
evaluation(L,R,+,V) :-
V is L + R.
evaluation(L,R,-,V) :-
V is L - R.
evaluation(L,R,/,V) :-
V is L / R.
这个版本产生了独特的答案:
?- tree_evaluation(tree(empty,3,empty),E).
E = 3 ? ;
no
?- tree_evaluation(tree(tree(empty,2,empty),+,tree(empty,3,empty)),E).
E = 5 ? ;
no