Prolog 用一个变量替换另一个变量
给定一个列表列表,我想替换Prolog 用一个变量替换另一个变量,prolog,Prolog,给定一个列表列表,我想替换Bs中的所有as,其中a和B是prolog变量 例如,如果列表是[[1,2,D,C],[A,D],[4,A],[1,2,A]] 我希望结果是[[1,2,D,C],[B,D],[4,B],[1,2,B]] 为此,我编写了以下内容,以替换单个列表中Bs中的所有As: /*substitude_single(+OldVar,+NewVar,+OldList,-NewList) */ substitute_single(_,_,[],[]). substitute_singl
B
s中的所有a
s,其中a
和B
是prolog变量
例如,如果列表是[[1,2,D,C],[A,D],[4,A],[1,2,A]]
我希望结果是[[1,2,D,C],[B,D],[4,B],[1,2,B]]
为此,我编写了以下内容,以替换单个列表中B
s中的所有A
s:
/*substitude_single(+OldVar,+NewVar,+OldList,-NewList) */
substitute_single(_,_,[],[]).
substitute_single(A,B,[A|As],[B|Bs]):-
substitute_single(A,B,As,Bs).
substitute_single(A,B,[X|As],[X|Bs]):-
substitute_single(A,B,As,Bs).
现在我把它应用到主列表的每个元素上,它本身就是一个列表:
substitute(_,_,[],[]).
substitute(A,B,[P|Ps],[Q|Qs]):-
substitute_single(A,B,P,Q),
substitute(A,B,Ps,Qs).
例如,当我在substitute_single(A,B,[C,A,D,1],X)
上测试我的代码时,问题就出现了。我得到了许多解决方案,一些解决方案将值应用于变量。例如,我得到:
A = 1,
C = 1,
D = 1,
X = [B, B, B, B] ;
或:
只有在其他许多解决方案之后,我才能得到:
X = [C, B, D, 1]
这是我想要的解决方案。然而,接下来还有更多的解决方案(我不希望如此)
因此,我试图切断程序,以防止它产生更多的解决方案:
substitute_single(A,B,[A|As],[B|Bs]):-
substitute_single(A,B,As,Bs),
!.
但是现在,虽然我只得到了一个解决方案,但它不是我想要的
(对于上面的示例,我得到的解决方案是
A = 1,
C = 1,
D = 1,
X = [B, B, B, B].
)
我不知道应该如何或在哪里更改我的程序,这样它只会给我想要的解决方案
(注意:
A
和B
可能是变量,也可能是常量,例如:替换单个(A,3,[C,A,D,1],X)
)应生成[C,3,D,1]
)尝试将X\=B添加到第二个子句中:
substitute_single(A,B,[X|As],[X|Bs]):-
X \= B,
substitute_single(A,B,As,Bs).
因此,当X不是B时,它不会分支到新的解决方案。您的解决方案的问题是,您正在应用术语统一作为相等测试,而您需要的是对具有
==/2
谓词的严格相同术语进行测试
对于在一个列表中交换两个可能是变量的术语,假设一个正确闭合的列表和一个模式+,?,,,-以下谓词就足够了
exchgterms([],_,_,[]).
exchgterms([X|Xs],A,B,[C|Ys]) :-
( X == A -> C=B ;
( X == B -> C=A ; C=X ) ),
exchgterms(Xs,A,B,Ys).
您可以从这里开始解决您的问题,并更改它以满足您的需要,特别是如果您的谓词必须具有不同的模式
更新
我更改了谓词的名称,以强调它也适用于交换非变量的术语
应该清楚的是,它应该在substitute/4
的第二个子句中用不同顺序的参数替换substitute\u single/4
,因此您寻求的解决方案是
substitute(_,_,[],[]).
substitute(A,B,[L|Ls],[R|Rs]) :-
exchgterms(L,A,B,R),
substitute(A,B,Ls,Rs).
我建议您更改
substitute/4
中参数的顺序,使第三个参数成为第一个参数。在这种形式下,大多数Prolog系统都会知道,如果这个参数被实例化,就像这里的情况一样,这两个子句是互斥的,这将有助于更高效的执行。subsvarinterm/4
就是我想到的
:- use_module(library(apply)).
substVarInTerm(A,B,Term0,Term) :-
term_variables(Term0,Vars0),
exclude(==(A),Vars0,Vars),
copy_term(A^Vars^Term0,B^Vars^Term).
请注意,如果第一个参数不是变量,则subsvarinterm/4
不起作用
您提供的其他用例的效果很好:
我会为一个纯单调的解决方案悬赏,只要悬赏可以提供。。。。和确定-对于常见情况。@重复一遍,我对
substitute_single/4
的意思是在B
中替换A
,替换单个列表中出现的A
。然后,我将它应用到每个列表中,将其用于列表列表。我这样做了,但现在得到了一个[B,B,B,B]
解决方案。不管怎么说,我不认为加入这条规则会让我如愿以偿。我的意思是,假设X=A
(和A≠B
),因此我不希望我的解决方案(更换后)也包含A
,我希望它包含B
。问题似乎出现在您的测试案例中。Prolog将大写的输入视为变量。当您使用替换单变量(A,B,[C,A,D,1],X)进行测试时。
Prolog将C,A和D视为变量,并尝试给它们赋值,在您的情况下,每个变量都是1。尝试使用以小写字母开头的原子,比如substitute_single(a,b,[c,a,d,1],X)
或者将输入放在单括号中,比如substitute_single('a','b',[c','a','d',1],X)。
单括号->单引号,但我确实希望它们是变量。有时我想替换常量中变量的外观,而不实际为该变量赋值,我的输入是变量和常量列表的形式。如果第一个参数必须是变量,那么你的解决方案不符合问题末尾的注释,说明第一个和第二个参数可以是非变量。
:- use_module(library(apply)).
substVarInTerm(A,B,Term0,Term) :-
term_variables(Term0,Vars0),
exclude(==(A),Vars0,Vars),
copy_term(A^Vars^Term0,B^Vars^Term).
?- substVarInTerm(A,B,[[1,2,D,C],[A,D],[4,A],[1,2,A]],R).
R = [[1, 2, D, C], [B, D], [4, B], [1, 2, B]].
?- substVarInTerm(A,B,[C,A,D,1],X).
X = [C, B, D, 1].
?- substVarInTerm(A,3,[C,A,D,1],X).
X = [C, 3, D, 1].