【问题标题】:Defining Prolog DCG with extra arguments用额外的参数定义 Prolog DCG
【发布时间】:2015-04-30 11:15:47
【问题描述】:

我正在尝试使用额外的参数为长度为 2N + 2M 的字符串集 0^N 1^M 2^N+M 定义一个 Prolog DCG,M >= 0。正确字符串的示例是“011222”,但不是“012”。

我已使用以下代码创建此 DCG。

s --> a(N), b(M), c(N), c(M).

a(0) --> [].
a(succ(X)) --> [0], a(X).

b(0) --> [].
b(succ(X)) --> [1], b(X).

c(0) --> [].
c(succ(X)) --> [2], c(X).

当我运行查询时

s([0,1,1,2,2,2], []).

Prolog 按预期返回 true。

但是当我运行时

s(X, []).

Prolog 返回以下内容:

X = []
X = [1,2]
X = [1,1,2,2]
X = [1,1,1,2,2,2]

这些不是有效的字符串。我认为这可能是因为 N 和 M 在 prolog 运行 a 和 b 谓词之前被 c 谓词递减。是这样吗?如何解决?

编辑: 我已经尝试将 s 生产修改为:

s --> a(N), b(M), c(NplusM), {NplusM is N + M}.

但是在运行查询时会出错。

【问题讨论】:

  • 产生式有效,您没有排除 N=0。

标签: prolog dcg


【解决方案1】:

IMO 你得到的答案是正确的!

我将您的语法从 s 重命名为 aN_bM_cNM 并添加了两个附加参数,一个用于 N,另一个用于 M。另外,我将succ重命名为s

aN_bM_cNM(N, M) --> n_reps(N, 0), n_reps(M, 1), n_reps(N, 2), n_reps(M, 2)。 n_reps( 0 , _) --> []。 n_reps(s(N), E) --> [E], n_reps(N, E)。

现在让我们运行@CapelliC 给出的查询。目标length(Xs, _) 确保公平枚举aN_bM_cNM//2 的无限解集:

?- 长度(Xs, _), 短语(aN_bM_cNM(N,M), Xs)。 ( Xs = [] , N = 0 , M = 0 ; Xs = [1,2] , N = 0 , M = s(0) ; Xs = [0,2] , N = s(0) , M = 0 ; Xs = [1,1,2,2] , N = 0 , M = s(s(0)) ; Xs = [0,1,2,2] , N = s(0) , M = s(0) ; Xs = [0,0,2,2] ,N = s(s(0)) ,M = 0 ; Xs = [1,1,1,2,2,2] , N = 0 , M = s(s(s(0))) ; Xs = [0,1,1,2,2,2] , N = s(0) , M = s(s(0)) ; Xs = [0,0,1,2,2,2] , N = s(s(0)) , M = s(0) ; Xs = [0,0,0,2,2,2],N = s(s(s(0))),M = 0 ; Xs = [1,1,1,1,2,2,2,2], N = 0 , M = s(s(s(s(0)))) ...

要提高NM 的下限,只需声明X = s(s(_)) 形式的附加目标(最小值为2)。 在以下查询中,NM 都大于 0

?- N = s(_) , M = s(_) , 长度(Xs, _), 短语(aN_bM_cNM(N,M), Xs)。 ( N = s(0) , M = s(0) , Xs = [0,1,2,2] ; N = s(0) , M = s(s(0)) , Xs = [0,1,1,2,2,2] ; N = s(s(0)), M = s(0) , Xs = [0,0,1,2,2,2] ; N = s(0) , M = s(s(s(0))), Xs = [0,1,1,1,2,2,2,2] ...

【讨论】:

    【解决方案2】:

    您误用了 succ/2,可能是因为您希望 Prolog 在头部模式中评估函数。它没有。然后,尝试用

    替换您的规则
    a(0) --> [].
    a(Y) --> {succ(X,Y)}, [0], a(X).
    

    等等等等

    edit 因为 succ/2 需要至少一个参数实例化为整数,我们可以将 N,M 提供给 DCG 条目,或者,使用 CLP(FD):

    :- use_module(library(clpfd)).
    
    s --> a(N), b(M), c(N), c(M).
    
    a(0) --> [].
    a(Y) --> {Y #= X-1}, [0], a(X).
    
    b(0) --> [].
    b(Y) --> {Y #= X-1}, [1], b(X).
    
    c(0) --> [].
    c(Y) --> {Y #= X-1}, [2], c(X).
    

    但仍然必须提供列表的长度。例如

    ?- length(L,_),phrase(s,L).
    L = [] ;
    L = [1, 2] ;
    L = [0, 2] ;
    L = [1, 1, 2, 2] ;
    L = [0, 1, 2, 2] ;
    L = [0, 0, 2, 2] ;
    ...
    

    【讨论】:

    • 我试过了,但它不起作用。 Prolog 给出了一个错误,即 succ 没有充分实例化。有什么办法吗?
    • 如果您在此处使用 clpfd,还要在递归子句中使用额外的约束,例如 X #>= 0。它们在某些模式下可能是多余的,但在其他模式下确保终止!
    • 您的解决方案的终止特性很差。例如。 phrase(s,[2|_]). 循环
    猜你喜欢
    • 2014-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多