无法通过缓存/记忆来停止 Prolog 节点的创建
Can't stop Prolog nodes creation by caching / memorizing
我如何在 Prolog 中记住树上的术语?
我认为我的推理很好,但是像换向这样的节点不断添加创建更多具有相同先前值的节点,该程序可以运行,但我想停止创建这些节点。
name(Term,X) :- Term=..[X|_].
prop(eq,commutative).
prop(and,commutative).
prop(and,associative).
prop(Op,P):-compound(Op),name(Op,Opname),prop(Opname,P).
identity(A,A). %checks if both are the same, or returns the same in any parameter
commute(A,B):- A=..[N,X,Y], B=..[N,Y,X]. %true if B is commutation of A, or B outputs commutation of A
associate(X,Y):- X=..[N,A,B],B=..[N,BA,BB], Y=..[N,C,BB],C=..[N,A,BA].
:- dynamic proofcache/1.
proof(_,Steps) :- Steps<1, !, false.
proof(eq(A,B),Steps) :- identity(A,B),writeln(["id",A,"=",B,Steps]),!,true.
proof(eq(A,B),Steps) :- prop(A,commutative), (proofcache(eq(A,B));asserta(proofcache(eq(A,B))), commute(A,R),writeln(["comm",A,"=",R,Steps]), proof(eq(R,B),Steps-1)).
proof(eq(A,B),Steps) :- prop(A,associative), (proofcache(eq(A,B));asserta(proofcache(eq(A,B))), associate(A,R),writeln(["assoc",A,"=",R,Steps]), proof(eq(R,B),Steps-1)).
示例查询:
proof( eq( and(t,and(t,f)), and(and(t,t),f) ) ,6).
显然问题是我假设分号像 C++ 代码中的 ||
一样被短路,因此即使先前的命题被评估为 false,也会评估 ;
之后的条款, 所以在 cut 运算符前面添加解决了这个问题。
由于我是该语言的新手,可能会出现更多错误,这里是解决方案的示例,writeln
消息有助于发现问题,trace
也可能有所帮助。
proof(eq(A,B),Steps) :- prop(A,commutative),
(proofcache(eq(A,B),comm), writeln(["comm was cached",eq(A,B),Steps]), !;
asserta(proofcache(eq(A,B),comm)), writeln(["comm was not cached",eq(A,B),Steps]),
commute(A,R), writeln(["comm",A,"=",R,Steps]),
proof(eq(R,B),Steps-1)).
我如何在 Prolog 中记住树上的术语?
我认为我的推理很好,但是像换向这样的节点不断添加创建更多具有相同先前值的节点,该程序可以运行,但我想停止创建这些节点。
name(Term,X) :- Term=..[X|_].
prop(eq,commutative).
prop(and,commutative).
prop(and,associative).
prop(Op,P):-compound(Op),name(Op,Opname),prop(Opname,P).
identity(A,A). %checks if both are the same, or returns the same in any parameter
commute(A,B):- A=..[N,X,Y], B=..[N,Y,X]. %true if B is commutation of A, or B outputs commutation of A
associate(X,Y):- X=..[N,A,B],B=..[N,BA,BB], Y=..[N,C,BB],C=..[N,A,BA].
:- dynamic proofcache/1.
proof(_,Steps) :- Steps<1, !, false.
proof(eq(A,B),Steps) :- identity(A,B),writeln(["id",A,"=",B,Steps]),!,true.
proof(eq(A,B),Steps) :- prop(A,commutative), (proofcache(eq(A,B));asserta(proofcache(eq(A,B))), commute(A,R),writeln(["comm",A,"=",R,Steps]), proof(eq(R,B),Steps-1)).
proof(eq(A,B),Steps) :- prop(A,associative), (proofcache(eq(A,B));asserta(proofcache(eq(A,B))), associate(A,R),writeln(["assoc",A,"=",R,Steps]), proof(eq(R,B),Steps-1)).
示例查询:
proof( eq( and(t,and(t,f)), and(and(t,t),f) ) ,6).
显然问题是我假设分号像 C++ 代码中的 ||
一样被短路,因此即使先前的命题被评估为 false,也会评估 ;
之后的条款, 所以在 cut 运算符前面添加解决了这个问题。
由于我是该语言的新手,可能会出现更多错误,这里是解决方案的示例,writeln
消息有助于发现问题,trace
也可能有所帮助。
proof(eq(A,B),Steps) :- prop(A,commutative),
(proofcache(eq(A,B),comm), writeln(["comm was cached",eq(A,B),Steps]), !;
asserta(proofcache(eq(A,B),comm)), writeln(["comm was not cached",eq(A,B),Steps]),
commute(A,R), writeln(["comm",A,"=",R,Steps]),
proof(eq(R,B),Steps-1)).