Процедурные средства языка
При обсуждении примеров спецификаций фреймов мы пользовались интуитивным пониманием значения. Спецификация этого понятия в ЯПЗ PILOT/2 следующая. Значения могут быть простыми (единичными) и множественными. Множественные значения — списки простых значений одного типа, заключенные в фигурные скобки. В качестве простых значений в PILOT/2 выступают выражения. Введение префиксов и постфиксов к именам переменных является первым шагом на пути определения выражений. Но в ЯПЗ PILOT/2 есть и более мощные средства этого типа. Здесь используются традиционный набор арифметических операций и общепринятое их старшинство, а специфика ЯПЗ на уровне первичного выражения:
перв-арифм::= | | число | | | | GET-переменная | | | | VAR-переменная | | | | - перв-арифм | | | | вызов-функции | | | | (арифметическое) | | | | слот-фрейма | | вызов-функции::= имя-функции (значение {{, значение }})
Первые шесть вариантов вполне традиционны, а последний имеет следующее определение: слот-фрейма::= [ имя-фрейма: имя-слота ] Учитывая вышесказанное, следующие примеры суть правильно построенные выражения ЯПЗ PILOT/2:
empty пустое выражение "а" ASCII-символ char «qwerty» строка string Person имя-фрейма frame $NameFrame VAR-переменная frame $AgeValue> GET-переменная int 10 * ($var1 + 2 ** 4) арифметическое int [John: Age] слот-фрейма int my_func («events.kb», [Event: Value]) вызов-функции bool
Теперь вернемся к основному средству построения конфликтного множества — к условиям. Напомним, что в ЯПЗ PILOT/2 две точки, где, согласно синтаксису языка, возможно использование условий: конструкция if в секционных и прави-ловых разрешениях и левые части продукционных правил. И в том и в другом случае инженер по знаниям может сформулировать произвольную условную конструкцию в базисе И-ИЛИ-НЕ с общепризнанным старшинством логических операций. Кроме того, на уровне первичных условий возможно использование отношений и образцов.
Образцы являются наиболее важной и мощной конструкцией языка PILOT/2, так как они позволяют находить и фиксировать интересующую инженера по знаниям ситуацию в базе знаний. По синтаксису образец похож на слот-фрейма, но у него существенно большие возможности и другая семантика. Образец — это предикат на базе знаний, принимающий значения «истина» или «ложь», тогда как слот-фрейма возвращает значение конкретного слота конкретного фрейма. Образец определяет некий шаблон, которому могут удовлетворять фреймы из базы знаний. Образец состоит из синтаксического обрамления «?[...]» и тела. Тело представляет собой шаблон фрейма, которому, быть может, предшествует конструкция «захвата» результатов отождествления в переменную, и список слотов-образцов, который может быть пустым. Каждый слот-образец также имеет шаблон слота в качестве базы отождествления и, быть может, конструкцию «захвата» результатов. Таким образом, тело определяет структуру, которую должны иметь фреймы базы знаний, чтобы успешно сопоставиться с образцом. Шаблон фрейма определяет множество фреймов базы, на которых будет происходить отождествление. Это множество может состоять из единственного фрейма (при этом указывается имя фрейма или его отрицание); всей базы (тогда шаблоном фрейма является символ «*»); фрейма (фреймов), имена которых хранятся в переменных типа VAR или GET, а также фиксироваться спомощью конструкции явного задания множества, образованного из элементов и стандартных теоретико-множественных операций one_of (пересечение); all_of (объединение); ~ (вычитание). Пустой префикс соответствует операции one_of. При этом семантика операции one_of — «первый из сопоставленных». Операция «вычитание» может использоваться только с именами фреймов, заданными явно. Результаты успешных сопоставлений могут запоминаться в переменных с помощью операции присваивания (в случае префикса one_of или его отсутствия запоминается результат первого успешного сопоставления, а в случае префикса all_of — результаты всех успешных сопоставлений). Шаблон слота практически тот же, что и шаблон фрейма. Однако для слотов есть еще один способ указания объединения — перечисление нужных слотов через разделитель «;». Отличие шаблона слота от шаблона фрейма в том, что здесь добавляется значение-образец. Как и в предыдущих случаях, найденные значения могут «захватываться» в переменные. Шаблон значения может фиксировать, что оно произвольно, но существует (в этом случае используется символ «*», либо определить возможные значения более точно с помощью элементов (значение-первичного-спецификатора) и логических операций в базисе И-ИЛИ. Заметим, что отрицание здесь не требуется, так как его функцию берет на себя отношение «!=«в первичном-спецификатора. Спецификаторы задают декларативно ограничения на значения. Синтаксис спецификаторов следующий:
спецификатор::= терм-спецификатора {{ || терм-спецификатора || терм-спецификатора::= первичное-спецификатора {{ && первичное-спецификатора }} первичное-спецификатора::= || || < || значение-первичн-спецификатора || II II <= II || II II == II II II II!= || II II II >= I| II II II > II || || (спецификатор) I| значение-первичн-спецификатора::= || значение || || ||пусто || || VAR-переменная || || || || one_fгоm || || GET-переменная || || II II all_from || ||
Знаки отношений имеют стандартную семантику для чисел и семантику сравнения ASCI-кодов для символов и строк. В тех случаях, когда значение в первич-ном-спецификатора является множеством, все знаки отношений имеют следующую интерпретацию: • < — строгое включение множества значений спецификатора во Множество значений слота; • <= — нестрогое включение множества значений спецификатора во множество значений слота; • = = — совпадение множества значений спецификатора с множеством значений слота; •!= — несовпадение множества значений спецификатора с множеством значений слота;
• >= — нестрогое покрытие множества значений спецификатора множеством значений слота; • > — строгое покрытие множества значений спецификатора множеством значений слота. Дополнительно к этому значение-первичного-спецификатора может быть VAR-или GET-переменной, которым предшествует префикс one_from (один из элементов в переменной должен быть использован); all_from (все элементы переменной должны быть использованы). Пустой префикс соответствует операции one_from. Возможности образцов лучше рассмотреть на примерах. Пусть в текущей базе имеются следующие фреймы, причем порядок их расположения в базе такой, как описано ниже:
[ F1 is_a prototype; [ F2 is_a F1; [ F3 is_a F1; S1 Int, by_default 8; S2 = "x" ]; S1=0]; 82 char];
Имеются также переменные $V1 (типа frame) и $V2 (типа char), которые до применения каждого из образцов содержат следующие значения:
$V1 = ╎F1 ╎F2 ╎F3 $V2 = ╎'a' ╎'b' ╎
Примеры образцов с их значениями и значениями переменных $V1 и $V2 после применения этих образцов к описанной базе представлены ниже.
N/N Образец Результат 1?[ F: S] false 2?[F1: 82] true 3?[F2: 81 {== 8}] true 4?[ >>$V1 = all_of *: S1{==8}], true 5?[*: S2 {== <<$V2} ] true 6?[ one_of $V1>>: S1{== one_from {1,0}} ] true 6a?[ one_of $V1>>: S1 {== all_from {1,0}} ] false 7?[$V1<<: S1{==8}; >$V2=S2] true 8?[*: *] true
Образцы 1 и 2 представляют собой запросы на наличие в базе соответствующих слотов-фреймов. Поскольку [F:S] в базе нет, a [F1:S2] — есть, значения образцов 1 и 2 соответственно false и true. Образец 3 более избирателен, он проверяет базу на наличие в ней фрейма F2 со слотом S1, имеющим значение 8. Такой фрейм в определенной нами базе имеется (вспомним, что фрейм-экземпляр наследует слоты своего прототипа), поэтому значение образца — true. Образец 4 ищет все (all_of) фреймы со слотами S1, равными 8, записывая при этом их имена в переменную $V1. Префикс этой переменной предписывает заносить в нее значения слева с сохранением. В образце 5 значение слота S2 берется из переменной $V2 (слева без сохранения), причем имя фрейма может быть любым (*). Но фрейм со слотом S2 = "а" в базе один (F2). Ключевое слово one_of в образце 6, явно указывающее на поиск только первого подходящего фрейма, — не обязательно, такая стратегия подразумевается по умолчанию. Для успешного сопоставления с этим образцом фрейм F3, имя которого взято справа без сохранения из переменной $V1, должен иметь слот S1, значением которого может быть одно из (one_from) чисел: 1 или 0. Условие соблюдается, и значение образца — true. Вместо one_from может быть указано all_from (образец 6а), в этом случае значением слота должно быть все множество {1,0}. Образец 7 показывает, что можно проверять значения нескольких слотов сразу. Семантика его следующая: найти первый фрейм со слотами S1 = 8 и S2; если такой фрейм будет найден, записать его имя в переменную $V1 справа, протолкнув верхушку стека справа, а значение слота S2 — в переменную SV2 слева, без сохранения значения в верхушке стека. С помощью образца 8 проверяется, есть ли вообще в текущей базе какие-нибудь фреймы.
Таким образом, мы обсудили конструкции ЯПЗ PILOT/2, которые могут потребоваться при формировании левых частей продукционных правил. Все они предназначены для выделения в БЗ системы интересующих нас ситуаций. Такое выделение не самоцель, а средство для преобразования таких ситуаций для получения решений. Сами преобразования описываются в основном, в правых частях продукционных правил ЯПЗ-программы и сводятся к выполнению определенных действий над БЗ и/или значениями переменных. В ЯПЗ PILOT/2 все действия делятся на стандартные (системные) и нестандартные (пользовательские). Все они могут использоваться не только в правых частях продукционных правил, но и в аннотациях, что позволяет реализовывать в ЯПЗ PILOT/2 развитые модели объяснений [Clancey, 1983]. Синтаксис нестандартных действий определяется спецификацией прототипов процедур, рассмотренной выше, и синтаксисом обращений к процедурам, а семантика и реализация — целиком в руках пользователя ЯПЗ PILOT/2. Классификация стандартных действий проста. Это обработка переменных, обработка базы знаний, процедурное управление и ввод/вывод. Как указывалось выше, в ЯПЗ PILOT/2 имеются три вида переменных (VAR, GET, PUT). С учетом этого:
обработка-переменных::= || оператор-присваивания || || PUSH-оператор || || РОР-оператор || || CLEAR-оператор || оператор-присваивания::= || VAR-переменная || = значение || PUT-переменная ||
Примерами присваивания значений переменным могут служить конструкции вида:
$var1=<$a+$b; >$var2=[FrameName: SlotName] * $var1; $var3«=empty;
Заметим, что с помощью присваивания можно реализовать и «проталкивание» стека, например, так: »$var2 = empty; $var3<< =; или даже так $var <<; Однако более общим будет действие вида push (left, $var2, $var3); push (right, $var2, $var3);
так как здесь с помощью одного действия можно обработать несколько стеков, причем одно и то же имя может многократно повторяться в качестве параметра. В этом случае в соответствующем стеке появится несколько пустых позиций-уровней. Выталкивание значений из стеков производится аналогичным образом. Для очистки стеков следует использовать стандартное действие CLEAR. При этом не важно, с какой стороны (слева или справа) начнет очищаться стек. Присваивания и операторы обработки стеков, рассмотренные выше, конечно, важны, но не они составляют суть обработки данных в языках представления знаний. В дополнение к этому, а вернее, в первую очередь, здесь должны быть средства изменения базы знаний, текущее состояние которой и определяет, какие решения уже были приняты и что будет происходить дальше. Выше уже обсуждалась конструкция образца ЯПЗ PILOT/2, которая используется для выделения интересующих инженера по знаниям ситуаций. Почти та же конструкция применяется и для преобразования ситуаций. Действительно, для выполнения любого преобразования в конечном счете нужно найти некоторую ситуацию и либо удалить ее, либо скорректировать соответствующим образом. Для полноты нужны и средства формирования новых ситуаций. Все эти действия выполняются в ЯПЗ PILOT/2 с помощью конструкции обработка-базы-знаний, которую для краткости и преемственности с языком ПИЛОТ [Хорошевский и др., 1990] будем также называть манипулятором. Итак, манипулятор, или обработка базы знаний, — это удаление фреймов, создание фреймов, замена фреймов или коррекция фрейма. Операции удаления, создания и замены фреймов в текущей базе знаний манипулируют с фреймами как с целыми и неделимыми единицами. При этом благодаря использованию образцов можно за одно обращение к соответствующему манипулятору провести множественные изменения в базе знаний:
[?[*:*] \ ]; [?[ *: *{==«обработан»} ] \ ]; [?[»$DeletedFrameNames=all_of *: * {—«обработан»} ] \ ];
Создание новых фреймов в ЯПЗ PILOT/2 для пользователя языка тоже простая операция. Здесь нужно дать определение нового фрейма или совокупности фреймов аналогично тому, как это делалось в рамках декларативной компоненты ЯПЗ PILOT/2: [ \ [ Framel: Slot11 = «Mother»; Slot12 = «Father»; Slot13 = «Children»; Slot14 = 21]; [ Frame2: Slot21 = empty]; [ FrameS:] ]
Замена одних фреймов на другие — не что иное, как объединение уже рассмотренных конструкций удаления и вставки: [?[*:*] \ [ Frame: Slot = «End Of Job» ] ] Так в ЯПЗ PILOT/2 осуществляется коррекция баз знаний на уровне отдельных единиц-фреймов. Вместе с тем часто требуется скорректировать некоторый фрейм или группу фреймов более «тонким» способом. Например, это может быть изменение значений некоторых слотов определенных фреймов, удаление «ненужных» слотов и/или добавление новых слотов в уже существующие фреймы. Все эти манипуляции с базой знаний осуществляются в ЯПЗ PILOT/2 на уровне конструкции коррекция-фрейма.. Примеры использования манипуляторов в случае коррекции базы знаний на уровне отдельных фреймов и/или групп фреймов приводятся ниже:
[ *: \ S1 int] - К первому фрейму в базе знаний добавить слот с именем 81. [all_of *: $del\ ] - Во всех фреймах, имеющих слот с именем, хранящимся в $del, удалить этот слот. [all_of *: S1=+1] - Во всех фреймах, имеющих слот S1, изменить значение последнего, увеличив его на 1.
При обсуждении общей структуры управления PILOT-программой были введены мощные, но «дорогие» средства управления выводом. Вместе с тем инженер по знаниям иногда может быть уверен, что надо выполнить определенную продукцию или секцию; он может знать, что определенные продукции пока не нужны, но зато необходимо включить в рассмотрение другие продукции. Наконец, иногда требуется осуществить принудительное завершение работы PILOT-npoграммы. Все такие действия в ЯПЗ PILOT/2 объединены в группу действий процедурного управления на уровне управление-активностью-правил, управление-активностыо-секций, вызов-секции или выход. Фильтр «активности/неактивности» продукций — первый из используемых «арбитром». Поэтому, явно активируя или деактивируя некоторые из продукций, можно существенно сократить его работу и увеличить производительность всей продукционной системы. В случае секций фильтр активности, конечно, не столь эффективен, но у инженера по знаниям появляется возможность более точной структуризации правил продукционной системы и за счет этого увеличения эффективности ее функционирования. Одними из уже упоминавшихся действий являются переключения флагов активности продукций (rule_tm/rule_off), с помощью которых можно устанавливать их как в текущей, так и любой другой секции. Возможно манипулирование флагами сразу всех продукций одной секции (section_on/section_off). Особым действием является вызов (invoke) секции. В результате его выполнения текущая активная секция «проталкивается» в управляющий стек, а ее место на следующем шаге занимает вызываемая секция. Так как за вызовом секции могут следовать другие действия (в частности, другие вызовы), после полной отработки этого вызова «арбитр» на некотором шаге, минуя формирование КМ и выбор из него продукции, возвращается к применению данной продукции, причем в той ее части, которая непосредственно следует за вызовом. Выполнение действия exit прерывает работу «арбитра» и таким образом завершает работу продукционной системы. В качестве «побочного» эффекта это действие позволяет передать во внешнюю среду информацию о том, как завершилась PILOT-программа. По «умолчанию» выход происходит с нулевым кодом возврата. Мы рассмотрели обработку переменных и баз знаний, а также действия, связанные с управлением выполнением PILOT-программ. Вместе с тем понятно, что сколько-нибудь сложные задачи требуют удобного ввода/вывода. Вот почему в ЯПЗ PILOT/2 включена совокупность стандартных действий, поддерживающих ввод/вывод информации. При этом основное внимание уделяется действиям по работе с базами знаний. Что же касается средств работы с файлами, то в ЯПЗ PILOT/2 используется лишь последовательный доступ и простые форматные преобразования, а также специализированный обмен с экраном на уровне сообщений и вопрос-ответных цепочек [Khoroshevsky, 1994]. Все более развитые средства этого типа, которые могут потребоваться пользователю, должны подключаться на уровне нестандартных действий. Выше мы обсудили основные аспекты представления знаний на базе ЯПЗ PILOT/2. Примеры его использования будут рассматриваться в следующих параграфах данной главы.
Воспользуйтесь поиском по сайту: ©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|