【问题标题】:Prolog CLPFD trying to define domain for lists of listProlog CLPFD 试图为列表定义域
【发布时间】:2015-03-25 12:18:40
【问题描述】:

我正在处理 Prolog 中的约束编程问题,并且在尝试为列表定义域时遇到问题。问题的初步挑战如下:

   trains([[1,2,0,1], %from station, to station, departs at, arrives at
           [2,3,4,5],
           [2,3,0,1],
           [3,4,5,6],
           [3,4,2,3],
           [3,4,8,9]]).

   threepath(A,D,Ps):-
        Ps = [[A,B, _T0, T1], [B,C, T2, T3], [C,D, T4, _T5]],
        T2 #> T1,
        T4 #> T3,
        trains(Ts),
        tuples_in(Ps, Ts).

在那之后,我预计会对此进行扩展,以容纳任意数量的火车,而不是只有 3 列。这是我的尝试:

  anypath(A,D,Ps,N):-
        length(Ps,N),
        Ps ins Xs,
        Xs = [A,B,C,D],
        Xs ins 1..9. %How to define the domain for a list of length 4 inside a list of variable length.

但是,我不太确定如何为列表定义域。到目前为止,我已经定义了 length(Ps, N) 以便 Ps 可以有任意长度。然后,我尝试在 Ps 中定义变量,以便它们成为长度为 4 的列表,但失败了。

此外,我也不确定如何定义可变长度 Ps 的约束,例如 T2 #> T1 和 T3 #> T4 的 3 个场景案例。我看到的模式是下一个列表的最后一个元素应该大于它之前列表的第三个元素,但我也坚持使用表示这个约束的语法。

现在,我正在尝试使用递归以某种方式将 Ps 的头部设置为长度为 4 的列表,并通过递归对尾部执行相同的操作,因为我无法知道列表 Ps 的长度会的。

如果有人能对此有所了解,我将不胜感激。

25/3/2015 进展更新

我阅读了另一个问题的示例,即使用 maplist 生成内部列表。代码摘录如下:

length_(Length, List) :- length(List, Length).

child_row(X) :- X ins 1..16 .

ww(X) :-
        write(X),
        write('/').

print_row(Row) :-
        maplist(ww, Row),
        nl.

children(Class) :-
        length(Class, 4),
        maplist(length_(4), Class),
        maplist(child_row , Class),

据我了解, maplist(length_(4), Class) 将 length_(4) 应用于 Class 内的每个元素,并因此创建长度为 4 的内部列表。因此,我尝试将此应用于我的问题,这是我的尝试:

length_(Length, List) :- length(List, Length).
anypath(A,D,Ps,N):-
    length(Ps,N),
    maplist(length_(4), Ps),
    %constraint(Ps),
    trains(Ts),
    tuples_in(Ps, Ts).

但是,无论 N 设置为 3 还是 4,我都会收到一条错误消息“长度/2:类型错误:list' expected, found4'”,我也不太明白这一点,因为它应该可以工作与上面的示例相同,gtrace 检测对我来说有什么问题有点混乱。

我目前卡住了,如果我有什么发现我会更新。

所以,我还有一个问题希望得到解答,“创建内部列表的常规做法是什么?您通常如何自己做?”。

谢谢!

【问题讨论】:

  • Xs 未实例化时,您不能执行Ps ins Xs。你可以试试Xs = [A,B,C,D], Xs ins 1..9, label(Xs), Ps ins Xs
  • 我试过了,但它给了我Domain Error: 'clpfd-domain' expeceted, found '[1,1,1,1]'。我添加了约束“B #> A”,因为我要从一个站点到另一个站点,并且“T0 > T1”因为时间会过去,并且在我旅行时它会增加。这是我根据您的建议更新的代码:anypath(A,D,Ps,N):- length(Ps,N), Xs = [A, B, T0, T1], Xs ins 1..9, label(Xs), Ps ins Xs, B #> A, T1 #> T0, trains(Ts), tuples_in(Ps, Ts).
  • 抱歉,我对Ps ins Xs 的建议是愚蠢的......
  • 创建一个谓词,比如define_foo(X) :- length(X, 4), X ins 1..9.,然后执行length(P, N), maplist(define_foo, P)。那么P将是一个长度为N的列表,由长度为4的元素组成,这些元素是域变量ins 1..9
  • 我尝试了一种不同的方式,因为使用 maplist 的帖子来自另一个我看到的涉及使用长度来定义内部列表的问题,但效果不佳。我更新了我的帖子,详细说明了我的尝试,如果您有空时可以查看它,我将不胜感激。 :D

标签: list prolog constraint-programming clpfd


【解决方案1】:

您可以使用扁平化列表

append(Trains, FlatTrains)

然后约束 FlatTrains 的域

FlatTrains ins 1..9

【讨论】:

  • s(X)! append/2 是一个很好的删除一层嵌套的方法。
猜你喜欢
  • 1970-01-01
  • 2016-01-16
  • 2014-01-31
  • 1970-01-01
  • 1970-01-01
  • 2016-09-03
  • 2014-01-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多