2015-04-30 2 views
3

Я пытаюсь определить Prolog DCG для набора строк 0^N 1^M 2^N + M длины 2N + 2M для N, M> = 0 с использованием дополнительных аргументов. Примером правильной строки будет «011222», но не «012».Определение Prolog DCG с дополнительными аргументами

Для создания этого 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], []). 

Пролог возвращает значение ИСТИНА, как и ожидалось.

Однако, когда я бегу

s(X, []). 

Пролог возвращает следующее:

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

Они не являются действительными строками. Я думаю, это может быть связано с тем, что N и M декрементируются предикатом c до того, как пролог выполнит предикаты a и b. Это так? Как это можно решить?

Edit: Я попытался изменения производства ей на это:

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

но выдает ошибку при выполнении запросов.

ответ

1

Вы злоупотребляете succ/2, возможно, потому что вы ожидаете, что Prolog оценивает функции в шаблонах головы. Это не так. Затем попробуйте заменить правила с

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

и т.д. и т.п.

редактировать так 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] ; 
... 
+0

Я попытался это, но он не работает. Prolog дает ошибку, что succ не был достаточно инстанцирован. Как это обойти? – Darkphenom

+1

Если вы используете clpfd здесь, используйте также дополнительные ограничения, такие как 'X #> = 0' в рекурсивных предложениях. Они могут быть избыточными в некоторых режимах, но обеспечить прекращение в других! – repeat

+0

Ваше решение имеет плохие свойства завершения. Например. 'phrase (s, [2 | _]).' loops – false

1

ИМО ответы, которые вы получаете, верны!

я переименовал свою грамматику от 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:

 
?- length(Xs, _), phrase(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)))) 
... 

Чтобы поднять нижнюю границу N или M, просто констатирует дополнительную цель формы X = s(s(_)) (для минимального значения 2). В следующем запросе как N и M должны быть больше, чем 0:

 
?- N = s(_) , M =  s(_) , length(Xs, _), phrase(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] 
... 
Смежные вопросы