- •Модуль 1. Приемы программирования на пролоГе.
- •Тема 1. Основные понятия и определения логического программирования.
- •Лекция 1
- •1. Язык логического программирования пролог.
- •1.1 Основные понятия и определения
- •Лекция 2
- •1.2 Создание консольного приложения. Структура файла main.Pro.
- •1.3 Примеры построения правил
- •Лекция 3
- •1.5 Согласование целевых утверждений. Поиск с возвратом
- •1.5 Рекурсия в пролоГе.
- •Лекция 4
- •1.6 Средства управления пролог-программой. Отладка пролог-программ.
- •1.7 Стандартные предикаты обработки строк
- •1.8 Средства ввода и вывода. Работа с файлами.
- •Лекция 4
- •1.9 Изображение и обработка списков
- •Лекция 5
- •1.10 Динамические базы данных
- •2. Язык функционального программирования лисп Введение
- •2.1 Объекты данных Лиспа
- •2.2 Основные функции лисПа
- •2.2.1 Функции назначения
- •2.2.2 Числовые функции
- •2.2.3 Базовые функции лисПа
- •2.3 Основы работы в среде mulisp-85
- •2.4 Трассировка функций в muLisp.
- •2.4 Определение функций в лисПе
- •2.6 Рекурсивные определения и вычисления
- •Задания для лабораторных работ
1.3 Примеры построения правил
Пример 1.
Рассмотрим задачу поиска девушкой жениха, который должен удовлетворять определенным ее требованиям. Если ввести предикат
man (symbol, symbol, integer),
где аргументы могут обозначать имя, цвет глаз, возраст и т.п., это правило приобретет вид
ideal(X):-man(X,C,A),C=blue,A<=30.
Обычно количество требований-аргументов можно увеличивать практически неограниченно и, кроме того, возможна ситуация, когда какой-либо из аргументов имеет несколько свойств. Например, автомобиль характеризуется маркой, мощностью двигателя, цветом и т.д. В таких случаях применяются сложные структуры данных, которые формируются с помощью стандартных типов Пролога. Эти структуры называются функторами и имеют следующий формат записи
имя_функтора (свойство1, свойство2, , свойство)
Поставим в нашей задаче дополнительное требование, чтобы идеальный друг имел некоторую собственность. Каждую возможную форму собственности можно изобразить в форме функтора, а их многообразие записать с помощью альтернативного задания типов.
Например, введем предикат владеть(объект) или have(object), и пусть к собственности будет принадлежать автомобиль, книга, и конь и каждый из этих функторов имеет разное количество свойств, которые принадлежат к разным типам Пролога. Тогда запись решения задачи приобретет вид
domains object=book(symbol,symbol,integer);
horse(symbol);
avto(symbol,integer).
predicates man(symbol,integer,integer,object).
ideal(symbol).
сlauses man(“Stas”,28,186,have(book(“Куприн”,”Поединок”,1902))).
man(“Vlad”,27,183,have(avto(“Volvo”,350))).
ideal(X):- man(X,A,H,have(book(“Куприн”,_,_))),A<=30,H>=180.
или
ideal(X):- man(X,A,H,have(avto(M,_))), A<=30, H>=180, M=”Volvo”.
Итоговое содержание файла main.pro имеет вид
implement main open core domains object=book(symbol,symbol,integer); horse(symbol); avto(symbol,integer).
property=have(object). class facts man: (symbol,integer,integer,property). class predicates ideal: (symbol) nondeterm(o). clauses man("Stas",28,186,have(book("Куприн","Поединок",1902))). man("Vlad",27,183,have(avto("volvo",350))). ideal(X):- man(X,A,H,have(book("Куприн",_,_))),A<=30,H>=180. run():- console::init(),ideal(X),stdio::write(X),stdio::nl,fail.
run():- stdio::write("fail"),succeed().
end implement main goal mainExe::run(main::run).
Пример 2.
Рассмотрим построение программы, которая позволяет определить родственные связи вашей семьи. В основу построения программы возьмем предикат родители (мама, папа, ребенок). Такой выбор базовой связи позволяет автоматически определить папу и маму.
Следует отметить, что не следует создавать типы папа, мама, ребенок и т.п., так как в одном случае аргумент может быть дедушкой, а в другом – сыном.
Например, программа для определения дедушки будет иметь следующий вид
implement main open core class facts man: (symbol). woman: (symbol). parents: (symbol,symbol,symbol). class predicates
gr_father: (symbol,symbol,symbol) nondeterm anyflow.
clauses classinfo("family", "1.0").
parents("pavel","olga","misha"). parents("anna","mariya","sergey"). parents("igor","anna","pavel"). parents("vita","anna","pavel"). man("petr"). man("pavel"). man("igor"). man("sergey"). man("misha"). woman("mariya").
woman("anna"). woman("olga"). woman("vita").
gr_father(X,Y):-parents(X,_,F),parents(F,_,Y),man(Y). gr_father(X,Y):-parents(X,M,_),parents(M,_,Y),man(Y).
run():- console::init(),
gr_father(stdio::read(),Y),stdio::nl,stdio::write(Y),stdio::nl,fail.
run():- stdio::write("fail"),succeed(). end implement main goal mainExe::run(main::run).
Так как каждый человек должен иметь дедушку как по отцовской линии, так и по материнской, то задача решается с помощью двух правил. Можно было бы объединить эти два правила в одно с помощью логической операции or (или). Но в этом случае правило стало бы более трудным для понимания и, как следствие, возросла бы вероятность допущения ошибки. В обоих правилах необходимо употребление анонимной переменной. Это объясняется тем, что в первом правиле имена мамы и бабушки встречались бы только один раз, что запрещено синтаксисом. Аналогичная ситуация с именами папы и бабушки в правиле для определения дедушки по материнской линий.