Agregar fatos no sistema especialista em clipes para encontrar um máximo
-
24-09-2019 - |
Pergunta
Estou tentando esclarecer minha compreensão da semântica no sistema especialista em clipes, por isso estou tentando escrever algumas regras simples para agregar uma lista de fatos para encontrar o fato com o maior valor de slot. A metáfora que estou usando é a de um agente simples tentando decidir se deve comer ou dormir. Fatos que descrevem os estados do agente são expandidos para ações em potencial e, em seguida, uma regra tenta encontrar a ação final com a maior utilidade.
Este é o meu código:
(clear)
(deftemplate state
(slot name)
(slot level (type NUMBER))
)
(deftemplate action
(slot name)
(slot utility (type NUMBER))
(slot final (type INTEGER) (default 0))
)
(defrule eat-when-hungry ""
(state (name hungry) (level ?level))
=>
(assert (action (name eat) (utility ?level)))
)
(defrule sleep-when-sleepy ""
(state (name sleepy) (level ?level))
=>
(assert (action (name sleep) (utility ?level)))
)
(defrule find-final-action ""
?current_final <- (action (name ?current_final_action) (utility ?
current_final_utility) (final 1))
(action (name ?other_action) (utility ?other_utility) (final 0))
(neq ?current_final_action ?other_action)
(< ?current_final_action ?other_action)
=>
(modify ?current_final (name ?other_action) (utility ?
other_utility))
)
(assert (action (name none) (utility 0.0) (final 1)))
(assert (state (name hungry) (level 0.5)))
(assert (state (name sleepy) (level 0.1)))
(run)
(facts)
Depois de executar isso, eu esperaria que a ação final fosse:
(action (name eat) (utility 0.5) (final 1))
No entanto, os clipes avaliam para:
(action (name none) (utility 0.0) (final 1))
Indicando a regra de ação final nunca ativa. Por que é isso? Como você iteraria sobre um grupo de fatos e encontraria aquele com o valor do slot Min/Max?
Solução
Sua regra teve alguns erros. Aqui está a versão corrigida:
(defrule find-final-action ""
?current_final <- (action (name ?current_final_action)
(utility ?current_final_utility) (final 1))
(action (name ?other_action) (utility ?other_utility) (final 0))
(test (neq ?current_final_action ?other_action))
(test (< ?current_final_utility ?other_utility))
=>
(modify ?current_final (name ?other_action) (utility ?other_utility)))
Um método alternativo que não requer armazenamento de cálculos intermediários e várias demissões de regras é o seguinte:
(defrule find-final-action-2 ""
(declare (salience -10)) ; lower salience to allow all actions to be asserted first
(action (name ?action) (utility ?utility))
(not (action (utility ?other_utility&:(> ?other_utility ?utility))))
=>
(printout t "Final action is " ?action crlf))