【问题标题】:How to check for membership in a list in CLINGO?如何检查 CLINGO 列表中的成员资格?
【发布时间】:2020-11-25 12:17:23
【问题描述】:

拥有 Prolog 的背景,我正在努力将这个 DLV(它具有用于处理类似于 Prolog 的列表的内置谓词)程序转换为 CLINGO

path(X,Y,[X|[Y]]) :- rel(X,Y).
path(X,Y,[X|T]) :- rel(X,Z), path(Z,Y,T), not #member(X,T).

rel(X,Y) :- edge(X,Y).
rel(X,Y) :- edge(Y,X).

edge(a,b).
edge(a,c). 
edge(b,a). 
edge(b,c).
edge(e,c).

到目前为止,我设法做到了:

path(X,Y,cons(X,cons(Y,empty))) :- edge(X,Y).
path(X,Y,cons(X,L)) :- edge(X,Z), path(Z,Y,L), not member(X,path(Z,Y,L)).

member(X,path(X,T,cons(X,Y))) :- path(X,T,cons(X,Y)).
member(X,path(S,X,cons(S,L))) :- path(S,X,cons(S,L)).
member(X,path(S,T,cons(S,cons(Z,L)))) :- member(X,path(Z,T,cons(Z,L))).

% same edges    

但我收到错误unsafe variables in in file - at line 7 and column 1-72,我不完全明白为什么。我想知道是否有人可以提供帮助。

【问题讨论】:

    标签: list prolog membership answer-set-programming clingo


    【解决方案1】:

    你从未定义过 S 可能是什么。

    在第 7 行的规则正文中添加 edge(S,Z) 以消除该错误。或者如果你想定义一个顶点谓词,你也可以使用vertex(S)


    所以我用 cons-lists 修复了你的代码。这种方法很不寻常,因为列表不是 asp 中的关键特性,就像它们在 prolog 中一样。好的,这是我的解决方案(适用于有向图):

    edge(a,b).
    edge(a,c). 
    edge(b,c). 
    edge(c,a). 
    edge(c,d). 
    edge(d,b).
    
    node(X) :- edge(X,_). % get nodes
    node(X) :- edge(_,X). % get nodes
    num(N):- {node(X)} == N. % count nodes
    step(1..N) :- num(N). % mark possible steps
    
    path(X,Y,2,cons(X,cons(Y,empty))) :- edge(X,Y).
    path(A,C,NN+1,cons(A,L)) :- edge(A,B), path(B,C,NN,L), step(NN+1).
    
    member(X,path(X,Y,N,cons(X,L))) :- path(X,Y,N,cons(X,L)).
    member(Y,path(X,Y,N,cons(X,L))) :- path(X,Y,N,cons(X,L)).   
    member(M,path(S,T,NN+1,cons(S,cons(Z,L)))) :- member(M,path(Z,T,NN,cons(Z,L))), path(S,T,NN+1,cons(S,cons(Z,L))).   
    
    track(Y,Z,N,L):- {member(X,path(Y,Z,N,L)):node(X)} == N, path(Y,Z,N,L).
    
    #show track/4.
    

    首先你需要知道所有的顶点来计算它们的数量。我还引入了谓词step 来验证路径的深度。 path 现在也有一个深度计数器作为第三个参数。所有可能的路径都存储在path/4 中,允许循环。生成member/2 谓词以显示path/4 内的所有成员顶点。在最后一步中,当且仅当不同成员顶点的数量等于路径长度时,所有路径都被转发到谓词track/4。由于不会计算重复项,因此此条件确保仅转发没有循环的路径。请注意,以上所有步骤都是强制的。每张图都有一个答案集。

    让我们来看看一个更像 ASP 的解决方案。通常你会问一个特定的问题('从 a 到 b 的路径,长度为 n')而不是一个通用的问题('从所有节点到所有可能长度的所有节点的所有可能路径')。下面的代码需要有一个开始节点(start/1)和一个结束节点(end/1)。该程序通过为谓词order/2 中的每个顶点精确分配一个索引号来强制执行(随机)顺序。只要索引不大于结束节点的索引 (path(S,N):- order(S,N), maxZ(Z), S<=Z.),就会将 order 谓词复制到路径谓词。唯一的限制是在路径顺序内,每 2 个相邻顶点都与一条边相连。约束线被读作不可能存在路径内位置N上的节点S1和路径内位置N+1上的节点S2并且从S1到S2没有边的情况 em>。

    edge(a,b).
    edge(a,c). 
    edge(b,c). 
    edge(c,a). 
    edge(c,d). 
    edge(d,b).
    
    start(a).
    end(d).
    
    node(X) :- edge(X,_). % get nodes
    node(X) :- edge(_,X). % get nodes
    num(N):- {node(X)} == N. % count nodes
    step(1..N) :- num(N). % mark possible steps
    order(1,A):- start(A). % start has index 1
    maxZ(Z):- end(E), order(Z,E), step(Z). % end has index maxZ
    
    {order(S,N):node(N)} == 1 :- step(S). % exactly one assignment per step
    {order(S,N):step(S)} == 1 :- node(N). % exactly one assignment per node
    
    path(S,N):- order(S,N), maxZ(Z), S<=Z. % copy order when index is not largter than end node index
    :- path(N, S1), path(N+1, S2), not edge(S1,S2). % successing indices are connected through edges
            
    #show path/2.
    

    【讨论】:

    • 谢谢!我明白你的意思了!愚蠢的我没有发现!添加edge(S,Z) 可以消除错误,但问题永远不会终止......有什么想法吗?
    • 你可以在成员谓词中添加一个计数器来计算 cons 的长度。此数字不应高于顶点数。
    • 我以前从未在 cligo 程序中看到过缺点。我对路径列表的直观想法将是一个索引谓词,它说明顶点的顺序并测试它们是否形成从头到尾的路径。这简化了成员资格测试,但开销很大。
    • 嗨,@Raubsauger!工作比较忙,现在看看。非常感谢您的帮助!
    猜你喜欢
    • 2017-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-19
    • 1970-01-01
    相关资源
    最近更新 更多