Introdução ao JESS Henrique Lopes Cardoso (DEI/FEUP) Outubro 2005 Setembro 2006 Setembro 2007 Setembro 2008 1 Os primórdios: Sistemas Periciais Um ramo da IA Simulação do raciocínio humano num determinado domínio SP baseados em Regras são os mais utilizados simulam o raciocínio humano utilizando conhecimento heurístico dados do problema armazenados como factos raciocínio a partir de regras do tipo SE… ENTÃO… 2 1 Sistemas baseados em Regras Contêm regras para um certo domínio conhecimento não necessariamente pericial exemplos: Vantagens: definição de “regras de negócio” (business rules) componentes de decisão (e.g. em agentes computacionais) representação intuitiva do conhecimento separação entre conhecimento e sua aplicação alterações das regras não implicam recompilação Paradigma da programação declarativa definição de regras independentes execução não sequencial interpretador decide quando aplicar que regras 3 Sistemas baseados em Regras (2) Encadeamento (aplicação) das regras: encadeamento inverso (backward-chaining) goal-driven: como provar um objectivo? linguagens de programação lógica (e.g. Prolog) encadeamento directo (forward-chaining) data-driven: o que fazer quando surge um facto? sistemas de produção (e.g. CLIPS, JESS) 4 2 Componentes de um Sistema baseado em Regras Memória de Trabalho (FACTOS) Base de Conhecimento (REGRAS) Motor de Inferência Base de Conhecimento: conjunto de regras P1, ..., Pm → Q1, ..., Qn se as premissas P1 ... Pm são verdadeiras, então executar as acções Q1 ... Qn premissas, condições, antecedente ou LHS (left-hand-side) acções, conclusões, consequente ou RHS (right-hand-side) Motor de Inferência: decide quando aplicar que regras; controla a activação e selecção de regras Memória de Trabalho: guarda dados e resultados intermédios que compõem o estado actual do problema; é examinada e alterada pelas regras, que são activadas por estes dados 5 Funcionamento do Motor de Inferência O motor de inferência funciona de uma forma cíclica, decompondo-se em três fases: 1) fase de correspondência (match): 2) fase de resolução de conflitos: agrupamento das regras cujas premissas (LHS) são satisfeitas pela memória de trabalho: é feita a instanciação das regras com os factos que tornam as suas premissas verdadeiras obtém-se o conjunto de conflito ou agenda escolha de qual a regra a executar, de acordo com uma estratégia de resolução de conflitos (p. ex., a de maior prioridade) 3) fase de acção: execução sequencial das acções (RHS) presentes na regra que foi seleccionada estas acções podem alterar a memória de trabalho, provocando a activação de novas regras 6 3 JESS – Java Expert System Shell A rule engine that very efficiently applies rules to data. Developed at Sandia National Laboratories in late 1990s, created by Dr. Ernest J. Friedman-Hill. Inspired by the AI production rule language CLIPS. Fully developed Java API for creating rule-based expert systems. How does Jess work? Jess matches facts in the fact base to rules in the rule base. The rules contain function calls that manipulate the fact base and/or other Java code. Jess uses the Rete algorithm to match patterns. 7 Jess Architecture Diagram WORKING MEMORY INFERENCE ENGINE PATTERN MATCHER RULE BASE EXECUTION ENGINE AGENDA 8 4 The Jess Language Architecturally inspired by CLIPS LISP-like syntax. Basic data structure is the list. Can be used to script Java API. JAVA --> JESS Can be used to access JavaBeans. JESS --> JAVA you can create any Java object and access its methods from within Jess! Easy to learn and use. 9 Noções básicas Símbolos (átomos) Números Strings delimitadas por "" Listas identificadores: letras, dígitos e $*=+-/<>_?#. “case-sensitive” exemplos: abc um-valor valor#1 _xpto símbolos especiais: nil TRUE FALSE delimitadas por ( e ) contêm zero ou mais símbolos, números, strings ou outras listas exemplos: (+ 3 2) (a b c) ("Hello, World") () (deftemplate foo (slot bar)) o primeiro elemento da lista chama-se a cabeça da lista Comentários texto a seguir a ; e até ao fim da linha Comentários como em C: /* … */ 10 5 Funções As chamadas a funções (quer predefinidas quer definidas pelo utilizador) são listas notação prefixa: a cabeça da lista é o nome da função exemplos: Jess> (+ 2 3) 5 Jess> (+ (+ 2 3) (* 3 3)) 14 Jess> (printout t "Answer is " 42 "!" crlf) Answer is 42! Jess> (batch examples/hello.clp) 11 Variáveis Identificadores que começam por ? podem conter um símbolo, número ou string, ou ainda uma lista pode-lhes ser atribuído um valor através da função bind Jess> (bind ?v "The value") Jess> (bind ?grocery-list (list eggs bread milk)) Verificar o valor de uma variável: Jess> (bind ?a 123) Jess> ?a 123 As variáveis não são declaradas antes do seu primeiro uso excepção: é possível criar variáveis globais, que não são destruídas aquando de um reset – defglobal 12 6 Definição de funções: deffunction (deffunction <func-name> [<doc-comment>] (<parameter>*) <expr>* [<return-specifier>] ) Exemplo: (deffunction max (?a ?b) (if (> ?a ?b) then (return ?a) else (return ?b) ) ) Funções para controlo de fluxo: foreach, if, while, … Invocação: Jess> (printout t "Greater of 3 and 5 is " (max 3 5) "." crlf) Greater of 3 and 5 is 5. 13 Factos Ordenados Ordered facts são simplesmente listas em Jess a cabeça da lista funciona como uma espécie de categoria (equivalente ao functor de uma relação em Prolog) exemplos: (shopping-list eggs milk bread) (person "Bob Smith" Male 35) (father-of danielle ejfried) asserção/retracção de factos: assert/retract visualização dos factos existentes: facts remoção de todos os factos: clear 14 7 Factos Ordenados: exemplos Jess> (reset) TRUE Jess> (assert (father-of danielle ejfried)) <Fact-1> Jess> (facts) f-0 (MAIN::initial-fact) f-1 (MAIN::father-of danielle ejfried) For a total of 2 facts in module MAIN. Jess> (retract (fact-id 1)) TRUE Jess> (facts) f-0 (MAIN::initial-fact) For a total of 1 facts in module MAIN. o facto (initial-fact) é criado pelo comando reset 15 Factos Não Ordenados: deftemplate Unordered facts permitem estruturar a informação exemplos: (person (name "Bob Smith") (age 34) (gender Male)) (automobile (make Ford) (model Explorer) (year 1999)) cada facto tem um template associado que define os seus slots (deftemplate <template-name> [extends <template-name>] [<doc-comment>] [(declare ...)] [(slot | multislot <slot-name> [(type <typespec>) [(default <value>)] ... )]* ) 16 8 Factos Não Ordenados: exemplos Jess> (deftemplate automobile "A specific car." (slot make) (slot model) (slot year (type INTEGER)) (slot color (default white))) Jess> (assert (automobile (make Chrysler) (model LeBaron) (year 1997))) <Fact-0> Jess> (facts) f-0 (MAIN::automobile (make Chrysler) (model LeBaron) (year 1997) (color white)) For a total of 1 facts in module MAIN. 17 Factos Não Ordenados: exemplos (2) slot que pode conter múltiplos valores: multislot Jess> (deftemplate box (slot location) (multislot contents)) TRUE Jess> (bind ?id (assert (box (location kitchen) (contents spatula sponge frying-pan)))) <Fact-1> à variável ?id ficou associado o identificador do facto alteração dos valores de um slot: modify extensão de um deftemplate: Jess> (deftemplate used-auto extends automobile (slot mileage) (slot blue-book-value) (multislot owners)) TRUE 18 9 Deffacts Permite definir factos agrupados que são criados aquando da invocação do comando reset exemplo: Jess> (deffacts my-facts "The documentation string" (foo bar) (box (location garage) (contents scissors paper rock)) (used-auto (year 1992) (make Saturn) (model SL1) (mileage 120000) (blue-book-value 3500) (owners ejfried))) TRUE Jess> (reset) TRUE Jess> (facts) f-0 (MAIN::initial-fact) f-1 (MAIN::foo bar) f-2 (MAIN::box (location garage) (contents scissors paper rock)) f-3 (MAIN::used-auto (make Saturn) (model SL1) (year 1992) (color white) (mileage 120000) (blue-book-value 3500) (owners ejfried)) For a total of 4 facts in module MAIN. 19 Shadow Facts São factos não ordenados que mapeiam objectos Java Templates para shadow facts desta forma, um objecto Java pode ser colocado na memória de trabalho (deftemplate <template-name> (declare (from-class <class-name>))) ou (defclass <template-name> <class-name>) O template criado fica com slots correspondentes às propriedades JavaBeans da classe public class ExampleBean { private String name = "Bob"; public String getName() { return name; } public void setName(String s) { name = s; } 20 } 10 Shadow Facts (2) Criação de objecto Java (bind <var> (new <class-name>)) Criação do shadow fact (add <Java object>) se ainda não existir, o template é criado automaticamente ou (definstance <template-name> <Java object>) 21 Shadow Facts: exemplo Criação do template: Jess> (defclass ExampleBean ExampleBean) ExampleBean Jess> (ppdeftemplate ExampleBean) "(deftemplate MAIN::ExampleBean \"$JAVA-OBJECT$ ExampleBean\" (declare (from-class ExampleBean)))" Criação de objecto Java na memória de trabalho (shadow fact): Jess> (bind ?x (new ExampleBean)) (Java-Object::ExampleBean Jess> (add ?x) <Fact-0> Jess> (facts) f-0 (MAIN::ExampleBean (class <Java-Object:java.lang.Class>) (name "Bob") (OBJECT <Java-Object:ExampleBean>)) For a total of 1 facts in module MAIN. 22 11 Utilização de objectos Java Exemplo: criação e utilização de uma Hashtable Jess> (bind ?ht (new java.util.Hashtable)) <Java-Object:java.util.Hashtable> Jess> (call ?ht put "key1" "element1") Jess> (call ?ht put "key2" "element2") Jess> (call ?ht get "key1") "element1" Exemplo: manipulação de member variables Jess> (bind ?pt (new java.awt.Point)) <Java-Object:java.awt.Point> Jess> (set-member ?pt x 37) Jess> (set-member ?pt y 42) Jess> (get-member ?pt x) 37 23 Definição de regras: defrule (defrule <rule-name> [<doc-comment>] [<fact-pattern>]* => [<function-call>]* ) Exemplo: Jess> (deftemplate person (slot firstName) (slot lastName) (slot age)) Jess> (defrule welcome-toddlers "Give a special greeting to young children" (person {age < 3}) => (printout t "Hello, little one!" crlf) ) Jess> (assert (person (age 2))) Jess> (run) Hello, little one! 24 12 Utilização de padrões em regras Expressões booleanas p/ avaliar conteúdo de slot – dentro de { } < <= > >= == != <> && || Variável para referência posterior ao valor do slot – dentro de ( ) Exemplo: Jess> (defrule teenager ?p <- (person {age > 12 && age < 20} (firstName ?name)) => (printout t ?name " is " ?p.age " years old." crlf) ) Jess> (assert (person (age 15) (firstName Maria))) Jess> (assert (person (age 18) (firstName Paul))) Jess> (run) Paul is 18 years old. Maria is 15 years old. 25 Utilização de padrões em regras (2) Testes aos slots literais variáveis (possivelmente não livres) & (e) | (ou) ~ (não) : sucede se a função seguinte retornar TRUE = igualdade entre valor do slot e retorno da função expressões regulares rodeadas por / (coord ?X&:(> ?X 10) ?) (coord ?X ; facto não orden. (coord X Y) =(+ ?X 1)) / (person (firstName /A.*/)) mais exemplos: (coord (coord (coord (coord (coord ?X ?X) ?X ?Y&~?X) ?X&~10 ?) ? 10|20) $?both) ; multislot 26 13 Pattern bindings Associar variáveis a factos no LHS: <- Útil por exemplo quando se pretende remover o facto que despoletou a regra: (defrule example-5 ?fact <- (a "retract me") => (retract ?fact) ) 27 Outros elementos and, or e not exists testa a existência de pelo menos um facto, mas dispara apenas 1 vez test permitem alterar o comportamento por defeito do LHS (em que todas as premissas têm que ser satisfeitas) avaliação de expressões (em vez de verificação da ocorrência de factos) … 28 14 JESS e Java Jess API Classes jess.Context jess.Jesp jess.JessException jess.Rete jess.Value jess.ValueVector … Interfaces jess.Userfunction … 29 JESS e Java (2) class jess.Rete motor de inferência: para construir um componente Jess numa aplicação Java, cria-se um objecto desta classe métodos: correspondentes a funções Jess: run(), reset(), clear(), assertFact(), retract(), … execução de qualquer comando Jess: eval() acrescentar funções em Java invocáveis do Jess: addUserfunction() … interface jess.Userfunction definição de funções Java invocáveis em Jess métodos getName() e call() 30 15 JESS e Java (3) import jess.*; public class ExSquare { public static void main(String[] str) { try { Rete r = new Rete(); r.eval(" (deffunction square (?n) " + " (return (* ?n ?n)) ) "); Value v = r.eval("(square 3)"); System.out.println(v); } catch (JessException ex) { System.err.println(ex); } } } 31 JESS e Java – exemplo Determinação de descontos e ofertas numa loja abordagem: criar um motor Jess com as regras a aplicar e com os dados dos produtos em catálogo quando chega uma encomenda: acrescentar os dados da encomenda à memória de trabalho correr o motor de inferência obter da memória de trabalho factos adicionados pelas regras APPLICATION / USER INTERFACE RULE WORKING BASE MEMORY Items Order Pricing rules Offers 32 16 JESS e Java – exemplo (2) public class PricingEngine { private Rete engine; private WorkingMemoryMarker marker; // Constructor public PricingEngine(Database database) throws JessException { // Create a Jess rule engine engine = new Rete(); engine.reset(); // Load the pricing rules engine.batch("pricing.clp"); // Load the catalog data into working memory engine.addAll(database.getCatalogItems()); // Mark end of catalog data for later marker = engine.mark(); } 33 JESS e Java – exemplo (3) // Method for handling a new order public Iterator run(Order orderNumber) throws JessException { // Remove any previous order data, leaving catalog data engine.resetToMark(marker); // Add the order and its contents to working memory engine.add(order); engine.add(order.getCustomer()); engine.addAll(order.getItems()); // Fire the rules that apply to this order engine.run(); // Return the list of offers created by the rules return engine.getObjects(new Filter.ByClass(Offer.class)); } } 34 17 JESS e Java – exemplo (4) Exemplos de regras: (defrule 10%-volume-discount "Give 10% discount to everybody who spends more than €100." (Order {total > 100}) => (add (new Offer "10% volume discount" (/ ?total 10))) ) (defrule 25%-multi-item-discount "Give 25% discount on items customer buys 3 or more of." (OrderItem {quantity >= 3} (price ?price)) => (add (new Offer "25% multi-item discount" (/ ?price 4))) ) 35 JESS e JADE – exemplo Regras Jess para responder a mensagens ACL utilizar um motor Jess num behaviour de um agente AGENT ACLMessage AGENT BEHAVIOUR reply ACLMessage … send Userfunction WORKING MEMORY RULE BASE … ACLMessages Message handling rules Other rules and functions 36 18 JESS e JADE – exemplo (2) public class BasicJessBehaviour extends CyclicBehaviour { Rete jess; // constructor BasicJessBehaviour(Agent agent) throws JessException { // create a Jess rule engine jess = new Rete(); // create a fact with the agent's name: (i-am X) jess.eval(" (deffacts Me " + " (i-am " + myAgent.getName() + ") )"); // define Userfunction "send" to send ACLMessages jess.addUserfunction(new JessSend(myAgent)); // load rules and functions into working memory jess.batch("JadeAgent.clp"); jess.reset(); } 37 JESS e JADE – exemplo (3) // action method public void action() { // receive a message MessageTemplate mt = ... // some template ACLMessage msg = myAgent.receive(mt); if (msg != null) { try { // convert ACLMessage into Jess fact and assert it jess.assertString(ACL2JessString(msg)); // run Jess engine jess.run(); } catch (JessException je) { ... } } else block(); } 38 19 JESS e JADE – exemplo (4) public class JessSend implements Userfunction { Agent myAgent; public JessSend(Agent a) { myAgent = a; } public String getName() { return "send"; } // JESS calls (send ?m) where ?m is an ACLMessage Jess fact public Value call(ValueVector vv, Context ctx) throws JessException { // get the Fact Fact f = vv.get(1).factValue(ctx); // convert fact into ACLMessage ACLMessage msg = JessFact2ACL(ctx, f); // send the ACLMessage myAgent.send(msg); return Funcall.TRUE; } 39 } JESS e JADE – exemplo (5) ; (limited) template of an ACLMessage (deftemplate ACLMessage (slot communicative-act) (slot sender) (multislot receiver) (slot content) ) JadeAgent.clp ; rule for handling CFP (defrule proposal ?m <- (ACLMessage (communicative-act CFP) (sender ?s) (content ?c) (receiver ?r)) (i-am ?r) => (bind ?p (gen-proposal ?c)) (assert (ACLMessage (communicative-act PROPOSE) (sender ?r) (receiver ?s) (content ?p)) ) (retract ?m) ) ; rule for sending a message (defrule send-a-message ?m <- (ACLMessage (sender ?s)) (i-am ?s) => (send ?m) (retract ?m) ) 40 20 JESS e JADE – integração JESS pode ser utilizado para implementar o módulo de raciocínio de um agente Jade num dos vários behaviours de um agente Mais informação: http://jade.tilab.com/doc/tutorials/jade-jess/jade_jess.html 41 21