Инкремент переменной CLIPS без бесконечного цикла
Я был бы очень признателен за помощь с моим проектом CLIPS.
Итак, я пытаюсь создать консультанта по породе собак. Дефемплет выглядит так:
(deftemplate breed
(multislot name)
(slot size)
(slot type-owner)
(slot Living_Space)
(slot children)
(slot grooming)
(slot exercise)
(slot noisiness)
(slot trainability)
(slot aggression)
(slot playfulness)
(slot excitability)
(slot score))
Дефицит выглядит так:
(deffacts dog-breeds
(breed (name Great_Dane)
(size 5)
(type-owner No)
(Living_Space 5)
(children 5)
(grooming 1)
(exercise 4)
(noisiness 2)
(trainability 1)
(aggression 2)
(playfulness 2)
(excitability 3)
(score 0))
Таким образом, я пишу два типа отклонений: один отводит факты, которые не соответствуют (указанным пользователем) критериям, а другой тип увеличивает значение "оценки" каждый раз, когда факт соответствует критериям. Только несколько правил убираются, поэтому для меня важно, чтобы правила приращения работали. Пользовательский ввод и критерии для каждого слота могут быть от 1 до 5.
Мой вопрос: как мне изменить следующий код, не переходя в бесконечный цикл? В конце я хочу найти факт с максимальным счетом и отобразить его.
(defrule children
(input 1)
?children <- (breed (name ?)(size ?)(type-owner ?)(Living_Space ?) (children 1|2)(grooming ?)(exercise ?)(noisiness ?)
(trainability ?)(aggression ?)(playfulness ?)(excitability ?)(score ?score)
=>
(bind ?sc (+ ?score 1))
(modify ?children (score ?sc))
1 ответ
Если единственная цель факта (вход 1) состоит в увеличении оценки и больше не нужна после увеличения оценки, просто уберите этот факт.
(defrule children
?f <- (input 1)
?children <- (breed (children 1|2) (score ?score))
=>
(retract ?f)
(bind ?sc (+ ?score 1))
(modify ?children (score ?sc)))
Обратите внимание, что я удалил все слоты из шаблона, содержащего? подстановочный знак, поскольку они не нужны.
Если факт (input 1) необходим по другим правилам, вы можете создать промежуточный факт, который можно отозвать.
(defrule create-intermediate
(input 1)
=>
(assert (increment)))
(defrule children
?f <- (increment)
?children <- (breed (children 1|2) (score ?score))
=>
(retract ?f)
(bind ?sc (+ ?score 1))
(modify ?children (score ?sc)))
Вы также можете отслеживать, что вы набрали в этом факте. Добавьте (мультислот забитый) к вашей породе, и тогда вы можете сделать это:
(defrule children
(input 1)
?children <- (breed (children 1|2) (score ?score) (scored $?scored))
(test (not (member$ children ?scored)))
=>
(bind ?sc (+ ?score 1))
(modify ?children (score ?sc) (scored children ?scored)))
Наконец, шаблоны объектов не запускаются повторно при изменении слотов, которые отсутствуют в шаблоне. Так что, если вы используете defclasses вместо deftemplates, вы можете сделать это:
(defrule children
(input 1)
?children <- (object (is-a BREED) (children 1|2))
=>
(bind ?sc (+ (send ?children get-score) 1))
(send ?children put-score ?sc))