пролог dcg ограничение

Я хотел бы использовать DCGs в качестве генератора. На данный момент синтаксис

s-->a,b.
a-->[].
a-->a,c.
c-->[t1].
c-->[t2].
b-->[t3].
b-->[t4].

I would like to generate all s where the length of a is < someNumber.

Using ?- phrase(a,X),length(X,Y),Y<4. i can get all a with less than 4 items. However, when all combinations are exhausted, the system (SWI-Prolog 6.2.5) seems to stall. Sometimes ago, a similar question was asked here. However, being new to Prolog i am not able to make it work with the grammar above. Any ideas?

Update: There was a comment by (canrememberthename) which got deleted, somehow. Anyway, it was suggested to use between(1,4,Y),length(X,Y),phrase(a,X). to set limits. This worked nicely, after changing my code to a-->c,a.

6
добавлено отредактировано
Просмотры: 2
nl ja de
Я удалил ответ, потому что было неправильным. Вы определили проблему собой, в то время как я отлаживал...
добавлено автор CapelliC, источник

2 ответы

Первые шаги в Пролог часто немного трудные. Но вы на правильном пути:

В настоящее время ваша проблема состоит в том, что вы получаете некоторые ответы/решения как ожидалось, но тогда системные киоски; на самом деле это находится в бесконечном цикле. Вы узнали это, терпеливо поразив ПРОСТРАНСТВО . Это могло бы работать с крошечным набором решений, но это будет утомительно с большим. Просто думайте о рассмотрении всех предложений короче, чем 20.

Есть простая клавиатура и кистевой тоннель дружественный способ моделировать совершающее нападки пространство: Просто забейте гол , ложный в конце как так:

?- phrase(a,X),length(X,Y),Y<4, false.

На что Пролог мог ответить на такой вопрос? С тех пор там , ложный в конце, у Пролога нет большого выбора: Любой, на которого это отвечает ложный сам; или это образовывает петли (или производит ошибку или производит некоторый побочный эффект). И в этом случае, это образовывает петли.

Теперь, мы можем сузить проблему, добавив далее , ложный цели в вашу программу.

?- phrase(a,X),length(X,Y),false, Y<4, false.
**LOOPS**

Чтобы сделать это лучше удобочитаемым, я буду только использовать один , ложный цель, и зачеркивать остающуюся часть вопроса:

?- phrase(a,X),length(X,Y),false, Y<4.
**LOOPS**

Давайте уменьшим это еще больше:

?- phrase(a,X),false,length(X,Y),Y<4.
**LOOPS**

Они все петля! Но мы получаем некоторое интересное понимание: Начиная с них , ложный - не заканчиваются украшенные вопросы, также оригинальная программа не заканчивается. Таким образом, когда вы смотрите на вопрос, и самая первая цель не заканчивается для себя, из этого следует, что весь вопрос не закончится (см. мелкий шрифт в конце для больше).

Поэтому: необходимо обратиться к первой цели так или иначе !

Моя первая попытка состоит в том, чтобы обменять длину и фраза :

?- length(X,Y), phrase(a,X), Y<4.

Will this work? Just look at the first goal which loops:

?- length(X,Y), false, phrase(a,X), Y<4.

So this again will not terminate.

You have to change the program again:

?- between(1,3,Y), length(X,Y), false, phrase(a,X).
false.

So this terminates. And if there will be a termination problem, phrase(a,X) has now to take the blame:

?- between(1,3,Y), length(X,Y), phrase(a,X), false.
**LOOPS**

You might be tempted to look at actual answers:

?- between(1,3,Y), length(X,Y), phrase(a,X).
Y = 1,
X = [t1] ;
Y = 1,
X = [t2] ;
ERROR: Out of local stack

And you might conclude that this behavior is worse than your original definition. After all, we have now less answers than before. But exactly that kind of reasoning does not help you to improve termination: With false both are of the same kind of incorrectness and you have to address this first. So by hiding the answers you can better concentrate on the rest.

But why is your grammar problematic? We can continue with our technique to insert goals false to narrow it down. But this time within your grammar. Your program adorned with goals false is called a .

Just a practical remark: When I insert goals false into your program, I will save the program and type make in SWI: In this manner the program is rapidly recompiled.

After trying a bit, I got the following minimal failure-slice. Note that within a DCG, false has to be written as {false}.

?- between(1,3,Y), length(X,Y), phrase(a,X), false

s--> {false}, a,b.

a-->[], {false}.
a-->a,{false},  c.

c-->{false}, [t1].
c-->{false}, [t2].

b-->{false}, [t3].
b-->{false}, [t4].

Almost all your codebase are belong to false! So you have to address the tiny visible remaining part. It would be pointless to change something somewhere else. This a --> a, ... must be changed! And in fact changing it to a --> c, s solves the problem.

Why did you write a --> a, c. in the first place? I suspect that you wanted to enumerate all solutions in a fair manner. The new version doesn't:

?- phrase(a,X).
X = [] ;
X = [t1] ;
X = [t1, t1] ;
X = [t1, t1, t1] ;
X = [t1, t1, t1, t1] ;
X = [t1, t1, t1, t1, t1] ;
X = [t1, t1, t1, t1, t1, t1] ;
X = [t1, t1, t1, t1, t1, t1, t1] ...

That looks very intimidating. In fact, it looks wrong. Doesn't it? But don't let you confuse by this: We have here an infinite set of sentences. So the only correct response by Prolog is to produce infinitely many answers. For, if they would be finite, some list would be missing! But of course, you want to see them enumerated in a fair manner. To get this, simply write:

?- length(X,N),  phrase(a,X).
X = [],
N = 0 ;
X = [t1],
N = 1 ;
X = [t2],
N = 1 ;
X = [t1, t1],
N = 2 ;
X = [t1, t2],
N = 2 ;
X = [t2, t1],
N = 2 ;
X = [t2, t2],
N = 2 ;
X = [t1, t1, t1],
N = 3 ...

This is a major point in Prolog programs: Always go for the best (possible) termination property first. And do not look at the precise order how Prolog enumerates answers. For, if a program has better termination properties, it is next-to-trivial to use it to enumerate all solutions in a fair manner. But: A program that enumerates infinitely many solutions in a fair manner at the expense of termination cannot be used in more interesting cases.

Fine Print
See this answer.

5
добавлено
"вся ваша кодовая база, принадлежат ложному", возможно, лучшее заявление I' ve, прочитанные в Прологе, отвечают на StackOverflow. Спасибо за улыбку
добавлено автор mndrix, источник

нетерминальное//0 является обоими леворекурсивный, и 'эпсилон' (произведите пустую последовательность), и фраза/2 немедленно образует петли после пустого производства.

Можно решить проблему, ограничивающую список' длина:

?- between(1,4,Y),length(X,Y),phrase(a,X).

и, поскольку вы уже сделали, удалив левую рекурсию.

2
добавлено