(reasons), которые связывают высказывания о том или ином гипотетическом мире. Если А утверждает, что «В – лжец», и мы предполагаем, что А – правдолюбец, то это утверждение является причиной (основанием), по которой мы можем утверждать, что в данном гипотетическом мире В – лжец, а следовательно, все утверждения, которые содержатся в репликах, произносимых В, лживы. Отслеживая такие связи между высказываниями, можно восстановить исходное состояние проблемы, если в результате рассуждений мы придем к противоречию.
Естественно, что эти объекты можно представлять в программе по- разному. Онтологический анализ практически никогда не приводит к единственному способу представления. Для первой версии CLIPS-программы я выбрал следующее представление описанных объектов:
;; Объект statement (высказывание) связан с определенным
;; персонажем (поле speaker).
;; Высказывание содержит утверждение (поле claim).
;; Высказывание имеет основание – причину (поле reason),
;; по которой ему можно доверять,
;; и тэг (tag) – это может быть произвольный
;; идентификатор.
(deftemplate statement
(field speaker (type SYMBOL))
(multifield claim (type SYMBOL))
(multifield reason (type INTEGER) (default 0))
(field tag (type INTEGER) (default 1))
)
Вместо того, чтобы фокусировать внимение на персонаже, во главу угла я ставлю произносимую им реплику (высказывание), а персонаж отношу к атрибутам высказывания. Я хочу обеспечить возможность представить определенную головоломку в виде экземпляра шаблона, приведенного ниже.
(statement (speaker A) (claim F A))
Этот шаблон можно перевести на «человеческий» язык следующим образом:
«Существует высказывание, сделанное персонажем А, в которм утверждается, что А лжец и тэг этого высказывания по умолчанию получает значение 1». Обратите внимание на то, что в поле reason также будет установлено значение по умолчанию (это значение равно 0), т.е. мы можем предположить, что никаких предшествующих высказываний, которые могли бы подтвердить данное, в этой задаче не было.
Обратите внимание, что поля claim и reason имеют квалификатор multifield, поскольку они могут содержать несколько элементов данных (более подробно об этом рассказано в Руководстве пользователя).
Однако недостаточно только представить в программе высказывания персонажей – нам понадобиться также выявить суть содержащихся в них утверждений. Далее, приняв определенное предположение о правдивости или лживости персонажа, которому принадлежит высказывание, можно построить гипотезу об истинности или лживости этого утверждения. С каждым таким утверждением свяжем уникальный числовой идентификатор.
;; Утверждение, смысл которого, например,
;; состоит в следующем,
;; Т А . . . . означает, что А правдолюбец;
;; F А . . . . означает, что А лжец.
;; Утверждение может иметь под собой
;; основание (reason) – обычно это тэг
;; высказывания (объекта statement) или тэг
;; другого утверждения (объекта claim).
;; Утверждение также характеризуется признаком scope,
;; который может принимать значение «истина» или «ложь».
(deftemplate claim
(multifield content (type SYMBOL))
(field scope (type SYMBOL))
Например, раскрыв содержимое приведенного выше высказывания в предположении, что А говорит правду, получим следующие утверждение (объект claim):
(claim (content F A) (reason 1) (scope truth)).
Таким образом, объект claim наследует содержимое от объекта statement. Последний становится обоснованием (reason) данного утверждения. Поле scope объекта claim принимает значение предположения о правдивости или лживости этого высказывания.
Еще нам потребуется представление в программе того мира (world), в котором мы в настоящее время находимся. Объекты world порождаются в момент, когда мы формируем определенные предположения. Нужно иметь возможность различать разные множества предположений и идентифицировать их в программе в тот момент, когда процесс размышлений приводит нас к противоречию. Например, противоречие между высказываниями Т(А) и F(A) отсутствует, если они истинны в разных мирах, т.е. при разных предположениях. Если у вас есть сомнения на сей счет, вернитесь вновь к примерам в самом начале раздела А.4.
Миры будем представлять в программе следующим образом:
;; Объект world представляет контекст,
;; сформированный определенными предположениями
;; о правдивости или лживости персонажей.
;; Объект имеет уникальный идентификатор в поле tag,
;; а смысл допущения – истинность или лживость –
;; фиксируется в поле scope.
(deftemplate world
(field scope (type SYMBOL) (default truth))
Обратите внимание на то, что при указанных в шаблоне значениях по умолчанию мы можем начинать каждый процесс вычислений с объекта world, имеющего в поле значение 1, причем этот «мир» можно заселить высказываниями персонажей, которых мы предположительно считаем правдолюбцами. Таким образом можно инициализировать базу фактов the-facts для задачи Р0 следующим образом:
;; Утверждение, что А лжец.
(deffacts the-facts
(world)
Если этот оператор deffacts будет включен в тот же файл, что и объявления шаблонов (а также правила, о которых речь пойдет ниже), то после загрузки этого файла в среду CLIPS нам понадобится для запуска программы дать только команду reset.
А.4.3. Разработка правил
В этом разделе мы рассмотрим набор правил, который помогает справиться с вырожденной формулировкой Р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)
(defrule unwrap-false
(world (tag ?N) (scope falsity))
(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
(modify ?F (content F ?P))
(defrule not2
(modify ?F (content T ?P))
;; Выявление противоречия между предположением о
;; правдивости и следующими из него фактами.
(defrule contra-truth
(declare (salience 10))
?W f-3 (claim (content F A) (reason 1) (scope truth))
= => f-4 (claim (content T A) (reason 1) (scope truth))
FIRE 2 contra-truth: f-1, f-2, f-4, f-3
Statement is inconsistent if A is a knight. f-7 (claim (content F A) (reason 1) (scope falsity))
FIRE 4 not2: f-6
f-8 (claim (content T A) (reason 1) (scope falsity))
FIRE 5 contra-falsity: f-5, f-2, f-7, f-8
Statement is inconsistent if A is a knave. f-9 (world (tag 1) (scope contra))
Упражнение 1
Читателям, желающим самостоятельно проэкспериментировать с этой программой, я предлагаю рассмотреть другой вырожденный случай головоломок этого класса.
Предположим, что персонаж А утверждает : «Я всегда говорю правду». К какой категории следует отнести этот персонаж?
В такой постановке задача имеет неоднозначное решение. Предположение, что А правдолюбец, не приводит нас к противоречию. Но точно так же не приводит к противоречию и предположение, что А – лжец.
Ваша задача – модифицировать описанную выше программу таким образом, чтобы она давала заключение, что оба контекста непротиворечивы. Один из возможных вариантов модификации – ввести в состав программы правила consist- truth и consist-falsity, разработав их по образцу правил contra-truth и contra-falsity. Эти правила должны дать пользователю знать, что при данном положении противоречий не обнаружено, причем правила должны активизироваться в случае, когда нет больше правил, претендующих на внимание интерпретатора.
Обратите внимание на то, что в задачах этого класса недостаточно убедиться, что начальное предположение об истинности некоторого высказывания не приводит к противоречию. Необходимо еще и проверить, приведет ли к противоречию обратное предположение. Если окажется, что оно также непротиворечиво, значит, задача не имеет единственного решения.
А.4.4. Расширение набора правил – работа с составными высказываниями
Расширим тепрь возможности программы таким образом, чтобы она могла работать с составными высказываниями. Это даст возможность охватить в ней не только вырожденный случай, рассмотренный в предыдущем разделе, но и более сложные. За основу возьмем следующую головоломку.
Р4. Встречаются два персонажа, А и В, каждый из которых либо лжец, либо прадолюбец. Персонаж А говорит: «Мы оба лжецы.» К какой категории следует отнести каждого из них?
В этой задаче нам придется иметь дело с конъюнкцией, поскольку утверждение, высказанное персонажем А, моделируется выражением
F (A) ^ F (B)
Эту конъюнкцию нужно разделить на выражения-компоненты и проанализировать их непротиворечивость. Очевидно, что А не может быть правдолюбцем, поскольку это противоречит утверждению, которое содержится в его реплике. Но программа должна самостоятельно «распаковать» эту конъюнкцию для того, чтобы прийти к токому выводу.
Нам также понадобится снабдить программу и средствами обработки дизъюнкции, поскольку, если предположить, что А лжет, нужно будет оперировать с отрицанием этого утверждения, которое преобразует выражение
Страницы: 1, 2, 3, 4, 5, 6