дб. Четвертое издание джозеф Джарратано Университет Хьюстон клиэрЛэйк Гари Райли People5oft, Издательский дом "Вильямс" Москва СанктПетербург Киев 2007 ббк 32. 973. 26 018 75 Д
Скачать 3.73 Mb.
|
z2)) (z ?гЗ)) green) red)) ?уЗ) (> ух г Х) (лесу ?гЗ х) =>) 9.24. На рис. 9.15 показана сеть диагностирования неисправностей для гипотетических компонентов оборудования. Стрелки указывают направление, в котором распространяются неисправности. Например, при возникновении неисправности в компоненте А неисправности возникают ив компонентах В и С 778 Глава 9. Модульное проектирование, управление выполнением. Рис. 9.15. Сеть диагностирования неисправностей гипотетических компонентов оборудования Ниже приведены правила, которые описывают распространение неисправностей посети В) (assert (fault С) (defrule С (fault С) (assert (fault device-D)) (assert (fault device-E))) (defrule propagate-device-E-fault (fault device-E) (assert (fault device-F))) Перепишите эти три правила в виде одного общего правила и конструкции de f f acts, которые будут описывать распространение неисправностей также, как и три приведенных выше правила. Объясните, какие изменения потребуется внести при использовании каждого из этих двух вариантов организации программы после добавления нового компонента к сети диагностирования неисправностей ,.... 10 Процедурное программирование 10.1 Введение В языке CLIPS предусмотрены средства процедурного программирования, аналогичные тем, которые применяются в таких языках, как Си. В настоящей главе приведено вводное описание этих средств. Иногда бывает более удобно (и более эффективно) осуществлять некоторые операции с использованием подхода, базирующегося на процедурном программировании, а не подхода, основанного на правилах. В настоящей главе вначале рассматривается ряд процедурных функций, включая определенные функции, которые обеспечивают организацию циклов и выбор путей передачи управления по условию. Для определения новых функций, которые могут вызываться из правил или других функций, предназначена конструкция de f f unction. Конструкция de f global позволяет определять глобальные переменные. В отличие от локальных переменных, определяемых в правилах или функциях, глобальные переменные всегда сохраняют свои значения. Конструкции de f gener i c и de f method обеспечивают создание универсальных функций, которые подобны обычным функциям, за исключением того, что выполняемый в них код зависит от количества и типов параметров, передаваемых в функцию. Наконец, в данной главе дано вводное описание целого ряда полезных вспомогательных функций. Процедурные функции В языке CLIPS предусмотрено несколько функций, предназначенных для управления потоком выполнения действий. Функции while, if, switch, loop forcount, progn$ и break предоставляют функциональные возможности, аналогичные управляющим структурам, которые предусмотрены в таких современных язы- 780 Глава 10. Процедурное программирование Функция дй Функция i f имеет следующий синтаксис (if expression> then — это единственное выражение (такое как предикативная функция или переменная), а параметр , для определения того, должны ли быть выполнены действия, заданные в конструкции then или else. Если проверка условия приводит к получению любого символа, отличного от FALSE, то выполняются действия, заданные в конструкции then этой функции, а если проверка условия приводит к получению символа FALSE, то выполняются действия, заданные в конструкции else. Если же конструкция else не включена, то после получения ложных результатов проверки условия никакие действия не выполняются. Сразу после завершения выполнения функции i f система переходит к выполнению следующего действия в правой части правила, если оно имеется. Функцию if удобно использовать для проверки значений в правой части правила, поскольку это позволяет избавиться от необходимости осуществлять проверку с помощью других правил. Например, с помощью следующего правила можно определить, должно ли быть продолжено выполнение программы ках высокого уровня, как Ada, Pascal и С. Кроме того, функция halt, заданная в правой части любого правила, позволяет остановить выполнение правил. Язык в первую очередь предназначен для использования в качестве эффективного языка, основанного на правилах, а процедурные функции, рассматриваемые в этой главе, предусмотрены лишь для ограниченного применения. Попытка написать объемистую процедурную программу, включив ее в правую часть правила, противоречит общему назначению языка, основанного на правилах. Поэтому, вообще говоря, такие функции должны использоваться для выполнения простых проверок и циклов в правой части правила, и следует избегать применения в правых частях правил сложных вложенных конструкций, состоящих из процедурных функций 10.2. Процедурные функции (defrule continue-check ?phase <- (phase check-continue) — > (retract ?phase) (printout t "Continue? ") (bind ?answer (read)) (if (or (eq ?answer у) (eq ?answer yes)) then (assert (phase continue)) else (assert (phase halt)))) Следует отметить, что функция if позволяет преобразовать положительный или отрицательный ответили по, в факт, указывающий, какого типа действие должно быть предпринято. В рассматриваемом случае таким действием становится либо continue, либо halt. Возвращаемым значением функции i f является результат вычисления последнего выражения в части then или else функции. Если результатом вычисления выражения становится FALSE ив функции отсутствует часть then, то функция возвращает символ. Функция while Функция while имеет следующий синтаксис (while [do] этом определении представляет собой единственное выражение (такое как предикативная функция или переменная, а параметр Та часть функции while, которая представлена выражением, вычисляется до выполнения действий, предусмотренных в теле цикла. Если вычисление выражения приводит к получению любого значения, отличного от символа FALSE, то выполняются выражения, представленные в теле цикла. Если же вычисление выражения приводит к получению символа FALSE, то программа переходит к выполнению оператора, который следует за функцией while, если таковой имеется. Условие функции while проверяется каждый раз перед выполнением операторов в теле цикла для определения того, должны ли они быть снова выполнены. Глава 10. Процедурное программирование 782 (defrule continue- check ?phase <- (phase check-continue) — > (retract ?phase) (printout t "Continue? ") (bind ?answer (read)) (while (and (neq ? answer yes) (neq ?answer по) do (printout t "Continue? ") (bind ? answer (read))) (if (eq ?answer yes) then (assert (phase continue)) else (assert (phase halt)))) Функция switch Функция switch имеет следующий синтаксис (switch применяется функция while для определения условия продолжения цикла до тех пор, пока не будет получен приемлемый ответ. Процедурные функции 783 падает с результатом вычисления выражения определяемые вариантом приведенном ниже коде функция switch используется для установления соответствия между символическими именами и знаками арифметических функций. (defrule perform-operation (operation ?type ?arg1 ?arg2) > (switch ?type (case times then (printout t ?arg1 " times " ?arg2 is " (* ?arg1 ?arg2) crlf)) (case plus then (printout t ?arg1 " plus " ?arg2 is " (+ ?arg1 ?arg2) crlf)) (case minus then (printout t ?argl " minus " ?arg2 is " (- ?arg1 ?arg2) crlf)) (case divided-by then (printout t ?arg1 " divided by " ?arg2 is " (/ ? arg1 ?arg2) crlf)))) В качестве примера можно привести следующий диалог CLIPS> (assert (operation plus 3 4))J CLIPS> (ги) 3 plus 4 is 7 CLIPS> Символ plus в факте operation вызывает переход к варианту саяе со значением plus в операторе switch, после чего выводится результат сложения чисел 3 и Глава 10. Процедурное программирование 784 Приведенное выше правило perform — operation можно записать иначе, в виде четырех отдельных правил, те. без использования функции switch, следующим образом (defrule perform-operation-times (operation times ?argl ?arg2) => (printout t ?argl " times " ?arg2 is " (* ?argl ?arg2) crlf)) (defrule perform-operation-plus (operation plus ? argl ?arg2) — > (printout t ?argl " plus " ?arg2 is " (+ ?argl ?arg2) crlf)) (defrule perform-operation-minus (operation minus ?argl ?arg2) — > (printout t ?argl " minus " ?arg2 is " (- ?argl ?arg2) crlf)) (defrule perform-operation-divided-by (operation divided-by ?argl ?arg2) => (printout t ? argl " divided by " ? arg2 is " (/ ?argl ?arg2) Функция loop- for-count Функция loop — for — count имеет следующий синтаксис (loop-for-count ( которые возвращают целые числа. Если задано только выражение cnt2 3) do (printout t ?cnt1 " ") (loop-for-count 3 do (printout t ".")) (printout t " " ?cnt2 crlf)))J 2 ... 1 2 ... 2 2 . ° ° 3 3 ... 1 3 ... 2 3 ... 3 4 .. ° 1 4 ... 2 4 ... 3 FALSE CLIPS> Переменная for-count (х 2) do (printout t "inside ?x is " ?x crlf)) (printout t "outside ?x is " ?x crlf))J CLIPS> (reset)J CLIPS> (й1иЪ) inside х is 1 inside х is 2 outside х Глава 10. Процедурное программирование is 4 Функция progn$ Функция progn$ имеет следующий синтаксис ( (рхiп1оиi. t ?v-index " " 7v crlf))J 1 а 2 Ь 3 с CLIPS> Если задан не только параметр
создается специальная переменная путем добавления суффикса -index к имени параметра
10.2. Процедурные функции 787 Функция break Функция break имеет следующий синтаксис (break) Функция break прекращает выполнение той функции while, loop-forcount или progn$, в которой она непосредственно обнаруживается. Обычно функция break используется, чтобы вызвать преждевременное завершение цикла при обнаружении некоторого условия. Например, правило print-list, показанное в приведенном ниже диалоге, выводит первые пять элементов из списка, а затем выводит многоточие, если есть еще оставшиеся элементы) (defrule print-list (print-list $?list) > (progn$ (ч ?list) (if (< ?v-index 5) then (printout t ?v '™) else (printout t "...") (break))) (printout t crlf))J CLIPS> (reset)J CLIPS> (assert (print-list а b c d e))J После ее вызова прекращается выполнение каких-либо действий, заданных в правой части запущенного правила, и управление передается в приглашение верхнего уровня. В рабочем списке правил продолжают находиться все оставшиеся правила, активизированные ко времени вызова функции halt. 788 Глава 10. Процедурное программирование Например, в правиле continue — check следующее действие (assert (phase halt)) можно было бы заменить таким действием, которое прекращает выполнение правил) Функция halt становится особенно удобной, если требуется прекратить выполнение программы после того, как пользователь выразит намерение снова вызвать в дальнейшем программу на выполнение с помощью команды run. Рассмотрим следующую модификацию правила continue-check: (defrule continue-check ?phase <- (phase check-continue) — > (retract ?phase) (printout t "Continue? ") (bind ? answer (read)) (while (and (песу ?answer yes) do (printout t "Continue? ") (bind ?answer (read))) (assert (phase continue)) (if (песу ?answer yes) then (halt))) (песу ?answer по) Конструкция de f f unction Язык CLIPS позволяет определять новые функции по такому же принципу, как ив других процедурных языках. Такие функции, применяемые наряду с правилами, позволяют уменьшить количество повторяющихся выражений ив левых, и правых частях. Новые функции определяются с использованием конструкции Конструкция беййыпсоп имеет следующий общий формат: Обратите внимание на то, что в этом правиле в список фактов вносится факт (phase continue ), невзирая на то, что ответил пользователь на вопрос о продолжении, "Continue? ". Внесение этого факта в список фактов приводит к тому, что в рабочий список правил помещаются правила, необходимые для продолжения выполнения. Если ответ на вопрос о продолжении не является положительным, то выполнение программы прекращается с помощью функции halt. После этого пользователь может проверить правила и факты, а затем снова перейти к выполнению программы с того места, где она была остановлена, воспользовавшись командой run. 10.3. Конструкция de f f unction 789 (deffunction Преобразование этой формулы в конструкцию de f function приводит к получению следующего определения В этом определении параметр которые выполняются последовательно при вызове конструкции def function. Определяемые пользователем конструкции de f function действуют аналогично заранее определенным функциям, предусмотренным в языке CLIPS. В любых условиях допускающих вызов заранее определенной системной функции, можно вызвать конструкцию def function. Нов отличие от заранее определенных функций, допускается удаление конструкций de f function, а для отслеживания их выполнения может использоваться команда watch. Объявления Возвращаемым значением конструкции de f f unction является значение последнего выражения, вычисленного в теле конструкции de f function. В качестве примера рассмотрим конструкцию def function, в которой вычисляется длина гипотенузы прямоугольного треугольника с помощью теоремы Пифагора. Допустим, что аи стороны, образующие прямой угол, а сгипотенуза. В таком случае согласно данной теореме можно записать следующее: Глава 10. Процедурное программирование 790 (deffunction hypotenuse-length (а ?b) (** (+ (* а а) (* Ь Ь) 0.5)) В данном случае значения длины сторон, прилегающих к прямому углу, равны 3 и 4, поэтому длина гипотенузы вычисляется правильно, как равная 5. Поскольку в конструкциях de f f unction можно использовать локальные переменные, применяемый способ вычисления длины гипотенузы можно представить в формате, |