想想你的谓词应该描述什么。它是五个列表列表之间的关系,根据您提供的示例,这些列表的长度相同。这表明基本情况有五个空列表。否则,所有五个列表的头都是列表本身,彼此之间具有特定的关系,我们将其称为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
但请注意,由于<
and >=
仅当第三个列表是自由变量时,这才有效。替换第一个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