Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

лаб3 clips

.doc
Скачиваний:
34
Добавлен:
09.04.2015
Размер:
47.1 Кб
Скачать

Лабораторная работа 3

ПЕРЕМЕННЫЕ

Цель работы: Изучить основные принципы работы с переменными в CLIPS

3.1 Теоретические сведения

Как и в других языках программирования, в CLIPS для хранения значений используются переменные. В отличие от фактов, которые являются статическими, или неизменными, содержание переменной динамично и изменяется по мере того, как изменяется присвоенное ей значение. Идентификатор переменной всегда начинается с вопросительного знака, за которым следует ее имя. В общем случае формат переменной выглядит следующим образом:

Примеры переменных:

?х ?sensor ?noun ?color

Перед использованием переменной ей необходимо присвоить значение. Все переменные, кроме глобальных, считаются локальными и могут использоваться только в рамках описания конструкции. К этим локальным переменным можно обращаться внутри описания, но они не определены вне него.

Чаще всего переменные описываются и получают значения в левой части правила. Например:

(defrule make-quack

(duck-sound ?sound)

=>

(assert (sounds-is ?sound) ) )

После исполнения, если в базе фактов был найден факт (duck-sound quack(анг. шарлатан)) переменной ?sound будет назначено значение quack. После чего в базе появиться факт (sounds-is quack) Получив значение, переменная сохраняет его неизменным при использовании как в левой, так и в правой части правила, если только это значение не изменяется в правой части при помощи функции bind.

(defrule addition

(numbers ?x ?y)

=>

(assert (answer (+ ?x ?y)))

(bind ?answer (+ ?x ?y))

(printout t "answer is " ?answer crlf))

Кроме значения самого факта, переменной может быть присвоено значение адреса факта. Это может оказаться удобным при необходимости манипулировать фактами непосредственно из правила. Для такого присвоения используется комбинация "<-". Следующий пример иллюстрирует присвоение переменной значения адреса факта и ее последующее использование:

CLIPS> (clear)

CLIPS> (assert (bachelor Dopey))//( бакалавр вялый)

<Fact-0>

CLIPS> (facts)

f-0 (bachelor Dopey)

For a total of 1 fact.

CLIPS> (defrule get-married

?duck <- (bachelor Dopey)

=>

(printout t "Dopey is now happily married " ?duck crlf)

(retract ?duck))

CLIPS> (run)

Dopey is now happily married <Fact-0>

CLIPS> (facts)

CLIPS>

В этом примере в базу фактов добавляется (bachelor Dopey), затем его необходимо удалить и сделать это нужно через правило (по другому его удалить можно просмотрев, базу фактов, определить под каким он номером и удалить его по номеру, это не удобно). И так в правиле, переменной ?duck присваивается адрес в памяти факта (bachelor Dopey), и затем производится очистка памяти по этому адресу.

Для определения глобальных переменных, которые видны всюду в среде CLIPS, используется конструкция defglobal. К глобальной переменной можно обратиться в любом месте, и ее значение остается независимым от других конструкций. Глобальные переменные CLIPS подобны глобальным переменным в процедурных языках программирования, таких как С или ADA. Однако, в отличие от переменных большинства процедурных языков программирования, глобальные переменные в CLIPS слабо типизированы. Фактически переменная может принимать значение любого примитивного типа CLIPS при каждом новом присваивании значения. С помощью конструктора defglobal в среде CLIPS могут быть объявлены глобальные переменные и присвоены их начальные значения.

(defglobal [<имя-модуля>] ?*<эначение-типа-symbol>*= <выражение> )

CLIPS позволяет использовать произвольное количество конструкторов defglobal. Необязательный параметр <имя-модуля> указывает модуль, в котором должны быть определены конструируемые переменные. Если имя модуля не задано, то переменные будут помещены в текущий модуль.

Глобальные переменные применяются в любом месте, где могут быть использованы переменные, созданные в левой части правил с некоторыми исключениями. Во-первых, глобальные переменные не могут использоваться как параметры в конструкторах deffunction, defmethod или обработчиках сообщений. Во-вторых, глобальные переменные не могут использоваться для получения новых значений в левой части правил.

Пример 1

