Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List 减少谓词调用_List_Prolog - Fatal编程技术网

List 减少谓词调用

List 减少谓词调用,list,prolog,List,Prolog,我有一个谓词: check_matrix([[_, E2, E3], [E4, E5, E6], [E7, E8, E9]]) :- E5 = E9, is_valid([E4, E5, E6]), is_valid([E7, E8, R9]), is_valid([E2, E5, E8]), is_valid([E3, E6, E9]). 它检查我的2 x 2矩阵是否有效,左上角的单元

我有一个谓词:

check_matrix([[_, E2, E3], 
             [E4, E5, E6], 
             [E7, E8, E9]]) :-
     E5 = E9,
     is_valid([E4, E5, E6]),
     is_valid([E7, E8, R9]),
     is_valid([E2, E5, E8]),
     is_valid([E3, E6, E9]). 
它检查我的2 x 2矩阵是否有效,左上角的单元格,
被完全忽略。
E2
E3
E4
E7
单元格只是2 x 2矩阵的标题

这是一个更好的方法,我可以
Is\u valid()
,这样我就不需要调用
Is\u valid()
4次。如果矩阵变大,例如5x5,则该谓词需要调用
is\u valid()
10次。这对Prolog正常吗?还是他们的方式更优雅

我想用另一个谓词创建一个嵌套列表,其中包含我要传递给
is\u valid()
的所有可能列表,并在每个列表上调用该谓词,然后将结果传递回
check\u matrix()
。我觉得他们的方式一定更优雅。如有任何建议,将不胜感激

更新


E5=E9
只是一个对角线检查器,它检查矩阵的对角线是否相同,如果不相同,则谓词失败

如果要避免这种硬编码谓词,可以尝试递归:

您可以检查每个列表(第一个列表除外)中的
是否有效,以便您可以编写:

check_matrix([H|T]) :- is_valid_each_list(T),....

is_vqlid_each_list([]).
is_vqlid_each_list([L|T]):- length(L,3),is_valid(L),
                            is_vqlid_each_list(T).
请注意,限制
length(L,3)
表示元素是长度为3的列表(或任何参数K,如果愿意,只需添加另一个参数)

现在检查E2、E5、E8(位于同一位置的元素)

因此,完整的通用解决方案:

check_matrix([H|T]) :- is_valid_each_list(T), is_valid_pos([H|T]).

is_vqlid_each_list([]).
is_vqlid_each_list([L|T]):- length(L,3),is_valid(L),
                            is_vqlid_each_list(T).

is_valid_pos(L):-length(L,3), is_valid_pos(L,1).

is_valid_pos(_,4).
is_valid_pos(L,K):- findall(X,(member(L1,L),nth0(K,L1,X)),L2),
                    is_valid(L2),K1 is K+1, is_valid_pos(L,K1).

如果要避免这种硬编码谓词,可以尝试递归:

您可以检查每个列表(第一个列表除外)中的
是否有效,以便您可以编写:

check_matrix([H|T]) :- is_valid_each_list(T),....

is_vqlid_each_list([]).
is_vqlid_each_list([L|T]):- length(L,3),is_valid(L),
                            is_vqlid_each_list(T).
请注意,限制
length(L,3)
表示元素是长度为3的列表(或任何参数K,如果愿意,只需添加另一个参数)

现在检查E2、E5、E8(位于同一位置的元素)

因此,完整的通用解决方案:

check_matrix([H|T]) :- is_valid_each_list(T), is_valid_pos([H|T]).

is_vqlid_each_list([]).
is_vqlid_each_list([L|T]):- length(L,3),is_valid(L),
                            is_vqlid_each_list(T).

is_valid_pos(L):-length(L,3), is_valid_pos(L,1).

is_valid_pos(_,4).
is_valid_pos(L,K):- findall(X,(member(L1,L),nth0(K,L1,X)),L2),
                    is_valid(L2),K1 is K+1, is_valid_pos(L,K1).

Prolog有一些库,如
library(apply)
,它们提供高阶谓词:传递另一个谓词的谓词

这里似乎适用的高阶谓词是。谓词将谓词(
:Goal
)和列表(
?list
)作为参数,并对
?list
的元素应用
:Goal
,直到谓词失败或列表耗尽。您可以将它与在列表上迭代的命令式语言中的函数进行比较,并检查谓词是否适用于列表的所有成员。比如Python中的
all(…)

