Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Лабы_ЭкспСист / Лабораторная №3

.doc
Скачиваний:
15
Добавлен:
09.02.2015
Размер:
88.06 Кб
Скачать

Лабораторная работа №3.

Предикаты.

Цель работы: Получить представление о предикатах Visual Prolog.

Задание: Реализовать две программы по рисованию карты.

Порядок выполнения:

3.1.Получите начальные сведения о предикатах Visual Prolog.

3.2.Создайте проект mapDataBase. Реализуйте программу находящую единственное решение.

3.3. Создайте проект drawMap. Реализуйте программу находящую множественные решения.

3.1. Предикаты

Предикаты это функции, чьим образом является множество {true, false}. Есть несколько предикатов, известных любому, кто приложил руку к программированию. Вот они:

X>Y возвращает true если X больше, чем Y, иначе возвращает false.

X<Y возвращает true если X меньше, чем Y, иначе возвращает false.

X=Y возвращает true если X равен Y, иначе возвращает false.

Предикат с одним аргументом говорит о свойстве его аргумента. Примеры одноместных предикатов:

positive(X): true если X положительный, false в любом другом случае.

exists(“text.txt”): true если файл text.txt существует, иначе false.

Предикат более чем с одним аргументом показывает, что между его аргументами существует отношение. В случае X=Y это отношение – равенство.

Еще примеры предикатов:

positive(X)

true если X положителен, иначе false

rain(Temperature, Pressure, Humidity)

true, если будет дождь при заданных температуре, давлении и влажности. Например,

rain(100, 1.2, 90)

вернет true, если пойдет дождь, когда ваши измерительные приборы покажут 100°F, 1.2 атмосфер, и 90% относительной влажности.

invest(Rate, StandardDeviation, Risk)

По заданным Rate, StandardDeviation, и приемлемом Risk, этот предикат возвращает true, если вам стоит выбрать инвестирование.

3.2. Решения

Предположим, что у вас есть предикат city(Name, Point), который определяет координаты города на карте. Предикат city/2 имеет домен (доменом называется множество возможных значений аргумента)

city : (string Name, pnt Position).

и может быть определен как база данных фактов:

city(“Salt Lake”, pnt(30, 40)).

city(“Logan”, pnt(100, 120)).

city(“Provo”, pnt(100, 200)).

city(“Yellowstone”, pnt(200, 100)).

Этот предикат проверяет, является ли заданное положение заданного города верным, когда кто-либо не уверен насчет этого. Вот несколько запросов, которые можно задать предикату city/2.

city("Salt Lake", pnt(30, 40)) true

city("Logan", pnt(100, 200)) false

city("Provo", pnt(100, 200)) true

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

city(“Salt Lake”, P) P=pnt(30, 40).

В этом новом виде предикатов, символы, начинающиеся с заглавной буквы, называются переменными. Примеры переменных: X, Y, Temperature, Rate.

Когда вы используете переменную, как P в запросе city(“Salt Lake”, P), вы желаете знать, что нужно подставить вместо P, чтобы сделать предикат city(“Salt Lake”, P) true, то есть истинным. Ответом является P=pnt(30, 40). Таким образом, давайте определим предикат city/2.

  1. Создайте новый проект с именем mapDataBase.

  2. Добавьте новый пакет к корневому каталогу дерева проекта: mapDataBase / plotter.

  3. Создайте новую форму: plotter /map. Добавьте следующие кнопки к новой форме: logan_ctl, saltLake_ctl, provo_ctl.

  4. Window Edit. Измените размеры новой формы. Окно формы должно иметь достаточный размер, чтобы отобразить нашу «карту». Оставьте больше пустого места в центре формы.

  5. Включите пункт Project Tree/TaskMenu File/New.

  6. Project Tree/TaskWindow.win/Code Expert. Добавьте

clauses

onFileNew(S, _MenuTag) :-

X=map::new(S), X:show().

к Menu/TaskMenu/id_file/id_file_new/onFileNew.

  1. Создайте класс draw. Чтобы создать новый класс и вложить его в пакет plotter, выберите папку plotter в дереве проекта и выберите пункт File/New из панели задач VDE. Название класса draw, и галочка Create Objects снята. Откомпилируйте проект, для того, чтобы внести прототип нового класса в дерево проекта. Затем отредактируйте draw.cl и draw.pro как показано ниже (лист.1,2).

  2. Для того, чтобы вызывать предикат drawThem кнопками городов, двойным нажатием на кнопке logan_ctl и отредактируйте фрагмент кода обработчика события нажатия кнопки.

clauses

onLoganClick(S) =button::defaultAction() :-

Parent=S:getParent(),

P=Parent:getVPIWindow(),

draw::drawThem(P, “Logan”).

