|  |  |  | 
6.3.3. 
  Значения по умолчанию и демоны
  
 Представьте 
  себя на некоторое время в роли агента по оценке недвижимости. Вы должны оценить 
  примерную стоимость на рынке земельных участков, полной информацией о которых 
  не располагаете. Большинство участков имеет, как правило, форму выпуклых прямоугольников, 
  поэтому можно оценить стоимость участков, предполагая, что те, о которых идет 
  речь, также имеют подобную форму, если только у вас нет конкретной информации 
  об обратном.
  
 Предположим, 
  что граф на рис. 6.6 представляет знания о плоских геометрических фигурах, которые 
  можно использовать для логических рассуждений о форме участков. Каждый узел 
  на этом графе имеет связанную с ним структуру записей (фрейм), формат которой 
  приведен ниже.
  
 NAME 
  (ИМЯ):
  
 Number 
  of sides (Количество сторон):
  
 Length 
  of sides (Длины сторон):
  
 Size 
  of Angles (Углы):
  
 Area 
  (Площадь):
  
 Price 
  (Цена):
  
 Практически 
  все слоты фрейма Многоугольник придется оставить незаполненными, поскольку ничего 
  нельзя сказать о сторонах и углах типичного многоугольника. Однако для слота 
  Количество сторон в качестве значения по умолчанию можно установить 4, поскольку 
  подавляющее большинство земельных участков имеет форму четырехугольника. Таким 
  образом, все земельные участки, информация о форме контура которых отсутствует, 
  будут полагаться четырехугольными. Слот Площадь также нельзя заполнить, но известно, 
  как вычислить площадь многоугольника, располагая другой информацией о нем. Любой 
  n-сторонний многоугольник можно разбить на п-2 треугольника, вычислить 
  их площади и затем просуммировать результаты. Программу, реализующую эту процедуру, 
  можно подключить к слоту Площадь. Процедуры, подключенные к структуре данных 
  и запускаемые на выполнение при появлении запроса или обновлении информации 
  в структуре, иногда называют демонами. Те демоны, которые по запросу 
  вычисляют некоторые значения, называются демонами по требованию (IF-NEEDED).
  
 Полезно также 
  иметь демон, который при заполнении слота Площадь сразу вычислял бы цену участка. 
  Эта процедура относится к другому типу демонов — демонам добавления (IP-ADDED) 
  — и подключается также к слоту Площадь. Теперь при обновлении или установке 
  значения слота Площадь автоматически будет вычислена цена участка, а результат 
  будет помещен в слот Цена.
  
 Перейдем к 
  следующему уровню в иерархии фреймов. Для фрейма Четырехугольник совершенно 
  очевидно нужно установить значение 4 в слот Количество сторон. Это значение 
  будет наследоваться фреймами на каждом из последующих уровней иерархии. Вычислять 
  площадь и цену всех фигур, представленных фреймами последующих уровней, можно 
  тем же способом, что и для многоугольника. Поэтому описанные выше демоны также 
  могут быть унаследованы всеми последующими фреймами.
  
 Но для четырехугольника 
  можно примерно оценить площадь, даже не располагая информацией о значениях внутренних 
  углов контура, а зная только длины сторон. Вполне приемлемые результаты можно 
  получить с помощью следующего эвристического способа: среднюю длину стороны 
  для одной пары противолежащих сторон умножить на среднюю длину стороны для другой 
  пары. Этот метод даст существенную ошибку только для четырехугольников, не являющихся 
  выпуклыми, а такое встречается очень редко.
  
 Эта эвристика 
  может быть реализована в виде демона по требованию, подсоединенного к слоту 
  Площадь фрейма Четырехугольник. Такой демон должен выполнять следующее:
  
 
 
  