因此,我们可以使用以下方法检查除第一行以外的所有行:

但是,我们也必须检查除第一列以外的所有列。因此我们可以使用谓词。它有两个参数,第二个参数是第一个参数的转置。因此:

?- transpose([[1, 2, 3], 
|             [4, 5, 6], 
|             [7, 8, 9]],X).
X = [[1, 4, 7], [2, 5, 8], [3, 6, 9]].
因此,我们可以转置矩阵,然后再次使用
maplist/2
检查矩阵
M
转置的除第一行以外的所有行。现在我们可以实现如下谓词:

:- use_module(library(apply)).
:- use_module(library(clpfd)).

check_matrix(M) :-
    M = [_|MT],
    maplist(is_valid,MT),
    transpose(M,[_|TT]),
    maplist(is_valid,TT).
编辑

如果您想检查除第一个对角线元素以外的所有元素是否都存在,我建议定义两个附加谓词:

  • all_same/1
    检查列表中的所有元素是否相同;及
  • diagonal/2
    构造对角线元素列表的
全部相同/1
可以实现为:

all_same([]).
all_same([_]).
all_same([H,H|T]) :-
    all_same([H|T]).
对角线/2
可通过以下方式获得:

diagonal(M,L) :-
    diagonal(M,0,L).

diagonal([],_,[]).
diagonal([R|RT],I,[D|DT]) :-
    nth0(I,R,D),
    I1 is I+1,
    diagonal(RT,I1,DT).
现在我们可以检查对角线,如下所示:

check_matrix(M) :-
    M = [_|MT],
    maplist(is_valid,MT),
    transpose(M,[_|TT]),
    maplist(is_valid,TT),
    diagonal(M,[_|DT]),
    all_same(DT).
检查矩阵(M):-
M=[[u124; MT],
地图列表(是否有效,MT),
转置(M,[[u124; TT]),
地图列表(是否有效,TT),
对角线(M,[| DT]),

all_same(DT)。
Prolog有一些库,如
library(apply)
,它们提供高阶谓词:传递另一个谓词的谓词

这里似乎适用的高阶谓词是。谓词将谓词(
:Goal
)和列表(
?list
)作为参数,并对
?list
的元素应用
:Goal
,直到谓词失败或列表耗尽。您可以将它与在列表上迭代的命令式语言中的函数进行比较,并检查谓词是否适用于列表的所有成员。比如Python中的
all(…)

因此,我们可以使用以下方法检查除第一行以外的所有行:

但是,我们也必须检查除第一列以外的所有列。因此我们可以使用谓词。它有两个参数,第二个参数是第一个参数的转置。因此:

?- transpose([[1, 2, 3], 
|             [4, 5, 6], 
|             [7, 8, 9]],X).
X = [[1, 4, 7], [2, 5, 8], [3, 6, 9]].
因此,我们可以转置矩阵,然后再次使用
maplist/2
检查矩阵
M
转置的除第一行以外的所有行。现在我们可以实现如下谓词:

:- use_module(library(apply)).
:- use_module(library(clpfd)).

check_matrix(M) :-
    M = [_|MT],
    maplist(is_valid,MT),
    transpose(M,[_|TT]),
    maplist(is_valid,TT).
编辑

如果您想检查除第一个对角线元素以外的所有元素是否都存在,我建议定义两个附加谓词:

  • all_same/1
    检查列表中的所有元素是否相同;及
  • diagonal/2
    构造对角线元素列表的
全部相同/1
可以实现为:

all_same([]).
all_same([_]).
all_same([H,H|T]) :-
    all_same([H|T]).
对角线/2
可通过以下方式获得:

diagonal(M,L) :-
    diagonal(M,0,L).

diagonal([],_,[]).
diagonal([R|RT],I,[D|DT]) :-
    nth0(I,R,D),
    I1 is I+1,
    diagonal(RT,I1,DT).
现在我们可以检查对角线,如下所示:

check_matrix(M) :-
    M = [_|MT],
    maplist(is_valid,MT),
    transpose(M,[_|TT]),
    maplist(is_valid,TT),
    diagonal(M,[_|DT]),
    all_same(DT).
检查矩阵(M):-
M=[[u124; MT],
地图列表(是否有效,MT),
转置(M,[[u124; TT]),
地图列表(是否有效,TT),
对角线(M,[| DT]),
都一样(DT)。