Повторите действия для “Salt Lake” и “Provo”. Не забудьте заменить названия предложений на onSaltLakeClick (S) и onProvoClick (S) соответственно, а также названия городов в drawThem. Откомпилируйте проект и запустите программу. В новом приложении, выберите пункт File/New. Появится новая форма. Когда вы нажимаете на кнопку, программа нарисует соответствующий город.

Листинг 1.

% File: draw.cl

class draw

open core, vpiDomains

predicates

classInfo : core::classInfo.

drawThem:(windowHandle, string) procedure.

end class draw

Листинг 2.

% File:draw.pro

implement draw

open core, vpiDomains, vpi

constants

className = "plotter/draw".

classVersion = "".

class facts

city:(string, pnt).

clauses

classInfo(className, classVersion).

city("Salt Lake", pnt(30, 40)).

city("Logan", pnt(100, 120)).

city("Provo", pnt(100, 80)).

city("Yellowstone", pnt(200, 100)).

drawThem(Win, Name) :-

B= brush(pat_solid, color_red),

winSetBrush(Win, B),

city(Name, P), !, P= pnt(X1, Y1),

X2= X1+20, Y2= Y1+20,

drawEllipse(Win, rct(X1, Y1, X2, Y2)).

drawThem(_Win, _Name).

end implement draw

3.3. Множественные решения

В предыдущем разделе вы видели предикаты, которые использовали свои переменные для получения решения, а не для проверки истинно отношение или ложно. В примере, предикат city/2 использован для получения только одного решения. Тем не менее, существуют ситуации, требующие более одного решения. Пусть conn/2 будет предикатом, устанавливающим связь между двумя городами.

conn(pnt(30, 40), pnt(100, 120)).

conn(pnt(100, 120), pnt(100, 200)).

conn(pnt(30, 40), pnt(200, 100)).

.

.

.

Вы можете использовать его для получения всех соединений между городами, как показано в примере:

conn(pnt(30, 40), W). W=pnt(100, 120)

W=pnt(200, 100)

conn(X, Y). X=pnt(30, 40) / Y=pnt(100, 120)

X=pnt(100, 120) / Y=pnt(100, 200)

X=pnt(30, 40) / Y=pnt(200, 100)

Рассмотрим запрос:

conn(pnt(30, 40), W)?

Ответом может быть как W=pnt(100, 120), так и W=pnt(200, 100).

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

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

  1. Project Settings. Создайте новый проект с именем drawMap.

  2. Create Project Item: Package. Добавьте новый пакет к корневому каталогу дерева проекта: drawMap / plotter.

  3. Create Project Item: Window. Создайте новую форму: plotter /map.

  4. Form Edit. Увеличьте размеры новой формы для карты.

  5. Project Tree/TaskMenu. Включите пункт File/New.

  6. Project Tree/TaskWindow.win/Code Expert. Добавьте

clauses

onFileNew(S, _MenuTag) :-

F=map::new(S), F:show().

к Menu/TaskMenu/id_file/id_file_new/onFileNew.

  1. Создайте класс draw. Откомпилируйте проект, затем отредактируйте draw.cl и draw.pro как показано ниже (лист.3,4).

  2. Project Tree/map.frm/Properties/Events. PaintResponder→onPaint:

clauses

onPaint(S, _Rectangle, _GDIObject) :-

W=S:getVPIWindow(),

draw::drawThem(W).

Листинг 3.

% File:draw.pro

implement draw     open core, vpiDomains, vpi constants     className = "plotter/draw".     classVersion = "". class facts     city:(string Name, pnt Position).     conn:(pnt, pnt). class predicates     connections:( windowHandle).     drawCities:(windowHandle). clauses     classInfo(className, classVersion).     city("Salt Lake", pnt(3040)).     city("Logan", pnt(100120)).     city("Provo", pnt(100160)).     city("Yellowstone", pnt(200100)).     conn(pnt(3040) , pnt(100120)).     conn(pnt(100120), pnt(100160)).     conn(pnt(3040), pnt(200100)).     drawCities(W) :-         city(NP),         P= pnt(X1Y1),         X2X1+10Y2Y1+10,         drawEllipse(W, rct(X1Y1X2Y2)),         drawText(WX1Y1N), fail.     drawCities(_Win).         connections(Win) :-         conn(P1P2),         drawLine(WinP1P2), fail.         connections(_Win).     drawThem(Win) :-         connections(Win),         drawCities(Win). end implement draw

Листинг 4.

% File:draw.cl

class draw     open core, vpiDomains predicates     classInfo : core::classInfo.     drawThem:(windowHandle) procedure.      end class draw

Если вы откомпилируете программу, вы должны получить окно с картой на нём, наподобие рис.3.1., когда нажмёте File/New.

Рис.3.1. Карта шт. Юта.

Соседние файлы в папке Лабы_ЭкспСист