Автор: Пользователь скрыл имя, 04 Марта 2013 в 18:15, курсовая работа
Название языка CLIPS – аббревиатура от C Language Integrated Production System. Язык был разработан в центре космических исследований NASA
{NASA’s Johnson Space Center} в середине 1980-х годов и во многом сходен с языками , созданными на базе LIPS, в частности OPS5 и ART. Использование C в качестве языка реализации объясняется тем, что компилятор LISP не поддерживается частью распространенных платформ, а также сложностью интеграции LISP-кода в приложения, которые используют отличный от LIPS язык программирования.
А.1. Краткая история CLIPS 3
А.2. Правила и функции в CLIPS 3
А.3. Обектно-ориентированные средства в CLIPS 10
А.4. Задача «Правдолюбцы и лжецы» 15
А.5 Стиль программирования на языке CLIPS 66
;; высказывания (объекта statement) или тэг
;; другого утверждения (объекта claim).
;; Утверждение также
характеризуется признаком scop
;; который может принимать значение «истина» или «ложь».
(deftemplate claim
(multifield content (type SYMBOL))
(multifield reason (type INTEGER) (default 0))
(field scope (type SYMBOL))
)
Например, раскрыв содержимое приведенного выше высказывания в предположении, что А говорит правду, получим следующие утверждение (объект claim):
(claim (content F A) (reason 1) (scope truth)).
Таким образом, объект claim наследует содержимое от объекта statement. Последний становится обоснованием (reason) данного утверждения. Поле scope объекта claim принимает значение предположения о правдивости или лживости этого высказывания.
Еще нам потребуется представление в программе того мира (world), в котором мы в настоящее время находимся. Объекты world порождаются в момент, когда мы формируем определенные предположения. Нужно иметь возможность различать разные множества предположений и идентифицировать их в программе в тот момент, когда процесс размышлений приводит нас к противоречию. Например, противоречие между высказываниями Т(А) и F(A) отсутствует, если они истинны в разных мирах, т.е. при разных предположениях. Если у вас есть сомнения на сей счет, вернитесь вновь к примерам в самом начале раздела А.4.
Миры будем представлять в программе следующим образом:
;; Объект world представляет контекст,
;; сформированный определенными предположениями
;; о правдивости или лживости персонажей.
;; Объект имеет уникальный
;; а смысл допущения –
;; фиксируется в поле scope.
(deftemplate world
(field tag (type INTEGER) (default 1))
(field scope (type SYMBOL) (default truth))
)
Обратите внимание на то, что при указанных в шаблоне значениях по умолчанию мы можем начинать каждый процесс вычислений с объекта world, имеющего в поле значение 1, причем этот «мир» можно заселить высказываниями персонажей, которых мы предположительно считаем правдолюбцами. Таким образом можно инициализировать базу фактов the-facts для задачи Р0 следующим образом:
;; Утверждение, что А лжец.
(deffacts the-facts
(world)
(statement (speaker A) (claim F A))
)
Если этот оператор deffacts будет включен в тот же файл, что и объявления шаблонов (а также правила, о которых речь пойдет ниже), то после загрузки этого файла в среду CLIPS нам понадобится для запуска программы дать только команду reset.
В этом разделе мы рассмотрим набор правил, который помогает справиться с вырожденной формулировкой Р0 задачи о лжецах и правдолюбцах. Первые два правила, unwrap-true и unwrap-false, извлекают содержимое высказывания в предположении, что персонаж, которому принадлежит высказывание, является соответственно правдолюбцем или лжецом, и на этом основании формируют объект claim.
;; Извлечение содержимого
(defrule unwrap-true
(world (tag ?N) (scope truth))
(statement (speaker ?X) (claim $?Y) (tag ?N))
=>
(assert (claim (content T ?X) (reason ?N)
(scope truth)))
(assert (claim (content $?Y) (reason ?M)
(scope truth)))
)
(defrule unwrap-false
(world (tag ?N) (scope falsity))
(statement (speaker ?X) (claim $?Y) (tag ?N))
=>
(assert (claim (content F ?X) (reason ?N)
(scope falsity)))
(assert (claim (content NOT $?Y) (reason ?N)
(scope falsity))
)
В каждом из приведенных правил первый оператор в условной части делает предположение соответственно о правдивости или лживости персонажа, а второй оператор в заключительной части правила распространяет предположение на формируемые утверждения – объекты claim.
Далее нам понадобятся правила, которые введут отрицания в выражения. Поскольку –Т(А) эквивалентно F(A),а –F(A) эквивалентно Т(А), то правила, выполняющие соответствующие преобразования, написать довольно просто. Анализ результатов применения этих правил значительно упростит выявление противоречий, следующих из определенного предположения.
;; Правила отрицания
(defrule not1
?F <- (claim (content NOT T ?P))
=>
(modify ?F (content F ?P))
)
(defrule not2
?F <- (claim (conteny NOT F ?P))
=>
(modify ?F (content T ?P))
)
;; Выявление противоречия между предположением о
;; правдивости и следующими из него фактами.
(defrule contra-truth
(declare (salience 10))
?W <- (world (tag ?N) (scope truth))
?S <- (statement (speaker ?Y) (tag ?N))
?P <- (claim (content T ?X) (reason ?N) (scope truth))
?Q <- (claim (content F ?X) (reason ?N) (scope truth))
=>
(printout t crlf
“Statement is inconsistent if “ ?Y “ is a knight.”
;; “Высказывание противоречиво, если “ ?Y “ правдолюбец.”
t crlf)
(retract ?Q)
(retract ?P)
(modify ?W (scope falsity))
)
Если предположить, что исходное высказывание было правдивым, то в дальнейшем обнаруживается противоречивая пара утверждений, которые затем удаляются из рабочей памяти, а значение «правдивости» предположения в объекте world изменяется на falsity (лживость). Если же после этого также будет обнаружено противоречие, то мы приходим к выводу о глобальной несовместимости условий задачи, т.е. в данной постановке мы имеем дело с логическим парадоксом.
;; Выявление противоречия между предположениями о
;; лживости и следующими из него фактами.
(defrule contra-falsity
(declare (salience 10))
?W <- (world (tag ?N) (scope falsity))
?S <- (statement (speaker ?Y) (tag ?N))
?P <- (claim (content F ?X) (reason ?N) (scope falsity))
?Q <- (claim (content T ?X) (reason ?N) (scope falsity))
=>
(printout t crlf
“Statement is inconsistent if “ ?Y “ is a knave.”
;; “Высказывание противоречиво, если “ ?Y “ лжец.”
t crlf)
(modify ?W (scope contra))
)
Правило sweep обеспечивает проверку, все ли следствия из неверного предположения удалены из памяти.
;; Удалить из базы фактов все утверждения,
;; которые следуют из предположения о правдивости.
(defrule sweep
(declare (salience 20))
(world (tag ?N) (scope falsity))
?F <- (claim (reason ?N) (scope truth))
=>
(retract ?F)
)
Обратите внимание на то, что правила contra-truth, contra-falsity и sweep имеют более высокий приоритет (значение параметра salience), чем другие правила. Этим обеспечивается как можно более ранее обнаружение противоречия, а следовательно, и удаление из базы фактов утверждений, сделанных на основе предположения, приведшего к противоречию.
Если теперь запустить на выполнение программу, представив ей исходный набор фактов, соответствующих условию задачи Р0, то программа обнаружит, что оба контекста противоречивы. Другими словами, независимо от того, предполагаем ли мы, что А говорит правду или лжет, программа обнаружит противоречие в контексте world. Трассировка программы в этом случае представлена в листинге А.1. Строки, выведенные курсивом, - сообщения основной программы, а прочие – сообщения программы трассировки. Для удобства строки, указывающие на активизацию правил, представлены полужирным шрифтом.
CLIPS> (reset)
= => f-0 (initial-fact)
= => f-1 (world (tag 1) (scope truth))
= => f-2 (statement (speaker A) (claim F A) (reason 0) (tag 1))
CLIPS> (run)
Assumption:
A is a knight, so (T A) is true.
= => f-3 (claim (content F A) (reason 1) (scope truth))
= => f-4 (claim (content T A) (reason 1) (scope truth))
Statement is inconsistent if A is a knight.
<= = f-3 (claim (content F A) (reason 1) (scope truth))
<= = f-4 (claim (content T A) (reason 1) (scope truth))
<= = f-1 (world (tag 1) (scope truth))
= => f-5 (world (tag 1) (scope falsity))
A is a knave, so (T A) is false.
= => f-6 (claim (content NOT F A) (reason 1) (scope falsity))
= => f-7 (claim (content F A) (reason 1) (scope falsity))
<= = f-6 (claim (content NOT F A) (reason 1) (scope falsity))
= => f-8 (claim (content T A) (reason 1) (scope falsity))
Statement is inconsistent if A is a knave.
<= = f-5 (world (tag 1) (scope falsity))
= => f-9 (world (tag 1) (scope contra))
Читателям, желающим самостоятельно проэкспериментировать с этой программой, я предлагаю рассмотреть другой вырожденный случай головоломок этого класса.
Предположим, что персонаж А утверждает : «Я всегда говорю правду». К какой категории следует отнести этот персонаж?
В такой постановке задача имеет неоднозначное решение. Предположение, что А правдолюбец, не приводит нас к противоречию. Но точно так же не приводит к противоречию и предположение, что А – лжец.
Ваша задача – модифицировать описанную выше программу таким образом, чтобы она давала заключение, что оба контекста непротиворечивы. Один из возможных вариантов модификации – ввести в состав программы правила consist-truth и consist-falsity, разработав их по образцу правил contra-truth и contra-falsity. Эти правила должны дать пользователю знать, что при данном положении противоречий не обнаружено, причем правила должны активизироваться в случае, когда нет больше правил, претендующих на внимание интерпретатора.
Обратите внимание на то, что в задачах этого класса недостаточно убедиться, что начальное предположение об истинности некоторого высказывания не приводит к противоречию. Необходимо еще и проверить, приведет ли к противоречию обратное предположение. Если окажется, что оно также непротиворечиво, значит, задача не имеет единственного решения.
А.4.4. Расширение набора правил – работа с составными высказываниями
Расширим тепрь возможности программы таким образом, чтобы она могла работать с составными высказываниями. Это даст возможность охватить в ней не только вырожденный случай, рассмотренный в предыдущем разделе, но и более сложные. За основу возьмем следующую головоломку.
Р4. Встречаются два персонажа, А и В, каждый из которых либо лжец, либо прадолюбец. Персонаж А говорит: «Мы оба лжецы.» К какой категории следует отнести каждого из них?
В этой задаче нам придется иметь дело с конъюнкцией, поскольку утверждение, высказанное персонажем А, моделируется выражением
F (A) ^ F (B)
Эту конъюнкцию нужно разделить на выражения-компоненты и проанализировать их непротиворечивость. Очевидно, что А не может быть правдолюбцем, поскольку это противоречит утверждению, которое содержится в его реплике. Но программа должна самостоятельно «распаковать» эту конъюнкцию для того, чтобы прийти к токому выводу.
Нам также понадобится снабдить программу и средствами обработки дизъюнкции, поскольку, если предположить, что А лжет, нужно будет оперировать с отрицанием этого утверждения, которое преобразует выражение
F (A) ^ F (B)
в
F (A) v F (B)
Таким образом, в программу нужно включить правило выполнения отрицания составных высказываний и правило, которое «понимало» бы, что дизъюнкции вроде Т (А) в действительности являются предположениями. Составное выражение T (A) v T (B) будем обрабатывать, предположив Т (А), и проанализируем, нет ли в нем противоречия. Если таковое не обнаружится, то можно предположить, что T (A) v T (B) совместимо с утверждением о том, что А лгун, т.е. F (A). Но если предположение Т (А) приведет к несовместимости, то нужно отказаться от него и предположить Т (В). Если и это предположение приведет к несовместимости, то это озаначает, что утверждение Т (А) v Т (В) несовместимо с предположением F (A). В противном случае Т (В) образует часть совместимоц интерпретации исходного высказывания.
В CLIPS составные высказывания проще всего представлять с помощью так называемой «польской» (или префиксной) нотации операций. Суть этого способа представления операций состоит в том, что символ операции предшествует символам операндов. Каждый оператор имеет фиксированное количество операндов, а потому всегда существует возможность однозначно установить область действия операций даже в случае, если операнды представляют собой вложенные выражения. Таким образом, выражение, представленное скобочной формой – (F (A)^T (B)), в польской записи будет иметь вид