
- •Введение
- •Принципы логического программирования
- •1.2. Математическая основа языка Пролог
- •1.2. Организация вычислительного процесса
- •1.2.2. Использование переменных
- •1.2.1. Синтаксис фактов и правил
- •1.3. Бэктрекинг
- •2. Основные элементы языка
- •2.1. Имена
- •2.2. Типы данных
- •2.3. Константы и переменные
- •2.4. Программные секции Пролога
- •2.4.1. Секция Domains
- •2.4.2. Секция Predicates
- •2.4.3. Секция Database
- •2.4.4. Секция Clauses
- •2.4.5. Секция Goal
- •3. Язык Пролог в задачах и примерах
- •3.1. Программирование с помощью фактов и правил
- •3.1.2. Первая формулировка задачи поиска в пространстве состояний 51 ад
- •3.1.3. Реализация на Прологе простой вопросно-ответной системы
- •It_is(“отказать в приеме на работу”):- not(this(“есть диплом”)).
- •It_is(“должность научного сотрудника”):- this(“есть диплом”),
- •3.2. Рекурсии
- •Упражнения
- •3.3. Программирование циклических процессов
- •3.4. Работа со списками
- •3.4.1. Описание списков в программе
- •3.4.2. Добавление элемента в список
- •3.4.3. Удаление элемента
- •3.4.4. Принадлежность элемента списку
- •3.4.5. Сцепление (конкатенация) списков
- •3.4.6. Удаление из списка повторяющихся элементов
- •3.4.7. Вычисление суммы элементов списка
- •3.4.8. Обращение списка
- •3.4.9. Нахождение максимального элемента списка
- •3.4.10. Перестановки
- •3.4.11. Примеры использования списков
- •Упражнения
- •3.5. Виды рекурсии
- •3.6. Поиск в пространстве состояний
- •Vshir ( [ [ V | Way ] | _ ], [ V | Way ] ) :- % Голова списка – полученное решение
- •Vshir ( Ways, Resh ). % Продолжение поиска в случае тупикового пути
- •Упражнения
- •3.6. Использование структур
- •3.6.1. Объявление структур
- •База данных с использованием структур.
- •Vife(X) :– family( _ , X , _ ). % X – жена
- •3.6.4. Планирование воздушного путешествия (143 Бр)
- •3.6.5. Реализация Планировщика в терминах структур
- •3.6.6. Задача «Зебра»
- •Упражнения
- •3.7. Динамическая база данных
- •3.7.1. Использование стандартных предикатов динамической базы данных
- •Упражнения
- •3.8. Средства управления
- •3.9. Представление множеств двоичными деревьями
- •3.9. Программы классификации
- •3.9.1. Программа классификации с обратной цепочкой рассуждений
- •Xpositive( X, y ), !. % в базе данных
- •Xnegative( X, y ), !, fail. % Отрицательный ответ обнаружен в базе данных
- •Xpositive("имеет","перья").
- •3.9.2. Программы классификации с прямой цепочкой рассуждений.
- •It_is( X ) :- write( X, “?”), % Механизм диалога
- •3.9. Обработка текстов
- •Verb( string ) % Глагол
- •Упражнения
- •4. Стандартные предикаты
- •4.1. Ввод/вывод
- •4.2. Управление экраном и оконная система
- •4.3. Обработка строк
- •4.4. Преобразование типов
- •4.5. Работа с базой данных
- •4.6. Управляющие предикаты
- •4.7. Прочие стандартные предикаты
- •4.8. Арифметические и логические предикаты
- •Приложение Приложение 1. Примерные варианты лабораторных заданий
- •1. Родословное дерево
- •2. Вопросно-ответная система
- •3. Работа со списками
- •4. Поиск пути на графе.
- •5. Разработайте прототип классификационной экспертной системы
- •6. Построение синтаксического анализатора
- •Рекомендуемая литература
Verb( string ) % Глагол
DOMAINS % Описание грамматики
DETERM = none ; determ( STRING )
NOUNP = nounp( DETERM, STRING, RELCL)
RELCL = none ; relcl( STRING, VERBP )
SENTENCE = sent( NOUNP, VERBP )
VERBP = verb( STRING ) ; verbp( STRING, NOUNP )
TOKL = STRING*
PREDICATES
is_det( STRING )
is_noun( STRING )
is_rel( STRING )
is_verb( STRING )
s_determ( TOKL, TOKL, DETERM )
s_nounp( TOKL, TOKL, NOUNP )
s_relcl( TOKL, TOKL, RELCL )
s_sentence( TOKL, TOKL, SENTENCE )
s_verbp( TOKL, TOKL, VERBP )
tokl( STRING, TOKL )
tom( TOKL )
run1
run2( STRING )
sen_an
GOAL makewindow(1,6,0,"",0,0,25,80),
sen_an.
CLAUSES
sen_an:– write("Try: every man that lives loves a woman"),
readln( LIN ), LIN >< "" ,
tokl( LIN, TOKL ), % перевод строки в список токенов
s_sentence( TOKL, _ , SENT ),
write("PROLOG OBJECT=",SENT," "),
readchar( _ ), clearwindow, !.
tokl( STR, [ TOK | TOKL ] ) :–
fronttoken( STR, TOK, STR1 ),
tokl( STR1, TOKL ).
tokl( _ ,[ ] ).
s_sentence( TOKL, TOKL2, sent( NOUNP, VERBP )):–
s_nounp( TOKL, TOKL1, NOUNP),
s_verbp( TOKL1, TOKL2, VERBP ),
TOKL2=[ ],! . /* Признак успешного грамматического разбора – остаток списка пуст*/
s_sentence( _ , _ , _ ):–write(">> Sentence not recognized \n"), fail.
% именная группа
s_nounp( TOKL, TOKL2, nounp( DETERM, NOUN, RELCL )):–
s_determ( TOKL, [ NOUN | TOKL1 ], DETERM ),
is_noun( NOUN ),
s_relcl( TOKL1, TOKL2, RELCL ).
% Группа дополнения
s_determ( [ DETERM | TOKL ], TOKL, determ( DETERM )):–
is_det( DETERM ).
s_determ( TOKL, TOKL, none ).
% Группа дополнения
s_relcl( [ REL | TOKL ], TOKL1, relcl( REL, VERBP )):–
is_rel( REL ),
s_verbp( TOKL, TOKL1, VERBP ).
s_relcl( TOKL, TOKL, none ).
% глагольная группа
s_verbp( [ VERB | TOKL ], TOKL1, verbp( VERB, NOUNP )):–
is_verb( VERB ),
s_nounp( TOKL, TOKL1, NOUNP ).
s_verbp( [ VERB | TOKL ], TOKL, verb( VERB )):–
is_verb( VERB ).
is_noun( X ):– noun( X ), !.
is_noun( X ):– noun( Y ), concat( Y, "s", X ).
is_det( X ):– det( X ).
is_rel( X ):– rel( X ).
is_verb( X ):– verb( X ), !.
is_verb( X ):– verb( Y ), concat( Y, "s", X ), !.
is_verb( X ):– verb( Y ), concat( Y, "ed", X ), !.
is_verb( X ):– verb( Y ), concat( Y, "es", X), !.
is_verb( X ):– verb( Y ), concat( Y, "ing", X ).
% словарь
det( "every" ).
det( "a" ).
noun( "man" ).
noun( "woman" ).
rel( "that" ).
rel( "who" ).
rel( "whom" ).
rel( "which" ).
rel( "that" ).
verb( "love" ).
verb( "live" ).
Несколько сложнее реализуется на Прологе система восходящего грамматического разбора, т.к. она базируется на прямой цепочке рассуждений. Однако такая система имеет то преимущество, что может работать с рекурсивными правилами, которые могли бы вызвать бесконечное зацикливание в системе нисходящего разбора.
Примером для реализации восходящей грамматики с рекурсивными правилами является синтаксический анализатор математических выражений. Такая система начинает работу с данными и переходит к простым синтаксическим объектам, а затем и к более сложным. В то время как система нисходящего разбора управляется в основном гипотезами, система восходящего грамматического разбора управляется данными.
В следующем примере на вход подается алгебраическое выражение в виде строки, которое может содержать имена переменных и знаки плюс и умножить. Результат работы программы – запись выражения в префиксной форме, когда знак операции предшествует операндам.
Предикат run начинает работу программы с создания окна, считывает исходное выражение в переменную STR . Следующий предикат tokl переводит строковую переменную в список TOKL токенов (лексем), далее предикат s_exp запускает рабочий предикат plusexp, с которого собственно начинается работа анализатора.
Процедура multexp первую лексему (имя переменной) переводит в префиксную форму и проверяет остаток на наличие после нее (лексемы) операции умножения предикатом multexp1. Если знак "*" присутствует, последний предикат переводит сомножители в префиксную форму.
Предикат plusexp1 проверяет остаток после знака "+" на наличие операции умножения предикатом multexp. Если умножения нет, слагаемые также переводятся в префиксную форму.
domains
TOKL = STRING *
EXP=var( STRING );
plus( EXP, EXP );
mult( EXP, EXP )
PREDICATES
run
tokl( STRING, TOKL )
s_exp( TOKL, TOKL, EXP )
multexp( TOKL, TOKL, EXP )
multexp1( TOKL, TOKL, EXP, EXP )
plusexp( TOKL, TOKL, EXP )
plusexp1( TOKL, TOKL, EXP, EXP )
elmexp( TOKL, TOKL, EXP )
GOAL
run.
CLAUSES
run:– makewindow(1, 2, 7, "", 0, 0, 25, 80),
readln( STR ), tokl( STR, TOKL ),
s_exp( TOKL, _ , EXP ), write(EXP), nl.
tokl( STR, [ TOK | TOKL ] ):–
fronttoken( STR, TOK, STR1 ),
tokl( STR1, TOKL ).
tokl( _ , [ ] ).
s_exp( IL, OL, EXP ):–plusexp( IL, OL, EXP ).
plusexp( IL, OL, EXP2 ):–
multexp( IL, OL1, EXP1 ),
plusexp1( OL1, OL, EXP1, EXP2 ).
plusexp1( [ "+" | IL ], OL, EXP1, EXP3 ):–
multexp( IL, OL1, EXP2 ),
plusexp1( OL1, OL, plus( EXP1, EXP2), EXP3 ).
plusexp1( IL, IL, EXP, EXP ).
multexp( IL, OL, EXP2 ) :–
elmexp( IL, OL1, EXP1 ),
multexp1( OL1, OL, EXP1, EXP2 ).
multexp1( [ "*" | IL ], OL, EXP1, EXP3 ):–
elmexp( IL, OL1, EXP2),
multexp1( OL1, OL, mult(EXP1, EXP2), EXP3).
multexp1( IL, IL, EXP, EXP ).
elmexp( [ NAME | IL ], IL, var( NAME ) ).