我最近一直试图找出Prolog并且一直在搞乱Prolog中的列表清单。我试图在p中创建一种掩模 序言。我有一个谓词,它决定了Prolog中两个列表列表(L1和L2可以说)之间的区别,并将它们保存为列表列表(让我们说R)。我有另一个谓词,只是说明差异是否等于零(noDifference)。我希望有两个结果列表(M1和M2)基于L1和L2与R相比。例如我想将L1和L2的所有值与R进行比较,如果负值在某个位置然后,在L1的相同位置的值被保存到M1中。如果正值位于R的位置,那么L2的相同位置的值将被保存到M2中,如果这是有意义的话。在所有这些之前,我使用noDifference函数检查差异是否为0,如果是,则M1和M2的列表列表的所有值都为0.
这是我到目前为止所做的事情(我不确定我是否开始做对了)
masker(L1,L2,R,M1,M2):- noDifference(R1), M1=R, M2=R1;
其余部分是一些示例值应该在引擎盖下的内容
L1=[[1,5,3,8],[1,5,3,8]]
L2=[[5,4,7,4],[5,4,7,4]]
R=[[4,-1,4,-4],[4,-1,4,-4]]
M1=[[0,5,0,8],[0,5,0,8]]Neg values of L1 at R are stored rest are 0)
M2=[[5,0,7,0],[5,0,7,0]](Pos values of L2 at R are stored rest are 0)
如果我到目前为止所做的事情是正确的,以及如何正确地制定子目标/我应该去的地方,那将是非常棒的!
使用ex谓词进行编辑
?- masker([[1,5,3,8],[1,5,3,8]],
[[5,4,7,4],[5,4,7,4]],
[[4,-1,4,-4],[4,-1,4,-4]], M1, M2).
M1=[[0,5,0,8],[0,5,0,8]].
M2=[[5,0,7,0],[5,0,7,0]].
答案 0 :(得分:5)
考虑你的谓词应该描述的内容。它是五个列表列表之间的关系,根据您提供的示例,它们具有相同的长度。这表明基本情况有五个空列表。否则,所有五个列表的头部都是列表本身,它们彼此具有特定的关系,我们称之为lists_mask_mlists / 5。当然,对于尾部也应如此,这可以通过递归目标来实现。所以你的谓词masker / 5可能看起来像这样:
masker([],[],[],[],[]).
masker([X|Xs],[Y|Ys],[M|Ms],[R1|R1s],[R2|R2s]) :-
lists_mask_mlists(X,Y,M,R1,R2),
masker(Xs,Ys,Ms,R1s,R2s).
实际的屏蔽关系也有一个带有五个空列表的基本情况。否则还有两个案例:
1)当前屏蔽元素(第三个列表的头部)为负数:第一个列表的头部是第四个列表的头部,第五个列表的头部是0
2)当前屏蔽元素为正:第二个列表的头部是第五个列表的头部,第四个列表的头部是0
你可以这样表达:
lists_mask_mlists([],[],[],[],[]).
lists_mask_mlists([X|Xs],[_Y|Ys],[M|Ms],[X|R1s],[0|R2s]) :- % 1)
M < 0,
lists_mask_mlists(Xs,Ys,Ms,R1s,R2s).
lists_mask_mlists([_X|Xs],[Y|Ys],[M|Ms],[0|R1s],[Y|R2s]) :- % 2)
M >= 0,
lists_mask_mlists(Xs,Ys,Ms,R1s,R2s).
使用此谓词,您的示例查询会产生所需的结果:
?- masker([[1,5,3,8],[1,5,3,8]],[[5,4,7,4],[5,4,7,4]],[[4,-1,4,-4],[4,-1,4,-4]],M1,M2).
M1 = [[0,5,0,8],[0,5,0,8]],
M2 = [[5,0,7,0],[5,0,7,0]] ? ;
no
但是请注意,由于<
和>=
这只会起作用,如果第三个列表是可变的。用变量替换第三个参数中的第一个4
会产生实例化错误:
?- masker([[1,5,3,8],[1,5,3,8]],[[5,4,7,4],[5,4,7,4]],[[X,-1,4,-4],[4,-1,4,-4]],M1,M2).
ERROR at clause 2 of user:masked/5 !!
INSTANTIATION ERROR- =:=/2: expected bound value
如果您打算将谓词与第三个不可变的参数一起使用,您可能会考虑使用clpfd。包括
行:-use_module(library(clpfd)).
在您的源文件中并改变lists_mask_mlists / 5,如下所示:
lists_mask_mlists([],[],[],[],[]).
lists_mask_mlists([X|Xs],[_Y|Ys],[M|Ms],[X|R1s],[0|R2s]) :-
M #< 0, % <- here
lists_mask_mlists(Xs,Ys,Ms,R1s,R2s).
lists_mask_mlists([_X|Xs],[Y|Ys],[M|Ms],[0|R1s],[Y|R2s]) :-
M #>= 0, % <- here
lists_mask_mlists(Xs,Ys,Ms,R1s,R2s).
现在第二个查询也有效:
?- masker([[1,5,3,8],[1,5,3,8]],[[5,4,7,4],[5,4,7,4]],[[X,-1,4,-4],[4,-1,4,-4]],M1,M2).
M1 = [[1,5,0,8],[0,5,0,8]],
M2 = [[0,0,7,0],[5,0,7,0]],
X in inf.. -1 ? ;
M1 = [[0,5,0,8],[0,5,0,8]],
M2 = [[5,0,7,0],[5,0,7,0]],
X in 0..sup ? ;
no
答案 1 :(得分:4)
@tas提出了一个很好的解决方案和解释(+1)。
在此代码的基础上,我想提高程序的空间效率。再次考虑使用基于CLP(FD)的解决方案的示例查询:
?- masker([[1,5,3,8],[1,5,3,8]],[[5,4,7,4],[5,4,7,4]],[[4,-1,4,-4],[4,-1,4,-4]],M1,M2). M1 = [[0, 5, 0, 8], [0, 5, 0, 8]], M2 = [[5, 0, 7, 0], [5, 0, 7, 0]] ; false.
我们从; false
看到选择点是在执行此程序期间累积的,因为Prolog引擎并不明白这些条款实际上是互斥的。< / p>
显然,这些程序使用的内存超过了跟踪剩余选择所需的内存。
抵制诱惑以巧妙地削减计算的分支,因为这只会导致更多问题。
相反,请考虑使用if_/3
。
在这种情况下应用if_/3
所需的全部内容是对CLP(FD)约束(#<)/2
的非常简单的说明,这对于zcompare/3
很容易:
#<(X, Y, T) :- zcompare(C, X, Y), less_true(C, T). less_true(<, true). less_true(>, false). less_true(=, false).
通过这个定义,整个程序变为:
:- use_module(library(clpfd)). masker([], [], [], [], []). masker([X|Xs], [Y|Ys], [M|Ms], [R1|R1s], [R2|R2s]) :- lists_mask_mlists(X, Y, M, R1, R2), masker(Xs, Ys, Ms, R1s, R2s). lists_mask_mlists([], [], [], [], []). lists_mask_mlists([X|Xs], [Y|Ys], [M|Ms], R1s0, R2s0) :- if_(M #< 0, (R1s0 = [X|R1s], R2s0 = [0|R2s]), (R1s0 = [0|R1s], R2s0 = [Y|R2s])), lists_mask_mlists(Xs, Ys, Ms, R1s, R2s).
现在要点:
?- masker([[1,5,3,8],[1,5,3,8]],[[5,4,7,4],[5,4,7,4]],[[4,-1,4,-4],[4,-1,4,-4]],M1,M2). M1 = [[0, 5, 0, 8], [0, 5, 0, 8]], M2 = [[5, 0, 7, 0], [5, 0, 7, 0]].
此示例查询现在是 deterministic !
该程序仍然足够通用来处理第二个示例查询!