НЛП ПРОЛОГ Грамматика - PullRequest
0 голосов
/ 17 мая 2018

У нас есть формальный язык

G 1 = { V , T , S , P }, where
V = { S , E }
T = { x , y , z }
P = { S->E , E->xE , E->yE , E->z }

Можем ли мы принять семь предложений {xz, xy, xyz, xyxz, z, xxyz, Xyz} как правильно построенные формулы? Проверьте это с помощью Пролога.

вот мой код:

s --> e.
e --> [x], e.
e --> [y], e.
e --> [z].

Он может распознавать только s ([z], R). Почему?

?- s([z], R).
R = [].

?- s([xz], R).
false.

?- s([x], R).
false.

Ответы [ 2 ]

0 голосов
/ 18 мая 2018

Во-первых, как уже указывалось @lurker в комментариях, всегда используйте phrase/2 или phrase/3 при вызове DCG. Во-вторых, как указывают @TomasBy и @WillBeason, ваш DCG описывает список, содержащий атомы x, y и z, разделенные запятыми. Итак, чтобы проверить, является ли xz действительным предложением (я полагаю, это то, что означает s) в соответствии с вашей грамматикой, вы должны запросить:

?- phrase(s,[x,z]).
true ;
false.

Действительно, это так. Теперь давайте посмотрим на самый общий запрос, то есть спросим Какие предложения есть? :

?- phrase(s,S).
ERROR: Out of local stack

Это не очень хорошо. Причиной этого является порядок правил DCG: вызов s//0 приводит к вызову первого правила e//0, которое рекурсивно вызывает e//0, то есть первое правило e//0 и т. Д. цикл продолжается до тех пор, пока Пролог не выйдет из стека. Итак, давайте изменим порядок правил, поместив сначала нерекурсивное правило ...

s --> e.

e --> [z].          % <- moved here from last position
e --> [x], e.
e --> [y], e.

... и повторите запрос:

?- phrase(s,S).
S = [z] ;
S = [x, z] ;
S = [x, x, z] ;
S = [x, x, x, z] ;
.
.
.

Теперь мы получаем актуальные решения. Так что порядок правил DCG имеет значение . Однако перечисление ответов является несправедливым, поскольку последнее правило e//0, которое относится к y, фактически никогда не вызывается. Это можно исправить, поставив перед собой цель length/2. Запрос ...

?- length(S,_).
S = [] ;
S = [_G3671] ;
S = [_G3671, _G3674] ;
S = [_G3671, _G3674, _G3677] ;
.
.
.

... возвращает списки со всеми возможными длинами, поэтому добавление префикса к вызову DCG заставит Prolog найти все решения длины 0, прежде чем перейти к длине 1, а затем перейти к длине 2 и т. Д. ...

?- length(S,_), phrase(s,S).
S = [z] ;                    % <- solutions of length 1 from here
S = [x, z] ;                 % <- solutions of length 2 from here
S = [y, z] ;
S = [x, x, z] ;              % <- solutions of length 3 from here
S = [x, y, z] ;
S = [y, x, z] ;
S = [y, y, z] ;
S = [x, x, x, z] ;           % <- solutions of length 4 from here
.
.
.

Таким образом, ваша грамматика фактически производит предложения произвольной длины, как и должно быть. Переходя к примеру с семью предложениями, если ваше приложение требует ограничения длины списков, вы можете сделать это, поставив перед вашим запросом цель between/3 ...

?- between(1,3,N), length(S,N), phrase(s,S).
N = 1,
S = [z] ;
N = 2,
S = [x, z] ;
N = 2,
S = [y, z] ;
N = 3,
S = [x, x, z] ;
N = 3,
S = [x, y, z] ;
N = 3,
S = [y, x, z] ;
N = 3,
S = [y, y, z] ;
false.

... теперь получится все семь предложений, состоящих не более чем из 3 слов Обратите внимание, что ваш пример {xz, xy , xyz, xyxz , z, xxyz , xyz } не совсем набор предложений описывается вашей грамматикой. Элемент xy не является предложением вообще согласно правилам грамматики. Предложения xyxz и xxyz определяются вашей грамматикой, но требуют максимальной длины не менее четырех слов, что даст шестнадцать ответов. И последнее из семи предложений, xyz , появляется дважды в вашем примере, если вы не имели в виду запрос ...

?- phrase(s,[X,y,z]).
X = x ;
X = y ;
false.

... с двумя предложениями, первое из которых по-прежнему является дубликатом.

Наконец, если вам действительно необходимо получить атомы в качестве ответа, вы можете изменить DCG, чтобы поместить в список коды, соответствующие x, y и z, вместо реальных атомов. Затем вы можете использовать atom_codes/2, чтобы получить предложения как один атом вместо списка слов:

s --> e.

e --> [0'z].      % 0'z denotes the code corresponding to z
e --> [0'x], e.   % 0'x denotes the code corresponding to x
e --> [0'y], e.   % 0'y denotes the code corresponding to y

?- between(1,3,N), length(S,N), phrase(s,S), atom_codes(A,S).
N = 1,
S = [122],
A = z ;
N = 2,
S = [120, 122],
A = xz ;
N = 2,
S = [121, 122],
A = yz ;
N = 3,
S = [120, 120, 122],
A = xxz ;
N = 3,
S = [120, 121, 122],
A = xyz ;
N = 3,
S = [121, 120, 122],
A = yxz ;
N = 3,
S = [121, 121, 122],
A = yyz ;
false.
0 голосов
/ 17 мая 2018

(из комментария выше)

Каждый элемент в предложении должен быть разделен запятыми. Строки обрабатываются атомарно, а не как последовательности символов.

?- s([x,z], R).
R = [] .

?- s([x,y,x,z], R).
R = [] .

?- s([x,y], R).
false.
...