Логическое программирование. Основы языка Пролог. Prolog — удивительный язык программирования Основы логического программирования языке пролог
Язык программирования Prolog является одним из ведущих логических языков программирования. Он был создан Аленом Колмерье (Alain Colmerauer) в 1970-х годах. Это была попытка сделать язык программирования для начинающих, который дает возможность выразить логику, а не тщательно задавать инструкциями на экране компьютера то, что хочется получить.
Пролог используется во многих программах искусственного интеллекта, но его синтаксис и семантика очень простые и ясные (первоначальная цель заключалась в обеспечении инструментом для компьютерных неграмотных лингвистов). Название Пролог акроним для ПРОграммирования в ЛОГике и широко известен при обучении основам программирования.
Пролог основан на исчислении предикатов (точнее первого порядка исчисления предикатов), однако он ограничен формулами Хорна. Программы Пролога эффективны для доказательства теорем в первом приближении. Основные понятия объединения, хвостовая рекурсии и отслеживание.
Типы данных
Пролог не использует типы данных в том виде, который нам привычен в распространенных языках программирования. Мы можем говорить о Пролог лексических элементах вместо типов данных, что непривычно в программировании для чайников.
Текст константы вводится с помощью атомов. Атом последовательность, состоящая из букв, цифр и подчеркивания, который начинается с буквы в нижнем регистре. Обычно, если это не буквенно-цифровые атомы, то необходимо, обрамлять их апострофами (например, "+" является атомом, + является оператором).
Большинство реализаций Prolog не делают различий между действительными и дробными числами.
Переменные
Переменные обозначаются строкой, состоящей из букв, цифр и символов подчеркивания, а начинается с буквы верхнего регистра. В среде Пролог, переменная не является контейнером, который может быть назначен (в отличие от процедурных языков программирования). Его поведение ближе к модели, которая похожа на объединения.
Так называемые анонимные переменные записываются в виде одного подчеркивание (_).
Термины являются единственным способом, которым Пролог может представлять сложные данные. Термин состоит из головы, которая также называется функтор (который должен быть атомом) и параметров (не ограниченные типами). Число параметров, так называемых арностей термина, является важным. Термин определяется по его голове и арности, обычно записывается как функтор / арности.
Списки
Список не является автономным типом данных, потому что он определяется рекурсивным построением (используя термин / 2 "."):
Atom - пустой список
Для удобства программиста, списки могут быть построены и разрушены в разному.
Если L является списком и X является элементом, то "." (X, L) является членом списка. Первый элемент X, за которым следует содержимое контекста L, синтаксически представляют как.
Для удобства программиста, списки могут быть построены и уничтожены в разному.
Элемент перечисление:
Предварение одного элемента:
Предварение несколько элементов:
Расширение термина: "."(abc, "."(1, "."(f(x), "."(Y, "."(g(A,rst), )))))
Строки обычно записывается как последовательность символов в кавычках. Они часто представлены в виде списков кодов символов таблицы ASCII.
Программирование на языке ПРОЛОГ сильно отличается от работы с процедурными языками. В Прологе Вы работаете с базами данных из фактов и правил, вы можете выполнять запросы к базе данных. Основной единицей Пролог является предикат, который определен, чтобы быть правдой (true). Предикат состоит из головы и числа аргументов. Например:
Здесь "cat" это голова, и "tom" является аргументом. Вот некоторые примеры запросов вы можете выполнить с помощью транслятора Пролог на основе этого факта:
Cat(tom).
yes.
Cat(X).
X = tom;
no.
Предикаты обычно определяются для выражения факта, с помощью которого программа знает о мире. В большинстве случаев, использование предикатов требует определенных соглашений. Таким образом, какая из представленных версий будет означать, что Пэт является отцом Салли?
Father(sally,pat).
father(pat,sally).
"father" в обоих случаях это голова, а "sally" и "pat"- аргументы. Однако в первом случае, Салли на первом месте в списке аргументов, а на втором Пэт на и наоборот. Первый случай является примером определения в порядке Глагол Предмет и Объект, ну а во втором примере порядок следующий Глагол Объект Предмет. Поскольку Пролог не понимает по-английски, обе версии прекрасно подходят, однако, считается хорошим стилем программирования придерживаться одного стиля, называемого соглашением, в ходе написания одной программы, чтобы потом не писать что-то вроде:
Father(pat,sally). father(jessica,james).
Некоторые предикаты встроены в язык, и позволяют Прологу уменьшить рутину повседневной деятельности (например, ввод / вывод с использованием графики и иного общения с операционной системой). Например, предикаты записи могут быть использованы для вывода на экран таким образом:
Write ("привет")
Будет отображать слово "Hello" на экране.
Правила
Второй тип заявлений в Пролог - это правила. Пример правила:
Light(on) :- switch(on).
": -" означает "если", это правило означает, light (on) верно (включен), если switch (on) это правда (иначе, если переключатель switch включен, тогда есть свет light). Правила могут также использовать переменные, переменные начинаются с большой буквы в то время как константы начинаются со строчных буквам. Например,
Father(X,Y) :- parent(X,Y),male(Y).
Это означает, "если кто-то является родителем, и он мужчина, то он является отцом". Причины и следствия могут находиться и в обратном порядке, так что это не противоречит обычной логике. Можно разместить несколько предикатов в разделе следствий, объединив их вместе, например:
Что эквивалентно нескольким объявлениям:
A:- d. b:- d. c:- d.
Но не разрешаются инструкции вида:
Что является эквивалентом "если с, то a или b". Это связано с ограничением, на накладываемым формулой Хорна.
Тема 3. Язык программирования ПРОЛОГ
Лекция № 2
Язык программирования Visual Prolog
2. Представление знаний, структуры данных в программах на языке Пролог.
3. Функциональные возможности Visual Prolog
1. Основные конструкции языка Visual Prolog, разделы программы, дескриптивный, процедурный и машинный смысл программы на Прологе
Краткая историческая справка:
В начале 70 х годов группа специалистов Марсельского университета во главе с А. Колмероэ разработали специализированную систему для доказательств теорем на базе языка Фортран, которую использовали для обработки высказываний на естественном языке. В начале 80 годов в Отделении Вычислительных наук Датского Технического Университета сформировался коллектив программистов, которым в 1982 году был разработан интерпритатор языка пролог для VAX. В 1984 Лео Йенсен, Джон Гофман, Финн Гронсков разработали компилятор для IBM PC возникла фирма PDC (Prolog Development Center). Фирма Borland до 1990 Turbo Prolog затем права переданы PDC. С 1993 года под руководством Виктора Юхтенко в разработке Visual Prolog принимает участие группа PDC из СПб. Возглавляют проект в настоящее время Лео Йенсен, Томас Линдер Пулс, Виктор Юхтенко, Юрий Ильин.
1. Основные конструкции языка Visual Prolog
Имена
a. В Прологе, напомним, имена используются для обозначения символических констант, доменов, предикатов и переменных. Имя состоит из буквы (или знака подчеркивания), за которой следует любая комбинация нуля или более букв, цифр или знаков подчеркивания. На имя накладываются два важных ограничения:
b. О имена символических констант должны начинаться со строчной буквы;
c. имена переменных должны начинаться с прописной буквы или знака подчеркивания.
За исключением этих ограничений, вы можете использовать прописные и строчные буквы в программе как угодно. Например, можно сделать имя более читабельным, смешивая большие и маленькие буквы, как в переменной
MyLongestVariableNameSoFar
или используя знаки подчеркивания:
pair_who_might_make_ar_happy_couple (henry_yiii, ann_boleyn)
Компилятор Visual Prolog, кроме как для первой буквы, не делает отличий между прописными и строчными буквами. Это означает, что две переменные
одинаковы.
Ключевые слова
Следующие слова являются зарезервированными и их нельзя использовать как имена, определенные пользователем:
abstract elsedef ifndef procedure
align endclass implement protected
as enddef include predicates
and erroneous language reference
class facts multi single
clauses failure nocopy static
constants global nondeterm struct
database goal object this
Специально определенные предикаты
Следующие предикаты обрабатываются компилятором специальным образом; эти имена нельзя переопределять в программе:
chain_insertafter
2. Разделы программы
Программа на языке Visual Prolog состоит из модулей, каждый из которых содержит несколько разделов. Раздел программы идентифицируется ключевым словом, как показано в табл. 23.1.
Опции компилятора Опции компилятора, заданные в начале модуля
constants Нуль или более символических констант
domains Нуль или более объявлений доменов
facts Нуль или более объявлений предикатов базы данных
predicates Нуль или более объявлений предикатов
goal Цель программы
clauses Нуль или более предложений
class Нуль или более объявлений открытых (и защищенных) предикатов, фактов и доменов
implement Нуль или более объявлений закрытых предикатов, фактов и доменов. Нуль или более предложений, реализующих открытые и закрытые предикаты (и инициализирующих факты)
abstract class Нуль или более объявлений открытых предикатов и доменов. не должны иметь реализацию
Чтобы создать программу, вы должны в ней указать цель. Программе необходимы, по меньшей мере, разделы predicates и clauses . Большинству программ нужен раздел domains для объявления списков, сложных структур и ваших собственных доменов.
При модульном программировании вы можете ставить перед ключевыми словами domains, predicates и facts ключевое слово global, указывая, что последующие объявления имеют глобальную область видимости и объявленные имена действительны во всех программных модулях, которые включают объявления этих глобальных разделов.
Программа может содержать несколько разделов domains, predicates, facts и clauses, а также несколько объявлений и реализаций классов,
Секция объявления объектов предметной области (domains section), которые будут использоваться в логической программе, например:
title, author = symbol pages = unsigned
секция объявления предикатов (predicates section), которые будут использоваться в логической программе, например:
book(title, pages) written_by(author, title) long_novel(title)
Секция логических предложений (clauses section), в которой указываются факты и правила, используемые системой Prolog для поиска решений поставленных перед ней задач, например:
секция цели (goal section), в которой формулируется задача для системы Prolog, например:
3. Дескриптивный, процедурный и машинный смысл программы на Прологе.
Обычно программа на Прологе не является последовательностью действий, - она представляет собой набор фактов с правилами, обеспечивающими получение заключений на основе этих фактов. Поэтому Пролог известен как декларативный язык.
Программы на языке Пролог состоят из двух типов фраз: фактов и правил, также называемых предложениями.
· Факты - это отношения или свойства, о которых известно, что они имеют значение "истина".
· Правила - это связанные отношения; они позволяют Прологу логически выводить одну порцию информации из другой. Правило принимает значение "истина", если доказано, что заданный набор условий является истинным.
2. В Прологе все правила имеют 2 части: заголовок и тело, разделенные специальным знаком: -.
· Заголовок - это факт, который был бы истинным, если бы были истинными несколько условий. Это называется выводом или зависимым отношением.
· Тело - это ряд условий, которые должны быть истинными, чтобы Пролог мог доказать, что заголовок правила истинен.
факты и правила- практически одно и то же, кроме того, что факты не имеют явного тела. Факты ведут себя так, как если бы они имели тело, которое всегда истинно.
Пролог всегда ищет решение, начиная с первого факта и/или правила, и просматривает весь список фактов и/или правил до конца.
Механизм логического вывода Пролога берет условия из правила (тело правила) и просматривает список известных фактов и правил, пытаясь удовлетворить условиям. Если все условия истинны, то зависимое отношение (заголовок правила) считается истинным. Если все условия не могут быть согласованы с известными фактами, то правило ничего не выводит.
Пролог базируется на предложениях Хорна, являющихся подмножеством формальной системы, называемой логикой предикатов. Логика предикатов - это простейший способ объяснить, как "работает" мышление, и она проще, чем арифметика, которой вы давно пользуетесь.
Пролог использует упрощенную версию синтаксиса логики предикатов, он прост для понимания и очень близок к естественному языку.
Язык Пролог не предназначен для программирования задач с большим количеством арифметических операций. Для этого используются процедурные языки программирования. Однако в любую Пролог-систему включаются все обычные арифметические операторы:
Сложение - вычитание * умножение / деление mod остаток от деления целых чисел div целочисленное деление
Пролог включает механизм вывода, который основан на сопоставлении образцов. С помощью подбора ответов на запросы он извлекает хранящуюся (известную) информацию. Пролог пытается проверить истинность гипотезы (другими словами - ответить на вопрос), запрашивая для этого информацию, о которой уже известно, что она истинна
Одной из важнейших особенностей Пролога является то, что, в дополнение к логическому поиску ответов на поставленные вами вопросы, он может иметь дело с альтернативами и находить все возможные решения. Вместо обычной работы от начала программы до ее конца, Пролог может возвращаться назад и просматривать более одного "пути" при решении всех составляющих задачу частей.
2. Представление знаний, структуры данных в программах на языке Пролог.
2. структуры данных в программах на Прологе.
1. Представление знаний о предметной области в виде фактов и правил базы знаний Пролога.
Деревья относятся к рекурсивные структурам данных
Тип данных является рекурсивным, если он допускает структуры, содержащие такие же структуры, как и они сами.
Наиболее важным рекурсивным типом данных является список, хотя он и не выглядит непосредственно рекурсивной конструкцией.
Visual Prolog позволяет определить действительно рекурсивные типы, в которых указатели создаются и обрабатываются автоматически. Например, можно определить дерево следующим образом:
treetype = tree(string, treetype, treetype)
Эта декларация говорит о том, что дерево записывается как функтор tree, аргументами которого являются строка и два других дерева.
Внутренняя база фактов (данных)
Внутренняя база фактов состоит из фактов, которые вы можете непосредственно добавлять и удалять из вашей программы на Visual Prolog во время ее исполнения. Вы можете объявлять предикаты, описывающие внутреннюю базу данных в разделе facts программы и применять эти предикаты таким же образом, как используются предикаты, описанные в разделе predicates.
Для добавления новых фактов в базу данных в Visual Prolog используются предикаты assert, asserta, assertz, а предикаты retract и retractall служат для удаления существующих фактов. Вы можете изменить содержание вашей базы фактов, сначала удалив факт, а потом вставив новую версию этого факта (или совершенно другой факт). Предикаты consult/1 и consult/2 считывают факты из файла и добавляют их к внутренней базе данных, a save/1 и save/2 сохраняют содержимое внутренней базы фактов в файле.
Visual Prolog интерпретирует факты, принадлежащие к базе данных, таким же образом, как обычные предикаты. Факты предикатов внутренней базы фактов хранятся в таблице, которую можно легко изменять, тогда как обычные предикаты для достижения максимальной скорости компилируются в двоичный код.
Ключевое слово facts (это синоним устаревшего слова database) определяет начало объявления раздела facts
Внешние базы данных в Visual Prolog
Система внутренних баз данных Visual Prolog, использующая предикаты asserta, assertz, retract и retractall, является простой и удобной. Однако она уступает в скорости работы с большими базами данных, отчасти из-за этих соображений была создана система внешних баз данных, с помощью которой можно, например, создать:
Систему управления запасами с большим количеством записей;
Экспертную систему со многими отношениями и небольшим количеством записей сложной структуры;
Учетную систему для запоминания больших текстов в базе данных;
Пользовательскую базу, в которой данные связаны не реляционным путем.
2. структуры данных в программах на Прологе
Списки и рекурсия
Обработка списков, т. е. объектов, которые содержат произвольное число элементов - мощное средство Пролога. В этой главе объясняется, что такое списки и как их объявлять. Затем приводится несколько примеров, в которых показано, как можно использовать обработку списков в задачах. Далее определяются два известных предиката Пролога - member (член) и append (объединение) при рассмотрении процедурных и рекурсивных аспектов обработки списков.
После этого определяется стандартный предикат Visual Prolog - findall, который дает возможность находить и собирать все решения для одной цели.
Что такое список?
В Прологе список - это объект, который содержит конечное число других объектов. Списки можно грубо сравнить с массивами в других языках, но, в отличие от массивов, для списков нет необходимости заранее объявлять их размер.
Конечно, есть другие способы объединить несколько объектов в один. Если число объектов заранее известно, то вы можете сделать их аргументами одной составной структуры данных. Если число объектов не определено, то можно использовать рекурсивную составную структуру данных, такую как дерево. Но работать со списками обычно легче, т. к. Visual Prolog обеспечивает для них более четкую запись.
Каждая составляющая списка называется элементом. Чтобы оформить списочную структуру данных, надо отделить элементы списка запятыми и заключить их в квадратные скобки. Вот несколько примеров:
["valerie ann", "Jennifer caitlin", "benjamin thomas"]
Объявление списков
Чтобы объявить домен для списка целых, надо использовать декларацию домена, такую как:
integerlist = integer*
Символ (*) означает "список чего-либо"; таким образом, integer* означает "список целых".
Обратите внимание, что у слова "список" нет специального значения в Visual Prolog. С тем же успехом можно назвать список "Занзибаром". Именно обозначение * (а не название), говорит компилятору, что это список.
Элементы списка могут быть любыми, включая другие списки. Однако все его элементы должны принадлежать одному домену. Декларация домена для элементов должна быть следующего вида:
elementlist = elements*
Здесь elements имеют единый тип (например: integer, real или symbol) или являются набором отличных друг от друга элементов, отмеченных разными функторами. В Visual Prolog нельзя смешивать стандартные типы в списке. Например, следующая декларация неправильно определяет список, составленный из элементов, являющихся целыми и действительными числами или идентификаторами:
Головы и хвосты
Список является рекурсивным составным объектом. Он состоит из двух частей - головы, которая является первым элементом, и хвоста, который является списком, включающим все последующие элементы. Хвост списка - всегда список, голова списка - всегда элемент. Например:
голова [а, b, с] есть a
хвост [а, b, с] есть
Что происходит, когда вы доходите до одноэлементного списка? Ответ таков
голова[с] есть с
хвост [с] есть
Работа со списками
В Прологе есть способ явно отделить голову от хвоста. Вместо разделения элементов запятыми, это можно сделать вертикальной чертой "|". Например:
[а, b, с] эквивалентно [а| ] и, продолжая процесс,
[а | ] эквивалентно [а | ]], что эквивалентно [а| ] ]
Можно использовать оба вида разделителей в одном и том же списке при условии, что вертикальная черта есть последний разделитель. При желании можно набрать [а, b, с, d] как [а, b [с, d] ].
Использование списков
Список является рекурсивной составной структурой данных, поэтому нужны алгоритмы для его обработки. Главный способ обработки списка - это просмотр и обработка каждого его элемента, пока не будет достигнут конец.
Алгоритму этого типа обычно нужны два предложения. Первое из них говорит, что делать с обычным списком (списком, который можно разделить на голову и хвост), второе - что делать с пустым списком.
Подсчет элементов списка
Проверка нахождения в списке
3. Функциональные возможности Visual Prolog
1. Модульное программирование
2. объектный механизм
3. Средства создания графического интерфейса
1. Модульное программирование
Способность системы работать с программами, разбитыми на модули, - это еще одна положительная черта Visual Prolog. Вы можете писать, компоновать и компилировать модули раздельно, а затем связывать их вместе, чтобы создать одну выполняемую программу. Если вам надо изменить программу, то достаточно только отредактировать и перекомпилировать отдельные модули, а не всю программу в целом. Это вы непременно оцените при написании больших программ. Кроме того, модульное программирование имеет еще и такое преимущество - по умолчанию все имена предикатов и доменов являются локальными. Это значит, что различные модули могут использовать одинаковые имена для разных целей. Visual Prolog использует две концепции для управления модульным программированием: глобальные объявления и проекты.
Глобальные объявления
По умолчанию все имена, используемые в модуле, являются локальными. Visual Prolog-программы взаимодействуют через границы модулей при помощи предикатов, определенных в разделах global predicates и в классах. Домены, определенные в этих глобальных разделах, должны быть определены как глобальные домены, либо должны быть стандартными доменами.
Начиная с версии 5.2, Visual Prolog обеспечивает управление глобальными объявлениями. А именно:
Главный модуль проекта (с разделом цели goal) должен содержать объявления всех глобальных доменов (и разделов глобальных фактов), объявленных во всех подмодулях проекта;
Любой другой проектный модуль содержит объявления только тех глобальных доменов, которые используются в этом модуле;
Глобальные объявления могут помещаться после локальных;
Если изменяется какое-либо глобальное объявление, то должны быть перекомпилированы только модули, включающие это объявление.
Глобальные домены
Вы делаете домен глобальным, записав его в разделе global domains. Во всем остальном глобальные домены аналогичны локальным.
Visual Prolog версии 5.2 предоставляет усовершенствованное управление глобальными доменами. Теперь не требуется, чтобы все модули содержали одинаковые объявления всех глобальных доменов в определенном порядке (в PDC Prolog и в версиях Visual Prolog до 5.2 для проверки этой идентичности использовалась специальная утилита chkdoms. exe). Теперь же вам нужно следовать двум правилам:
Только главный модуль проекта (с разделом цели) должен содержать объявления всех глобальных доменов (и разделов глобальных фактов), объявленных во всех подмодулях проекта;
Любой другой проектный модуль содержит объявления только тех глобальных доменов, которые используются в этом модуле.
Это дает следующие принципиальные преимущества:
Возможность создания и использования заранее скомпилированных библиотек (использующих глобальные домены);
Уменьшение времени компиляции: если изменяется какое-либо глобальное объявление, то должны быть перекомпилированы только модули, включающие это объявление;
Программы могут использовать больше доменов, т. к. модуль может включать только те глобальные домены, которые действительно используются в этом модуле.
Среда визуальной разработки Visual Prolog предоставляет гибкий автоматический механизм для управления включением объявлений глобальных доменов в модули проекта. Ядро этого механизма - диалоговое окно File Inclusion for Module, которое активизируется при создании нового модуля. Для небольших проектов вы можете использовать упрощенную стратегию обеспечения включения всех глобальных доменов в каждый проектный модуль. Для этого вам нужно:
Глобальные секции фактов
Раздел facts будет глобальным, если перед ключевым словом facts (можно использовать и устаревшее ключевое слово database) вставлено ключевое слово global.
Замечание
Размещать обязательно требующиеся инициализирующие предложения для single-фактов из глобальных секций фактов (баз данных) можно только после раздела goal в главном модуле проекта.
Поскольку Visual Prolog автоматически генерирует глобальный домен, соответствующий имени каждой глобальной секции фактов (базе данных), то все перечисленные правила управления глобальными доменами следует применить и к глобальным секциям фактов.
проекты
Если вы используете VDE, то эксперт приложений автоматически управляет созданием новых проектов и добавлением/удалением проектных модулей. Построитель программ (Make facility) VDE автоматически совершает операции компиляции и компоновки, необходимые для создания целевого модуля из исходных модулей проекта.
Следовательно, нужно объяснить здесь всего две особенности, которые будут важны в случае использования командной строки для вызова компилятора:
Как Visual Prolog-проект использует таблицу символов.
Visual Prolog-программы должны иметь цель (содержать Goal-секцию).
По умолчанию компилятор проверяет, имеет ли компилируемый файл раздел цели (Goal), и, если не имеет, - генерирует ошибку. Но в многомодульных проектах только один (главный) модуль проекта содержит раздел цели. Чтобы скомпилировать другие модули проекта, компилятор нужно проинформировать о том, что эти модули являются частями проекта и именно поэтому не содержат раздел цели. Это делается опцией компилятора командной строки - г.
Классы и объекты
Visual Prolog включает в себя объектный механизм, объединяющий парадигмы логического и объектно-ориентированного программирования (ООП).
Для того чтобы система могла рассматриваться как объектно-ориентированная, необходимо, чтобы она удовлетворяла четырем критериям. Это:
инкапсуляция;
наследование;
индивидуальность.
Инкапсуляция
Необходимость инкапсуляции и модульности хорошо известны. Инкапсулированные объекты помогают создавать более структурированные и читаемые программы, поскольку объекты могут рассматриваться как "черные ящики". Посмотрите на сложную программу и найдите часть, которую вы можете объявить и описать. Инкапсулируйте ее в объект, постройте интерфейс и продолжайте в том же духе, пока не будут объявлены все подпроблемы, составляющие программу. Когда вы разобьете всю программу на объекты и удостоверитесь, что каждый из них работает корректно, вы сможете абстрагироваться от них.
ООП также известно как программирование, управляемое данными. Фактически, вы позволяете объектам делать работу самим. Они содержат методы, которые вызываются при создании объектов, при их удалении и, вообще, при любых обращениях к объектам. Методы могут вызывать и методы других объектов.
Объекты и классы
Способы хранения данных в традиционных языках программирования обычно трудны для понимания и не подходят для моделирования. С объектами работать гораздо проще, т. к. они близки к человеческому восприятию реальных вещей и сами по себе являются инструментом для моделирования.
Объект - гораздо более сложная структура данных, чем список. На элементарном уровне, объект - это объявление согласованных между собой данных. Это объявление может содержать предикаты, которые работают с этими данными. В соответствии с терминологией ООП эти предикаты называются методами. Каждый класс представляет собой уникальный тип объектов и операций (методов), способных создавать такие объекты, удалять и манипулировать ими.
Класс - это определяемый пользователем тип объекта; класс может создавать объекты этого типа. Экземпляр - это фактическое состояние объекта. Вы можете определить столько экземпляров (объектов) класса, сколько вам необходимо.
Наследование
ООП - мощный инструмент для моделирования. Объекты могут быть определены на наиболее подходящем уровне абстракции . Относительно этого уровня объекты-наследники могут быть определены на более низких уровнях, или объекты-родители - на более высоких уровнях. Объект может наследовать данные и методы от объектов, определенных на более высоких уровнях. Таким образом, объекты - наиболее простой путь к созданию модульных программ.
Индивидуальность
Каждый объект уникален. Объекты изменяют свое состояние, и, т. к. состояния объектов можно наблюдать только посредством их предикатов-членов (т. е. предикатов, объявленных внутри определения класса), объект идентичен лишь самому себе. Таким образом, даже если состояния двух объектов одинаковы, объекты не являются идентичными, ибо мы можем изменять состояние одного объекта, не изменяя при этом состояния другого, и в этом случае объекты становятся не идентичными.
Очень важной характеристикой объекта является то, что индивидуальность сохраняется, даже несмотря на изменение его атрибутов. Мы всегда получаем доступ к объекту через ссылку на него. К нему можно получить доступ и через множество различных ссылок, а, т. к. объект идентичен только самому себе, мы можем организовать несколько ссылок на один и тот же объект.
Средства создания графического интерфейса
Визуальный интерфейс программирования VPI (Visual Programming Interface) - высокоуровневый программный интерфейс, разработанный для облегчения создания программ на Visual Prolog, способный поддерживать сложные интерфейсы, использующие графические возможности современных операционных систем. Окна, меню, диалоговые окна, элементы управления, перья, кисти, курсоры, рисунки и т. д. - все эти ресурсы и инструментальные средства входят в состав Visual Prolog как простые структуры,
VPI делает возможным создание переносимого исходного кода, который может быть откомпилирован, чтобы работать в 16-разрядной конфигурации под MS Windows 3.1*, 32-разрядной - под Windows 95/98/ME, Windows NT/2000, под администратором представлений OS/2.
Управляемые событиями приложения
Современная операционная система, кроме обеспечения уровня, сервиса, активно вовлечена в процесс выполнения всех приложений. Приложение взаимодействует с пользователем косвенно через операционную систему. Когда пользователь делает что-либо (нажимает клавишу, перемещает мышь, щелкает на пиктограмме и т. д.), интерфейс аппаратного обеспечения генерирует событие, операционная система переводит это событие в стандартизированный формат сообщения и посылает уведомительное сообщение вызвавшему его элементу. Обычно это окно, которое является активным.
События могут достигать приложения асинхронно, поэтому приложение должно быть написано так, чтобы обеспечить целостность всех данных и процессов независимо от последовательности событий. Приложения, основанные на графическом интерфейсе пользователя, должны реагировать на свое окружение и не могут имитировать стандартное поведение приложений DOS. Приложения позади неактивных окон могут оставаться активными, могут писать или рисовать в своих неактивных окнах, и все это будет отображаться, если окно не закрыто или не перекрыто другим. Приложение может в любое время активизировать одно из своих окон, чтобы запросить входные данные. Активное на этот момент окно становится неактивным, но его приложение продолжает работать.
Вообще, во время работы могут возникать самые разные ситуации, например, пользователь может получить срочный телефонный звонок. На него можно ответить, выбрав системную кнопку окна Task или меню файла и закрыв приложение. Операционная система сообщает приложению о событии, посылая сообщение обработчику событий окна Task . В большинстве многозадачных системах операционная система может приостановить ваше приложение в любое время. Приложение никогда не будет знать, запрашивал ли пользователь закрытие или это операционная система обнаружила сбой питания. Или если приложение хочет закрыть какое-то окно, то оно посылает этому окну запрос на закрытие CloseRequest точно так же, как пользователь, когда он выбирает команду Close в меню окна Task .
Конечно, вы можете уменьшить количество возможных событий и сообщений, блокируя пункты меню и кнопки управления. Часть обработки сообщений GUI-приложений может быть очень сложной, но это цена за большую гибкость. Пролог и VPI существенно упрощают работу программиста по связыванию приложения с GUI операционной системы. Эксперт кода и браузер (The Code Expert and the Browser) облегчают поиск и обработку кода, который соответствует определенному событию, отвечая на определенное сообщение, и вы редко будете иметь дело с запутанными деталями основной логики передачи сообщений.
Окна
Окно представляет собой прямоугольное пространство на экране. Окно используется приложением для вывода и ввода данных . Все пространство экрана рассматривается как специальное "экранное окно". Каждое окно разделяет экран с другими окнами, включая окна иных приложений, а иногда и операционной системы. Эти окна могут перекрывать друг друга.
Независимо от того, сколько приложений одновременно запущено, в любой момент времени активизировано лишь одно окно, т. е. только это окно может получать входные данные от пользователя. Активное окно всегда находится поверх остальных окон.
Все предикаты динамического создания окон формируют структуру в памяти, затем они отображают окно согласно этой управляющей структуре и присваивают окну дескриптор, который является уникальным номером. Дескрипторы присваиваются всем окнам, как видимым, так и скрытым. Почти все остальные VPI-предикаты в качестве входного параметра требуют дескриптор окна для доступа к нему. Загружаемые и готовые для использования ресурсы всех видов также имеют идентификаторы или дескрипторы, с помощью которых к ним можно обращаться.
Каждое окно или диалоговое окно в приложении представлены не только структурой памяти, но также и предикатом обработчика событий окна, которому VPI посылает сообщения при возникновении пользовательских или системных событий, связанных с окном. Причем эти сообщения не обязательно синхронизированы с приложением. Приложение также может посылать события любому из своих обработчиков событий. В VPI названия событий из домена событий всегда имеют префикс е_.
Типы окон
Окна классифицируются по типам. Типы окон должны принадлежать домену windowtype и иметь префиксы w_ (для окон), wc_ (для элементов управления) или wd_ (для диалоговых окон). Тип окна может быть получен по дескриптору окна вызовом предиката win_GetType. Возможные типы окон перечислены.
Обычное окно документа
Дочернее окно
Окно экрана Screen
Модальное диалоговое окно
Немодальное диалоговое окно
Командная кнопка
Переключатель
Горизонтальная полоса прокрутки
Вертикальная полоса прокрутки
Поле редактирования
Статический текст
Раскрывающийся список
Поле редактирования с раскрывающимся списком
Групповой блок
Пиктограмма
Специальные (определяемые пользователем) элементы управления
Внутреннее окно, используемое во время печати
Внутреннее окно, используемое во время создания изображений
Внутреннее окно, используемое во время создания метафайлов/
Цель урока: Знакомство с историей языка программирования Prolog, основы работы с компиляторами
Prolog (Pro gramming in log ic) — это язык высокого уровня, не алгоритмический, предназначенный для написания программ с использованием концепций и методов .
История
Пролог был разработан в Марсельском университете во Франции Алэном Колмероэ и другими членами «группы искусственного интеллекта» в 1973 году. Данная команда энтузиастов разработала программу, предназначенную для доказательства теорем. Написана она была на Фортране, и использовалась при построении систем обработки текстов на естественном языке. Работала программа довольно медленно и назвалась Prolog (от Programmation en Logique на франц.). Программа послужила прообразом Пролога.
Язык логического программирования prolog — , что означает, что программа, написанная на нем, выглядит как набор логических описаний, определяющих цель, ради которой она и написана .
В основе Пролога лежит раздел математической логики, называемый исчисление предикатов . Его базис составляет процедура доказательства теорем методом резолюции для хорновских дизъюнктов .
Логика предикатов - это простейший способ объяснить, как «работает» мышление.
По сути, Prolog представляет собой не столько язык для программирования, сколько средство для описания данных и логики их обработки. Поскольку язык не алгоритмический, то и программа на Прологе не содержит явных алгоритмических конструкций типа условных или циклических операторов, т.е. не является программой в классическом понимании. Написанная на Прологе, она представляет собой модель фрагмента предметной области на решение проблемы которой и направлена задача. Само решение задачи записывается не в терминах компьютера, как это принято в , а в терминах предметной области решаемой задачи, по сути, в духе .
Пролог включает механизм вывода, который основан на сопоставлении образцов, с помощью подбора ответов на запросы он извлекает хранящуюся (известную) информацию.
Области применения языка Prolog и декларативных языков в целом
- Реализация систем искусственного интеллекта.
- Создание экспертных систем и оболочек экспертных систем.
- Разработка систем помощи принятия решений.
- Разработка систем обработки естественного языка.
- Построение планов действий роботов.
- и т.п.
Особенности языка
- Описание проблемы и правил ее решения.
- Нахождение всех возможных решений с помощью механизма поиска с возвратом (backtracking).
- Легкий синтаксис.
Версии и компиляторы
На сегодня существует довольно много реализаций Пролога. Но самый первый компилятор языка был создан Уорреном и Перейрой в 1977 году в Эдинбурге, компилятор предназначался для ЭВМ DEC–10. Тот самый компилятор, известный как реализация под названием «эдинбургская версия», фактически стал первым и единственным стандартом языка и послужил прототипом для многих последующих реализаций Пролога. Интересным фактом является то, что компилятор был написан на самом Прологе.
Изучать Пролог без привязки к конкретной его версии не совсем целесообразно. Версий Пролога очень много, но мы выберем наиболее известную в России и довольно эффективную версию Пролога - Турбо Пролог . Начинала разработку версии (реализации) фирма Borland International совместно с датской компанией Prolog Development Center (PDC ). Первая версия вышла в 1986 году. Последняя совместная версия 1988 года вышла под номером 2.0.
Рис. 1. Сайт центра разработки Prolog (Prolog Developement Center)
Остальные версии начиная с 1990 года, когда PDC получила монопольное право на Турбо Пролог, продвигались под названием PDC Prolog.
Таким образом, в 1992 году вышла версия PDC Prolog 3.31, а в 1996 году, при участии группы питерских программистов, PDC выпустила систему Visual Prolog 4.0, у которой много достоинств, но мы не будем на них останавливаться.
Для работы мы выберем самый простой компилятор TPtolog (Турбо Пролог).
К достоинствам Турбо Пролога относится возможность присоединять к программе на этом языке процедуры, написанные на Паскале, Си , Фортране или ассемблере.
Для работы в Tprolog с 68 битной системой необходимо использовать программу для эмуляции DOS (например, dosbox).
Алгоритм работы с программой следующий:
- запуск dosbox
- mount c c:\dos\TProlog
- c: => enter
- prolog => enter
- Набор кода программы в редакторе «notepad++» и сохранение с расширением.PRO в папке tprolog\labs
Работа в Tprolog
Горячие клавиши и основные команды:
- F10 , Esc — переход в главное меню.
- Esc — выход из текущего пункта / отмена.
- Меню Edit — переход к редактированию кода.
- Меню Files -> New File — создание нового файла.
- Меню Compile -> Memory -> Меню Run — компиляция и запуск программы.
При работе в tprolog иногда возникают нестандартные ситуации, когда программа не реагирует на нажатия клавиш. Если не открывается какой-либо пункт меню – то надо несколько раз нажать клавишу i .
Запуск программы осуществляется :
- Через написание раздела GOAL и запуска программы в меню compile и run .
- Работа с окном DIALOG (в таком случае раздел GOAL в программе не нужен).
Запуск программы при использовании раздела GOAL
- Compile — компилируем
- Run — запускаем
- Esc – выход в меню
Работа с окном dialog
- Команда Run .
- Окно dialog .
- Запрос в виде: postroil (jack,house) .
Раздел Goal программы нельзя использовать, если работа осуществляется в окне dialog
Логическое программирование базируется на убеждении, что не человека следует обучать мышлению в терминах операций компьютера, а компьютер должен выполнять инструкции, свойственные человеку. В чистом виде логическое программирование предполагает, что инструкции даже не задаются, а сведения о задаче формулируются в виде логических аксиом. Такое множество аксиом является альтернативой обычной программе. Подобная программа может выполняться при постановке задачи, формализованной в виде логического утверждения, подлежащего доказательству (целевого утверждения ).
Идея использования логики исчисления предикатов I порядка в качестве основы языка программирования возникла в 60-е годы, когда создавались многочисленные системы автоматического доказательства теорем и вопросно-ответные системы. В 1965 г. Робинсон предложил принцип резолюции, который в настоящее время лежит в основе большинства систем поиска логического вывода. Метод резолюций был использован в системе GPS (general problem solver). В нашей стране была разработана система ПРИЗ, которая может доказать любую теорему из школьного учебника геометрии.
Язык программирования PROLOG (programming in logic) был разработан и впервые реализован в 1972 г. группой сотрудников Марсельского университета во главе с Колмероэ. Группа занималась проблемой автоматического перевода с одного языка на другой. Основа этого языка - исчисления предикатов I порядка и метод резолюций.
При программировании на Прологе усилия программиста должны быть направлены на описание логической модели фрагмента предметной области решаемой задачи в терминах объектов предметной области, их свойств и отношений между собой, а не деталей программной реализации. Фактически Пролог представляет собой не столько язык для программирования, сколько язык для описания данных и логики их обработки. Программа на Прологе не является таковой в классическом понимании, поскольку не содержит явных управляющих конструкций типа условных операторов, операторов цикла и т. д. Она представляет собой модель фрагмента предметной области, о котором идет речь в задаче. И решение задачи записывается не в терминах компьютера, а в терминах предметной области решаемой задачи, в духе модного сейчас объектно-ориентированного программирования.
Суть Пролога – программирование в терминах целей. Программист описывает условие задачи, пользуясь понятиями объектов различных типов и отношений между ними, и формулирует вопрос. PROLOG-система обеспечивает ответ на вопрос, находя автоматически последовательность вычисления решения, используя встроенную процедуру поиска. До 1981 г. число исследователей, занимавшихся логическим программированием, составляло около сотни во всем мире. В 1981 году PROLOG был выбран в качестве базового языка компьютеров пятого поколения, и количество исследователей логического программирования резко возросло. Одной из наиболее интересных тем исследований является связь логического программирования с параллелизмом.
Где же используется Пролог в настоящее время? Это область автоматического доказательства теорем, построение экспертных систем, машинные игры с эвристиками (например, шахматы), автоматический перевод с одного языка на другой.
В настоящее время создано достаточно много реализаций языка Пролог: Wisdom Prolog, SWI Prolog, Turbo Prolog, Visual Prolog, Arity Prolog и т.д.
В нашем курсе будем использовать SWI Prolog. SWI-Prolog развивается с 1987 года. Его создателем и основным разработчиком является Ян Вьелемакер (Jan Wielemaker). Название SWI происходит от Sociaal-Wetenschappelijke Informatica (гол. социально-научная информатика), первоначального названия группы в Амстердамском университете, где работает Вьелемакер.
SWI-Prolog позволяет разрабатывать приложения любой направленности, включая Web-приложения и параллельные вычисления, но основным направлением использования является разработка экспертных систем, программ обработки естественного языка, обучающих программ, интеллектуальных игр и т.п. Это интерпретатор. Файлы, содержащие программы, написанные на языке SWI Prolog, имеют расширение pl.
SWI-Prolog-Editor является средой программирования для языка SWI-Prolog, включающую редактор программ с подсветкой синтаксиса, интерпретатор и отладчик программ. Основным назначением среды является обучение логическому программированию на языке Prolog.
Сначала устанавливаем SWI Prolog, затем - SWI Prolog Editor. Для запуска редактора SWI Prolog Editor необходимо запустить файл SwiplEdit.exe. Для настройки работы интерпретатора в специальном окне редактора, следует установить путь к интерпретатору, выполнив в редакторе команду Окно-Конфигурация на закладке Программы установить в строке Папка Пролога путь к интерпретатору. Там же, на закладке Настройки необходимо установить поле Codepage равным cp1251. Настройка кодовой страницы необходима для правильного сопоставления строковых констант, набранных русским алфавитом, между текстом программы в среде SWI-Prolog-Editor и языком SWI-Prolog. Для запуска программы из панели редактирования программ ее следует сохранить и нажать функциональную клавишу F9 или соответствующий значок на панели инструментов. В случае успешной загрузки на панели запросов появится:
Consult(<имя файла>).
Загрузить файл можно так же с помощью команды: [<имя файла>].
После любой модификации программу требуется заново загрузить в память. Перезапуск интерпретатора Пролога осуществляется нажатием Ctrl+F9 или соответствующего значка на панели инструментов.
Для выхода из интерпретатора Пролога используется команда: halt.
Факты и правила
Как уже отмечалось Пролог использует исчисление предикатов первого порядка. Предикаты определяют отношения между объектами. Рассмотрим дерево родственных отношений:
Рисунок 10 - Дерево родственных отношений
Пример 1: Это дерево можно описать следующей Пролог-программой.
родитель(пам, боб).
родитель(том, боб).
родитель(том, лиз).
родитель(боб, энн).
родитель(боб, пат).
родитель(пат, джим).
У нас имеется отношение родитель между двумя объектами. Описаны 6 фактов наличия отношений между конкретными объектами. Имена объектов начинаются с маленьких букв (они являются константами). В Прологе принято соглашение, что константы начинаются с маленькой буквы, а переменные – с большой. После набора такой Пролог-программы в редакторе можно загрузить программу в Пролог и задавать вопросы, касающиеся отношения родитель.
Запрос к программе набирается после приглашения?- и должен заканчиваться точкой. Для выполнения набранного запроса необходимо нажать Enter. Ответ будет выдан под запросом. Запрос может быть набран в несколько строк - для перехода на новую строку используется клавиша Enter. В том случае, если строка будет заканчиваться точкой и будет нажата клавиша Enter SWI-Prolog начнет выполнение запроса. Если возможны несколько вариантов ответа на запрос, то для получения каждого следующего используется клавиша Enter. Варианты ответов SWI-Prolog отделяет друг от друга точкой с запятой. Прекратить выполнение программы (выдачу альтернативных ответов) можно нажав клавишу «a».
Вопросы могут быть простые и сложные (в качестве связки «и» при составлении сложного вопроса используется запятая). Ответы Пролог-системы выводятся сразу после вопроса. Могут быть следующие варианты ответов:
No (соответствует нет или не найдены значения переменных в вопросе);
Перечисляются возможные значения переменных в вопросе. При этом при нажатии клавиши «a» поиск решений прекращается, а при нажатии клавиши Enter, продолжается поиск новых решений до тех пор, пока не будут найдены все. Альтернативные решения разделяются точкой с запятой. Вывод завершается словом Yes, если не все решения были найдены и No, если других решений не осталось.
Вопрос относительно отношения родитель |
Вопрос в Пролог-системе |
Ответ Пролог-системы |
Боб является родителем Пат? |
родитель(боб,пат). | |
Пат – ребенок Лиз? |
родитель(лиз,пат). | |
Кто родители Лиз? |
родитель(X,лиз). | |
Кто дети Энн? |
родитель(энн, X). | |
Кто дети Боба? |
родитель(боб,X). | |
Есть ли дети у Лиз? |
родитель(лиз,_). | |
Кто чей родитель? |
родитель(X,Y). | |
Кто внуки Тома? |
родитель(том,X), родитель(X,Y). | |
Кто родители родителей Джима? |
родитель(X,джим), родитель(Y,X). |
Итак, в простейшем случае Пролог-программа описывает факты и правила.
Факт – это безусловное утверждение (всегда истинное), характеризующее объект с некоторой стороны или устанавливающее отношение между несколькими объектами. Факт не требует доказательств. Факт имеет следующий вид:
<имя предиката>(O 1 ,O 2 ,…,O n).
Обратим внимание на то, что в конце факта ставится точка. <имя предиката> должно начинаться со строчной буквы и может содержать буквы, цифры, знаки подчеркивания. О i (i = 1,..,n) - аргументы предиката могут быть конкретными объектами (константами) или абстрактными объектами (переменными). Если конкретные объекты начинаются с буквы, то эта буква должна быть строчной.
Переменные начинаются с прописной буквы или символа подчеркивания. Переменная в Прологе, в отличие от алгоритмических языков программирования, обозначает объект, а не некоторую область памяти. Пролог не поддерживает механизм деструктивного присваивания, позволяющий изменять значение инициализированной переменной, как императивные языки. Переменные могут быть свободными или связанными. Свободная переменная – переменная, которая еще не получила значения. Она не равняется ни нулю, ни пробелу; у нее вообще нет никакого значения. Такие переменные еще называют неконкретизированными. Переменная, которая получила какое-то значение и оказалась связанной с определенным объектом, называется связанной. Если переменная была конкретизирована каким-то значением и ей сопоставлен некоторый объект, то эта переменная уже не может быть изменена.
Областью действия переменной в Прологе является одно предложение. В разных предложениях может использоваться одно и то же имя переменной для обозначения разных объектов. Исключением из правила определения области действия является анонимная переменная, которая обозначается символом подчеркивания. Анонимная переменная предписывает интерпретатору проигнорировать значение переменной. Если в правиле несколько анонимных переменных, то все они отличаются друг от друга, несмотря на то, что записаны с использованием одного и того же символа.
Правило – утверждение, которое истинно при выполнении некоторых условий. Правило состоит из условной части (тела) и части вывода (головы). Головой правила является предикат, истинность которого следует установить. Тело правила состоит из одного или нескольких предикатов, связанных логическими связками: конъюнкция (обозначается запятой), дизъюнкция (обозначается точкой с запятой) и отрицание (означается not или \+). Правило имеет следующий вид:
<голова правила > :– <тело правила>.
В конце правила так же ставится точка. Можно считать, что факт – это правило, имеющее пустое тело.
С помощью правил можно описывать новые отношения.
Пример: Пусть имеется двуместное отношениеродительи одноместное отношение мужчина. Эти отношения описываются в виде фактов. Опишем новое двуместное отношениедед, используя правила.Xявляется дедомY, если существует цепочка:X– родительZ,Z– родительY, при этомXдолжен быть мужчиной.
дед(X,Y):–родитель(X,Z),родитель(Z,Y),мужчина(X).
Пример: Пусть имеется двуместное отношение родитель, описанное в виде фактов. Опишем новое двуместное отношение предок, используя правила. X является предком Y, если X – родитель Y или существует цепочка людей между Х и Y, связанных отношением родитель.
предок(X,Y):–родитель(X,Y).
предок(X,Y):–родитель(X,Z),предок(Z,Y).
Эти правила можно записать по-другому:
предок(X,Y):–родитель(X,Y);
родитель(X,Z),предок(Z,Y).
В данном примере получили рекурсивное определение отношения предок.
Пример. Определим двуместное отношение дальний_родственник с помощью правила, используя имеющееся отношение предок. X является дальним родственником Y, если они связаны отношением предок, но при этом не связаны отношением родитель.
дальний_родственник (X,Y):–предок(X,Y),not(родитель(X,Y));
предок(Y,X),not(родитель(Y,X)).
В правой части правила для сравнения можно использовать знаки @<, @=<, @>=, @> для проверки на упорядоченность, == для проверки на равенство и \== для проверки на неравенство.
Данный урок посвящен базовым понятиям языка Prolog. Так, на уроке будут изучаться основы написания программ на Прологе
Для начала вспомним нормальную форму Бэкуса-Наура (БНФ) , которая была создана для формального описания синтаксиса языков программирования в 1960 году . Ее авторы — Джон Бэкус и Питер Наур.
Итак, в БНФ приняты следующие обозначения:
Символ::= читаемый как «по определению» («это», «есть»). Слева от символа располагается объясняемое понятие, справа — разъясняющая конструкция. Например,
<Имя> ::= <Идентификатор>
Части выражения, используемые для обозначения синтаксической конструкции языка, берутся в угловые скобки; в нашем примере это <Имя> и <Идентификатор> .
Символ | означает логическое «или» и применяется для разделения различных равнозначных альтернативных объяснений определяемого понятия.
Используя данный символ можно, например, определить десятичную цифру:
<цифра> ::= 0|1|2|3|4|5|6|7|8|9
Если часть конструкции заключена в квадратные скобки , то это означает, что она является необязательной, т.е. может отсутствовать.
Так запись
<Целое число> ::= [-]<Положительное целое число>
говорит о том, что целое число можно объяснить как положительное целое число, перед которым может стоять знак минус (а может и не стоять).
Символ * указывает на то, что стоящая перед ним синтаксическая конструкция может повторяться произвольное количество раз (начиная с ноля и выше). Вместо символа * иногда используются фигурные скобки ({, }), по сути равнозначные ему.
Снова определим положительное целое число, используя нотацию БНФ:
<Положительное целое число> ::= <цифра>[<цифра>]*.
Что означает, что положительное целое число состоит из одной или нескольких цифр.
Структура программы на языке Prolog
Стандартная программа на языке состоит из следующих разделов :
- Constants
- Domains
- Predicates
- Clauses
- Goal
Необязательный раздел определения констант.
Раздел описания доменов (аналогичен описанию типов данных).
В Turbo Prolog можно выделить простые типы данных
:
char — символьный тип
integer — целое число
real — вещественное число
string — последовательность символов типа char, которая заключена в кавычки
symbol — последовательность букв латинского алфавита, цифр и знаков подчеркивания, которая начинается со строчной буквы (тогда без кавычек) или заключена в кавычки (тогда можно с прописной буквы)
Раздел описания предикатов (аналогичен разделу описания процедур и функций); по сути представляет собой шаблон написания фактов в разделе Clauses.
Утверждения (аналог: тело основной программы).
Целевое утверждение – «цель».
Задание prolog 2_1: Запустите компилятор . Создайте новый файл и наберите код программы, выводящий ответ на вопрос «Любит ли Мэри яблоки?» (ответ true или false). Код представлен ниже:
domains a= symbol predicates likes (a, a) clauses likes (mary, apples) . |
domains a=symbol predicates likes (a,a) clauses likes (mary,apples).
Перейдите в окно Dialog (меню Run) и введите запрос:
likes(mary, apples) |
likes(mary,apples)
В результате в окне должен появиться ответ true
Факты и правила
Часто программу, написанную на Прологе, называют базой знаний
.
База знаний на Прологе состоит из предложений , т.е. утверждений, каждое из которых завершается точкой .
Существует два вида предложений: факты и правила .
Предложения-правила имеют вид:
A:- B1,… , Bn.
Где A — это заголовок или голова предложения, а B1,..., Bn – это тело .
Факт обычно утверждает , что между объектами выполнено некоторое отношение и состоит из :
- отношения
- объекта или объектов, заключенных в круглые скобки (аргументы)
- завершается точкой (.)
Пример факта:
likes (bill, dogs) . |
likes (bill, dogs).
где likes — факт
bill , dogs — аргументы факта, между которыми выполнено отношение (likes)
Т.к. отношение в математической логике принято называть предикатами , то и мы иногда будем использовать понятие «предикат» вместо «факта» или «правила» .
Таким образом, предикат (факт) может состоять либо только из имени, либо из имени и следующей за ним последовательности параметров (аргументов) , которые заключаются в скобки.
Если факт состоит только из заголовка, то можно сказать, что факт – это предложение, у которого тело пустое .
Аргументом факта или предиката может быть константа , переменная или составной объект; от их числа зависит так называемая местность (n-местность) факта.
Отличие константы от переменной: константа получает свое значение в разделе описания констант , тогда как переменная инициализируется в процессе работы программы .
В TProlog имя предиката или факта может содержать: латинские буквы, цифры, знаки подчеркивания и начинаться с буквы или знака подчеркивания.
В следующем примере наводите курсор на части конструкций, и появится подсказка:
likes
(bill, dogs).
- Билл любит собак.
bird
(vorobej).
Птица – воробей.
Таким образом, в примере likes — это имя двухаргументного предиката (факта), у которого строковая константа « bill » является первым аргументом, а « dogs » — вторым аргументом.
Аргументы с известными или постоянными значениями должны начинаться со строчных букв
Задание prolog 2_2: Дано начало программы (раздел domains и predicates) для базы данных «Возраст ребенка» . Составить факты для программы, основываясь на данных указанных разделов и следующих сведений: Ивану 2 года, Алексу 3 года, Марии — 5 лет.
domains a= symbol b= integer predicates age(a, b) clauses age(...,... ) . ... (...,... ) . ... (...,... ) . |
domains a=symbol b=integer predicates age(a,b) clauses age(...,...). ...(...,...). ...(...,...).
Наберите код программы в компиляторе.
Цели
Цель — это формулировка задачи, которую программа должна решить. Цель также служит «триггером» для запуска программы.
Турбо-Пролог использует как , которые содержатся в программе, так и , которые вводятся с клавиатуры после запуска программы. Здесь существует два варианта:
- Если цель является фактом , то Турбо-Пролог отвечает True (истина) или False (ложь):
goal likes(mary,X).
Дословно: Что любит Мэри?
Важно: Переменные начинаются с прописных букв
* Понятие переменной в Прологе будет рассмотрено в .
Таким образом, цель состоит из взаимосвязанных предикатов. Ее структура точно такая же, как у факта. Т.е. цель зачастую совпадает с правилом или фактом .
Так, наш пример может быть как фактом, так и целью:
likes(mary,apples). — Мэри любит яблоки и Любит ли Мэри яблоки?
Алгоритм составления программы
Программа для компилятора TProlog состоит из разделов, рассмотренных в примере:
clauses likes (mary,apples). likes(mary,oranges). color(apples,red).
goal likes(mary, X) , write ("mary lyubit ", X) . |
goal likes(mary,X),write("mary lyubit ", X).
Результатом примера будет: «mary lyubit apples» .
В данном примере цель записана в виде раздела GOAL прямо в программе, но нужно иметь в виду, что чаще всего цели, требующие логический ответ (правда или ложь), записываются в окне Dialog (goal в программе тогда не пишется)
Бесконечный цикл
В примере, описанном выше, в результате выдается значение только первого из трех фактов:
clauses likes (mary, apples) . likes(mary, oranges) . color(apples, red) . goal likes(mary, X) , write ("mary lyubit ", X) . |
clauses likes (mary,apples). likes(mary,oranges). color(apples,red). goal likes(mary,X),write("mary lyubit ", X).
Результат выдает только apples . Хотя еще есть oranges.
Чтобы выдать все значения, необходимо организовать бесконечный цикл , который в коде выглядит как оператор fail , установленный в конце раздела GOAL
Раздел gaol того же примера, но с бесконечным циклом будет выглядеть так:
goal likes(mary, X) , write ("mary lyubit ", X) , nl , fail . |
goal likes(mary,X),write("mary lyubit ", X),nl,fail.
nl — означает переход на следующую строку (каждое значение выводится с новой строки).
Результат:
«mary lyubit apples»
.
«mary lyubit oranges»
.
Код программы целиком:
domains a= symbol predicates likes (a, a) clauses likes (mary, apples) . likes(mary, oranges) . color(apples, red) . goal likes(mary, X) , write ("mary lyubit ", X) , nl , fail . |
domains a=symbol predicates likes (a,a) clauses likes (mary,apples). likes(mary,oranges). color(apples,red). goal likes(mary,X),write("mary lyubit ", X),nl,fail.
Рассмотрим еще один пример.
Пример:
Составить базу фактов по стихотворению «Дом, который построил Джек»
.
Составить разные запросы к базе данных (выполнить часть запросов в окне Dialog , а другую часть в разделе Goal программы).
Код программы без запросов:
domains a= symbol predicates построил (a, a) хранится (a, a) ворует (a, a) ловит (a, a) треплет (a, a) доит (a, a) бранится (a, a) будят (a, a) clauses построил (джек, дом) . хранится (пшеница, чулан_дома) . ворует (птица_синица, пшеница) . ловит (кот, птица_синица) . треплет (кот, птица_синица) . треплет (пес, кот) . доит (старушка, корова) . бранится (пастух, старушка) . будят (два_петуха, пастух) . |
domains a=symbol predicates построил (a,a) хранится (a,a) ворует (a,a) ловит (a,a) треплет (a,a) доит (a,a) бранится (a,a) будят (a,a) clauses построил (джек,дом). хранится (пшеница, чулан_дома). ворует (птица_синица, пшеница). ловит (кот, птица_синица). треплет (кот, птица_синица). треплет (пес, кот). доит (старушка, корова). бранится (пастух, старушка). будят (два_петуха, пастух).
Выполнение запросов в окне dialog:
Построил (Х, дом). /*Кто построил дом?*/
Ответ: Х=Джек
? – ловит (кот, Y) /*Кого ловит кот?*/
Ответ: Y= птица_синица
? – хранится (X, чулан_дома), ворует (X,Y). /*Что хранится в чулане дома и кто ворует это */
Ответ: X = пшеница, Y= птица_синица
Выполнение запросов в разделе Goal:
goal postroil(X, house) , write (X) , nl , fail . |
goal postroil(X,house),write(X),nl,fail.
Задание prolog 2_3:
- Составить базу данных «Именины и хобби друзей» .
- чьи именины в сентябре?
- когда именины у Ивана?
- кто любит танцы?
- кто любит книги и спорт?
- что любит Петр?
domains a= symbol b= integer predicates birthday(a, b, a) likes(a, a) clauses birthday(nataly, 8 , september) . birthday(yana, 25 , august) . birthday(nina, 28 , september) . birthday(peter, 2 , august) . birthday(ivan, 12 , august) . likes(nataly, books) . likes(nataly, sport) . likes(yana, books) . likes(yana, dances) . likes(peter, music) . likes(peter, dances) . likes(ivan, sport) . likes(ivan, books) . Goal /* birthday(X,Y,september),write(X," rodilas ", Y, " sentyabrya"),nl,fail.*/ |
domains a=symbol b=integer predicates birthday(a,b,a) likes(a,a) clauses birthday(nataly, 8, september). birthday(yana, 25, august). birthday(nina, 28, september). birthday(peter, 2, august). birthday(ivan, 12, august). likes(nataly, books). likes(nataly, sport). likes(yana, books). likes(yana, dances). likes(peter, music). likes(peter, dances). likes(ivan, sport). likes(ivan, books). Goal /* birthday(X,Y,september),write(X," rodilas ", Y, " sentyabrya"),nl,fail.*/ … , write(…), nl, fail.
Задание prolog 2_4:
- Составить базу данных «Предметы и преподаватели» , содержащую информацию о названии предмета, должности и фамилии преподавателя, номер семестра, отчетность.
- Составить запросы к базе данных, исходя из приведенных ниже:
- по каким предметам экзамен?
- какой предмет и когда читает доцент морозов?
- какая отчетность по тои?
- кто и когда читает ПРЗ?
domains a= symbol b= integer predicates teach(a, a, a, b) vedomost(a, a) clauses teach(prz, assistent, ivanova, 2 ) . teach(toi, docent, morozov, 4 ) . teach(mpi, docent, petrova, 5 ) . vedomost(toi, exam) . vedomost(prz, zach) . vedomost(mpi, exam) . Goal /* vedomost(X,exam) ,write("exam po predmetu ", X),nl,fail. */ … , write (…) , nl , fail . |
domains a=symbol b=integer predicates teach(a,a,a,b) vedomost(a,a) clauses teach(prz, assistent,ivanova,2). teach(toi, docent, morozov,4). teach(mpi,docent, petrova, 5). vedomost(toi, exam). vedomost(prz, zach). vedomost(mpi, exam). Goal /* vedomost(X,exam) ,write("exam po predmetu ", X),nl,fail. */ … , write(…), nl, fail.
* Для удобства после выполнения очередного запроса, комментируйте его (/* ... */) и приступайте к написанию кода следующего запроса.
* При использовании материалов обязательна ссылка на