(defglobal

?*x* = 3

?*y* = ?*x*

?*z* = (+ ?*x* ?*y*) )

После выполнения данного конструктора в CLIPS появятся 3 глобальные переменные: х, у, z. Переменной х присваивается целое значение 3. Переменной у – значение, сохраненное в глобальной переменной х (т.е. 3). Переменной z – сумма значений х и у (т.е. 6).

Обратите внимание, что переменная у не является указателем на переменную x, просто их значения в данный момент совпадают. Если изменить значение х, значения переменных у и z, несмотря ни на что, останутся равными 3 и 6 соответственно. Добавим еще один конструктор defglobal, объявляющий переменные вещественного и текстового типа, а также переменную со значением типа symbol.

Пример 2

(defglobal

?*d* = 7.8

?*e* = "string"

?*f* = symbol)

При выполнении команды reset все глобальные переменные получают начальные значения, определенные в конструкторе.

Команда ppdefglobal выводит в диалоговое окно системы определение заданной глобальной переменной.

Имя глобальной переменной должно быть задано без вопросительного знака и символов *, т.е. name для переменной ?*name*. Команда list-defglobals предназначена для отображения в диалоговом окне списка имен всех определенных в системе глобальных переменных.

(list-defglobals [<имя-модуля>])

Если необязательный параметр <имя-модуля> не указан, то данная команда выводит имена глобальных переменных, определенных в текущем модуле. Если параметр содержит имя конкретного модуля, команда list-defglobal выводит список переменных, определенных в заданном модуле. Допускается использование символа *. В этом случае команда выведет в диалоговое окно имена всех глобальных переменные, определенных во всех модулях системы. Команда show-defglobals, в отличие от команды list-defglobals, выводит в диалоговое окно CLIPS не только имена глобальных переменных, но и их значения. В остальном эти две команды практически идентичны.

(show-defglobals [ <имя-модуля> ])

Команда undefglobal предназначена для удаления определенных пользователем глобальных переменных.

(undefglobal <имя-глобальной-переменной>)

В качестве параметра <имя-глобальной-переменной> допускается использование символа *. В этом случае команда попытается удалить все определенные пользователем глобальные переменные. Если глобальная переменная указана, например, в определении функции, удаление этой переменной закончится неудачей. Существуют похожие функции для стандартных операций с конструкторами различных типов (не только для defglobal).

(bind <имя-переменной> <выражение>*)

Параметр выражения является необязательным. Если он не задан, то переменной будет установлено начальное значение, заданное в конструкторе defglobal. В случае, если выражение было задано, то его значение будет вычислено и результат присвоен переменной. Если было задано несколько выражений, все они будут вычислены, из их результатов будет составлено составное поле, которое будет присвоено глобальной переменной. Функция bind возвращает значение false в случае, если переменной по какой-то причине не было присвоено никакого значения. В противном случае функция возвращает значение, присвоенное переменной. Поскольку переменные в CLIPS слабо типизированы, типы значений, присваиваемые одной и той же переменной, в

разные моменты времени могут не совпадать.

3.2 Задание к работе

  1. Внести три факта (f 1) (s 2) (t 3), создать правило, которое суммирует численную часть этих трех фактов и внесет факт (r (сумма)).

(deffacts facts (f 1) (s 2) (t 3))

(reset)

(defrule additional (f ?x) (s ?y) (t ?z) => (assert (r = (+ ?x ?y ?z))))

(reset)

(run)

(facts)

  1. Определить глобальную переменную со значением open, внести факт (door is <значение переменной>). Переопределить значение переменной на close и снова внести факт.

(defglobal ?*status* = open) //для глобальных переменных необходимы **

(assert (door is ?*status*))

(facts)

(defglobal ?*status* = close)

(assert (door is ?*status*))

(facts)

  1. Определить глобальные переменные с численными значениями 1, 2, 4.5 внести факт суммирующий значения переменных. Переопределить одну из переменных на другое значение, и внести снова факт суммы.

(defglobal

?*x* = 1

?*y* = 2

?*z* = 4.5)

(assert (cym (+ ?*x* ?*y* ?*z*)))

(facts)

(defglobal

?*x* = 5)

(assert (cym (+ ?*x* ?*y* ?*z*)))

(facts)

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]