列表总和上的参数未充分实例化
Arguments are not sufficiently instantiated on list sum
我正在尝试限制列表的总和,但我的代码在 label()
处失败。
.pl:
:- use_module(library(clpfd)).
solve(L, Dim) :-
length(L, 5), % define 5 diagonals
SkipVars is Dim - 2, % to skip variables
init_sublists_above_center(L, Dim, SkipVars),
init_center(L, 2, Dim),
init_sublists_below_center(L, 3, Dim, 1),
flatten(L, FlatL),
collect_vars(FlatL, _),
writeln("list="+L),
constraint_sum(L, 38).
collect_vars([], NewL):-
all_different(NewL).
collect_vars([H|T], NewL) :-
H == 0,
collect_vars(T, NewL).
collect_vars([H|T], NewL) :-
append(NewL, [H], NewestL),
collect_vars(T, NewestL).
constraint_sum([], _).
constraint_sum([H|T], Sum) :-
writeln(H),
label(H),
sum_list(H, Sum),
constraint_sum(T, Sum).
init_sublists_above_center([H|T], Dim, SkipVars) :-
length(H, Dim),
init_zeroes(H, SkipVars),
NewSkipVars is SkipVars + 1,
NewSkipVars =< Dim,
init_sublists_above_center(T, Dim, NewSkipVars).
init_sublists_above_center(_, _, _).
init_sublists_below_center(_, _, Dim, Fill) :-
End is Dim - 2,
Fill == End.
init_sublists_below_center([H|T], ToSkip, Dim, Fill) :-
ToSkip == 0,
length(H, Dim),
init_zeroes_start(H, Fill),
NewFill is Fill + 1,
init_sublists_below_center(T, 0, Dim, NewFill).
init_sublists_below_center([_|T], ToSkip, Dim, Fill) :-
NewToSkip is ToSkip - 1,
init_sublists_below_center(T, NewToSkip, Dim, Fill).
init_center(_, ToSkip, _) :-
ToSkip == -1.
init_center([H|_], ToSkip, Dim) :-
ToSkip == 0,
length(H, Dim),
init_center(_, -1, _).
init_center([_|T], ToSkip, Dim) :-
NewToSkip is ToSkip - 1,
init_center(T, NewToSkip, Dim).
init_zeroes([], _).
init_zeroes([H|T], Fill) :-
Fill == 0,
H is 0,
init_zeroes(T, Fill).
init_zeroes([_|T], Fill) :-
NewFill is Fill - 1,
init_zeroes(T, NewFill).
init_zeroes_start(_, Fill) :-
Fill == 0.
init_zeroes_start([H|T], Fill) :-
H is 0,
NewFill is Fill - 1,
init_zeroes_start(T, NewFill).
输出:
7 ?- solve(L, 5).
list= + [[_G15351,_G15407,_G15466,0,0],[_G15525,_G15584,_G15643,_G15702,0],[_G15761,_G15820,_G15879,_G15938,_G15997],[0,_G16056,_G16115,_G16174,_G16233],[0,0,_G16292,_G16351,_G16410]]
[_G15351,_G15407,_G15466,0,0]
ERROR: Arguments are not sufficiently instantiated
有什么想法吗?
编辑:
在 运行 调试器之后:,我 认为 错误在 label()
内,此时:
finite_domain(Var) :-
( fd_get(Var, Dom, _) ->
( domain_infimum(Dom, n(_)), domain_supremum(Dom, n(_)) -> true
; instantiation_error(Var)
)
; integer(Var) -> true
; must_be(integer, Var)
).
使用图形调试器单步执行代码:
?- gtrace, solve(L, 5).
如您所见,label/1
与此错误无关。
而不是 sum_list/2
,使用 CLP(FD) 约束 sum/3
:它适用于所有方向,让您看到查询的答案。
话虽这么说,但我建议您退后一步,认真考虑一下您在这里所做的事情。
例如,为什么要将副作用 (write/1
) 与纯代码混合?专注于对问题的清晰的声明性描述,让顶层为您报告。
此外,如此频繁地需要像 (==)/2
这样的额外逻辑谓词是非常不寻常的。例如写:
sublists_below_center(_, _, Dim, End) :-
End #= Dim - 2.
在不诉诸逻辑外的语言元素的情况下,使参数之间的关系完全清楚。
使用 flatten/2
几乎总是一个坏主意,通常表明您的数据结构设计存在问题。使用 append/2
删除一层嵌套。
如果您已经导入了 CLP(FD) 库,为什么还要使用原始算法?始终使用 (#=)/2
等。
此外,您的谓词名称表明您对问题的思考方式过于迫切。专注于对问题解决方案的纯声明性描述,Prolog 将为您完成剩下的工作。避免命令式名称。相反,使用描述什么条件下的名称。
我正在尝试限制列表的总和,但我的代码在 label()
处失败。
.pl:
:- use_module(library(clpfd)).
solve(L, Dim) :-
length(L, 5), % define 5 diagonals
SkipVars is Dim - 2, % to skip variables
init_sublists_above_center(L, Dim, SkipVars),
init_center(L, 2, Dim),
init_sublists_below_center(L, 3, Dim, 1),
flatten(L, FlatL),
collect_vars(FlatL, _),
writeln("list="+L),
constraint_sum(L, 38).
collect_vars([], NewL):-
all_different(NewL).
collect_vars([H|T], NewL) :-
H == 0,
collect_vars(T, NewL).
collect_vars([H|T], NewL) :-
append(NewL, [H], NewestL),
collect_vars(T, NewestL).
constraint_sum([], _).
constraint_sum([H|T], Sum) :-
writeln(H),
label(H),
sum_list(H, Sum),
constraint_sum(T, Sum).
init_sublists_above_center([H|T], Dim, SkipVars) :-
length(H, Dim),
init_zeroes(H, SkipVars),
NewSkipVars is SkipVars + 1,
NewSkipVars =< Dim,
init_sublists_above_center(T, Dim, NewSkipVars).
init_sublists_above_center(_, _, _).
init_sublists_below_center(_, _, Dim, Fill) :-
End is Dim - 2,
Fill == End.
init_sublists_below_center([H|T], ToSkip, Dim, Fill) :-
ToSkip == 0,
length(H, Dim),
init_zeroes_start(H, Fill),
NewFill is Fill + 1,
init_sublists_below_center(T, 0, Dim, NewFill).
init_sublists_below_center([_|T], ToSkip, Dim, Fill) :-
NewToSkip is ToSkip - 1,
init_sublists_below_center(T, NewToSkip, Dim, Fill).
init_center(_, ToSkip, _) :-
ToSkip == -1.
init_center([H|_], ToSkip, Dim) :-
ToSkip == 0,
length(H, Dim),
init_center(_, -1, _).
init_center([_|T], ToSkip, Dim) :-
NewToSkip is ToSkip - 1,
init_center(T, NewToSkip, Dim).
init_zeroes([], _).
init_zeroes([H|T], Fill) :-
Fill == 0,
H is 0,
init_zeroes(T, Fill).
init_zeroes([_|T], Fill) :-
NewFill is Fill - 1,
init_zeroes(T, NewFill).
init_zeroes_start(_, Fill) :-
Fill == 0.
init_zeroes_start([H|T], Fill) :-
H is 0,
NewFill is Fill - 1,
init_zeroes_start(T, NewFill).
输出:
7 ?- solve(L, 5).
list= + [[_G15351,_G15407,_G15466,0,0],[_G15525,_G15584,_G15643,_G15702,0],[_G15761,_G15820,_G15879,_G15938,_G15997],[0,_G16056,_G16115,_G16174,_G16233],[0,0,_G16292,_G16351,_G16410]]
[_G15351,_G15407,_G15466,0,0]
ERROR: Arguments are not sufficiently instantiated
有什么想法吗?
编辑:
在 运行 调试器之后:,我 认为 错误在 label()
内,此时:
finite_domain(Var) :-
( fd_get(Var, Dom, _) ->
( domain_infimum(Dom, n(_)), domain_supremum(Dom, n(_)) -> true
; instantiation_error(Var)
)
; integer(Var) -> true
; must_be(integer, Var)
).
使用图形调试器单步执行代码:
?- gtrace, solve(L, 5).
如您所见,label/1
与此错误无关。
而不是 sum_list/2
,使用 CLP(FD) 约束 sum/3
:它适用于所有方向,让您看到查询的答案。
话虽这么说,但我建议您退后一步,认真考虑一下您在这里所做的事情。
例如,为什么要将副作用 (write/1
) 与纯代码混合?专注于对问题的清晰的声明性描述,让顶层为您报告。
此外,如此频繁地需要像 (==)/2
这样的额外逻辑谓词是非常不寻常的。例如写:
sublists_below_center(_, _, Dim, End) :-
End #= Dim - 2.
在不诉诸逻辑外的语言元素的情况下,使参数之间的关系完全清楚。
使用 flatten/2
几乎总是一个坏主意,通常表明您的数据结构设计存在问题。使用 append/2
删除一层嵌套。
如果您已经导入了 CLP(FD) 库,为什么还要使用原始算法?始终使用 (#=)/2
等。
此外,您的谓词名称表明您对问题的思考方式过于迫切。专注于对问题解决方案的纯声明性描述,Prolog 将为您完成剩下的工作。避免命令式名称。相反,使用描述什么条件下的名称。