Рис. 6.6. 
  Иерархия плоских геометрических фигур
  
 Фреймы, представляющие 
  все последующие разновидности четырехугольников, наследуют значение из слота 
  Количество сторон фрейма Четырехугольник. Но в каждом из этих фреймов можно 
  реализовать свою процедуру вычисления площади, лучше учитывающую особенности 
  именно данного вида фигур. Например, площадь трапеции можно вычислить как произведение 
  высоты на среднюю длину оснований, а фреймы прямоугольника и квадрата могут 
  унаследовать эту процедуру у параллелограмма, площадь которого равна произведению 
  основания на высоту.
  
 Этот простой 
  пример демонстрирует, как, используя значения по умолчанию и демоны, можно заполнить 
  слоты иерархической системы фреймов, причем этот механизм оказывается более 
  удобным, чем тот, который используется в структурах записей языка PASCAL. Данные, 
  процедуры и определения оформляются в виде единого пакета и образуют отдельный 
  модуль для каждого фрейма, причем разные модули могут совместно использовать 
  данные и процедуры, пользуясь механизмом наследования.
  
 6.1. 
  Реализация фреймов и наследования в языке CLIPS
  
 Хотя 
  язык CLIPS и не поддерживает в явном виде формализм семантических сетей и фреймов, 
  их можно неявно определить, используя имеющуюся в CLIPS конструкцию def class. 
  Мы более подробно поговорим об этой конструкции в следующей главе, поскольку 
  ее основное назначение — реализация объектно-ориентированного подхода. Для представления 
  иерархии геометрических объектов, показанной на рис. 6.6, нам понадобятся следующие 
  определения:
  
(defclass polygon (is-a USER))
(defclass quadrilateral (is-a polygon))
(defclass trapezium (is-a quadrilateral))
(defclass parallelogram (is-a trapezium))
(defclass rectangle (is-a parallelogram))
 
  (defclass square (is-a rectangle))
  
 Обратите 
  внимание на то, что класс polygon (многоугольник) объявлен как подкласс класса 
  USER, который является базовым для всех классов, объявленных пользователем. 
  Отношение is-a (является), которое фигурирует во всех языках представления фреймов, 
  обычно обладает свойством транзитивности: квадрат является прямоугольником, 
  но квадрат также является и трапецией и т.д. Это отношение является антисимметричным, 
  т.е. если квадрат является прямоугольником, то прямоугольник в общем случае 
  не является квадратом.
  
 Для 
  того чтобы представить на языке CLIPS тот факт, что большинство многоугольников 
  предположительно должно иметь четыре стороны, потребуются кое-какие дополнительные 
  языковые конструкции. Нужно будет несколько изменить определение классов polygon 
  и quadrilateral:
  
 (defclass 
  polygon (is-a USER)
  
 (role 
  abstract)
  
(slot no-of-sides (default 4)))
(defclass 
  quadrilateral (is-a polygon)
  
 (role 
  concrete))
  
 Теперь 
  polygon объявлен как абстрактный класс, т.е. класс, не способный самостоятельно 
  порождать определенные объекты. Его подкласс quadrilateral и все последующие 
  подклассы класса quadrilateral являются конкретными классами, т.е. эти классы 
  могут порождать конкретные экземпляры (объекты классов). При определении класса 
  polygon его слоту no-of-sides (количество сторон) назначено по умолчанию значение 
  4. Это отражает наше интуитивное предположение, что большинство многоугольников 
  будет четырехугольниками. В терминологии систем фреймов такое значение по умолчанию 
  называется фацетом слота no-of-sides.
  
 После 
  этого можно приступить к описанию демонов. Для этого нужно воспользоваться конструкцией 
  defmessage-handler, которая имеется в CLIPS. (Подробно конструкция defmessage-handler 
  также будет описана в следующей главе.)
  
 (defmessage-handler 
  polygon sides () ?self:no-of-sides)
  
 Демон 
  sides связан с классом polygon и попросту получает доступ к слоту no-of-sides 
  того объекта, который его вызвал. Предположим, например, что определен конкретный 
  участок, имеющий форму квадрата, причем ему присвоено наименование square-one.
  
 (definstances 
  geometry (square-one of square))
  
 Система 
  инициализируется командой (reset). Теперь можно активизировать демон, послав 
  ему сообщение
  
 (send 
  [square-one] sides)
  
 В 
  ответ интерпретатор CLIPS выведет результат
  
 Обратите 
  внимание на то, что выражение ?self :no-of-sides вычисляется в контексте объекта 
  square-one, которому было направлено сообщение и который в ответ на него активизировал 
  демона. В этом выражении ?self является переменной и определяет объект, к слоту 
  которого производится обращение, а двоеточие — это инфиксный оператор доступа 
  к конкретному слоту.
  
|  |  |  |