Законное использование (\+)//1

В правилах грамматики (dcg) есть несколько предопределенных конструкции: (',')//2 означает конкатенацию, ('|')//2 означает чередование и т. д. Одна конструкция, которая поддерживается несколькими, но не всеми системами Prolog, — это (\+)//1.

Лично я использовал его только ради использования. Я никогда не видел его в коде, написанном другими.

Итак, есть ли законное использование (\+)//1?

Изменить: и, кроме того, есть ли законное использование (\+)//1 в запросе phrase(nt, L) с L неконкретной переменной.


person false    schedule 06.10.2012    source источник


Ответы (2)


\+ можно использовать для создания менее неоднозначных грамматик. Преимущество использования \+ перед ! например, является определенной декларативностью \+, так что, например, результирующие правила DCG могут быть переупорядочены.

Давайте сделаем пример, рассмотрим следующую грамматику:

s([X|Y]) --> t(X), s(Y).               % 1
s([])    --> [].                       % 2

t(2)     --> [a,a].                    % 3
t(1)     --> [a].                      % 4

Приведенная выше грамматика очень неоднозначна, например, я получаю несколько синтаксических анализов для следующего ввода:

?- phrase(s(A),[a,a,a,a,a]).
A = [2,2,1] ;
A = [2,1,2] ;
A = [2,1,1,1] ;
etc..

Теперь предположим, что я хочу предпочесть длинный анализ t короткому анализу t. Я могу сделать это с разрезом следующим образом:

t(2)     --> [a,a], !.                 % 5
t(1)     --> [a].                      % 6

?- phrase(s(A),[a,a,a,a,a]).
A = [2,2,1] ;
No

К сожалению не могу перезаказать. Так как выполнение следующего не дает желаемого результата. Хотя s(A) теперь выдает результаты в другом порядке, мы вернулись к исходной точке, поскольку грамматика снова неоднозначна:

t(1)     --> [a].                      % 7
t(2)     --> [a,a], !.                 % 8

?- phrase(s(A),[a,a,a,a,a]).
A = [1,1,1,1,1] ;
A = [1,1,1,2] ;
A = [1,1,2,1] ;
etc...

Теперь давайте попробуем то же самое с \+. Мы можем заменить разрез следующим отрицанием:

t(2)     --> [a,a].                    % 9
t(1)     --> [a], \+ [a].              % 10

?- phrase(s(A),[a,a,a,a,a]).
A = [2,2,1] ;
No

Теперь давайте попробуем, можем ли мы изменить порядок. Переупорядочим правила грамматики t//1:

t(1)     --> [a], \+ [a].              % 11
t(2)     --> [a,a].                    % 12

?- phrase(s(A),[a,a,a,a,a]).
A = [2,2,1] ;
No

Декларативность очень полезна. Это означает, например, что мы можем использовать \+ в синтаксическом анализаторе диаграмм справа налево, который выбирает правила грамматики в произвольном порядке. Декларативность гарантирует, что восходящая прямая цепочка анализатора диаграмм дает один и тот же результат независимо от порядка ввода правил DCG.

Затем можно применять метод DCG в больших проектах на естественном языке (NL), и он хорошо масштабируется. Грамматики ЕЯ можно эмпирически настроить на детерминизм. Чем более детерминирована грамматика, тем эффективнее ее синтаксический анализ. Сложные ЕЯ-грамматики, которые в противном случае были бы неразрешимы, становятся возможными.

до свидания

person Mostowski Collapse    schedule 07.10.2012
comment
+1, но я очень скептически отношусь к вашему заявлению о декларативности: phrase(s([1]),[a]). удается, но phrase(s([1]),L) терпит неудачу. Именно такая нечистота и беспокоит меня. - person false; 07.10.2012
comment
То есть: как вы проводите грань между законным использованием и незаконным? - person false; 07.10.2012
comment
Я не претендую на общую декларативность. Я написал некую декларативность. Вы можете установить декларативность в отношении украшения (= жаргон базы данных для объявления режима Prolog). Методы могут быть также применены к грамматикам. См. также: ftp.inf.ethz.ch/doc/tech -отчеты/1xx/177.pdf - person Mostowski Collapse; 07.10.2012

Когда L не создается, грамматика используется для генерации текста. Тогда вам вообще не нужна грамматика \+. Так как больше нет проблемы двусмысленности из какого-то текста.

Давайте сделаем пример, рассмотрим следующую грамматику:

s([X|Y]) --> t(X), s(Y).               % 1
s([])    --> [].                       % 2

t(2)     --> [a,a].                    % 3
t(1)     --> [a].                      % 4

Каждый отдельный синтаксический анализ имеет свое дерево синтаксического анализа. И нет никакой двусмысленности в использовании фразы/2 для генерации текста. Следующие запросы дают ровно один ответ:

?- phrase(s([2,1]),L).
L = [a,a,a]
?- phrase(s([1,2]),L).
L = [a,a,a]
?- phrase(s([1,1,1]),L).
L = [a,a,a]

Но есть небольшая проблема с повторным использованием. Предположим, у меня есть грамматика NL с \+ для синтаксического анализа. Затем я не могу использовать его для разбора. Так как паттерн инстанцирования цели \+ будет другим, а значит и семантика конструкции изменится.

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

Я думаю, что в некоторых случаях также можно использовать одну грамматику и рассматривать \+ как аннотацию для устранения неоднозначности, которая отбрасывается во время разбора или обрабатывается по-другому. Можно построить такой механизм. Но проблемы с разбором по сравнению с разбором глубже: двунаправленность вспомогательных условий ({}/1), левая рекурсия при разборе и т. д.

до свидания

person Mostowski Collapse    schedule 07.10.2012
comment
Опять же, здесь может помочь технология дедуктивной базы данных. Установление двунаправленного дополнения (= жаргон базы данных для объявления режима Prolog) является первым шагом. Но это уже не обычный Пролог. - person Mostowski Collapse; 07.10.2012