使用带有`length/2`的约束变量

10 prolog clpfd

这是问题所在:

$ swipl
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.3.6-5-g5aeabd5)
Copyright (c) 1990-2015 University of Amsterdam, VU Amsterdam
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to redistribute it under certain conditions.
Please visit http://www.swi-prolog.org for details.

For help, use ?- help(Topic). or ?- apropos(Word).

?- use_module(library(clpfd)).
true.

?- N in 1..3, length(L, N).
N = 1,
L = [_G1580] ;
N = 2,
L = [_G1580, _G1583] ;
N = 3,
L = [_G1580, _G1583, _G1586] ;
ERROR: Out of global stack % after a while
Run Code Online (Sandbox Code Playgroud)

(我可以切换子查询的顺序,结果是一样的).

我想N在使用之前我需要贴标签,但我想知道问题是什么?我之前没有成功length/2.

jsc*_*mpf 5

什么可能比略微不确定的更有用的length/2是适当的列表长度约束.您可以在此处找到它的ECLiPSe实现,称为.有了这个,你会得到以下行为:len/2

?- N :: 1..3, len(Xs, N).
N = N{1 .. 3}
Xs = [_431|_482]               % note it must contain at least one element!
There is 1 delayed goal.
Yes (0.00s cpu)
Run Code Online (Sandbox Code Playgroud)

然后,您可以通过枚举来枚举有效列表N:

?- N :: 1..3, len(Xs, N), indomain(N).
N = 1
Xs = [_478]
Yes (0.00s cpu, solution 1, maybe more)
N = 2
Xs = [_478, _557]
Yes (0.02s cpu, solution 2, maybe more)
N = 3
Xs = [_478, _557, _561]
Yes (0.02s cpu, solution 3)
Run Code Online (Sandbox Code Playgroud)

或者通过生成具有良好旧标准的列表length/2:

?- N :: 1..3, len(Xs, N), length(Xs, _).
N = 1
Xs = [_488]
Yes (0.00s cpu, solution 1, maybe more)
N = 2
Xs = [_488, _555]
Yes (0.02s cpu, solution 2, maybe more)
N = 3
Xs = [_488, _555, _636]
Yes (0.02s cpu, solution 3)
Run Code Online (Sandbox Code Playgroud)

  • 关键线是`暂停(len(Xs,L,N),0,[[Xs0,N] - > inst,N-> min])`,其中目标被延迟直到Xs0或N被实例化或者更低N个变化的界限.您必须研究如何使用SWI的clpfd执行此操作. (3认同)
  • @Boris:请注意,此方法因不一致而进行非终止交易!`len(L,N),len([_ | L],N)`是这样的不一致,`len(L,L)`另一个.如果您在这样的环境中直接编程,最终会出现一堆您无法理解的"延迟"或"挣扎"目标.也就是说,这些机制当然可以用于产生有意义的抽象.但是没有稳定的概念来直接推理它们(比如故障切片是针对常规的Prolog). (2认同)