rule trade { /* In this rule, one agent will buy a product from another agent. */ declarations people.Salesman s; people.Customer c; products.Product p; preconditions c.needs(p); // he won't buy junk... s.owns(p); s.priceAskedFor(p) <= c.getMoney(); actions s.sell(p); c.buy(p); }
people
, for
any c instance of Customer (also defined in package
people
), and for any p instance of
Product (that is defined in package products
), if the
needs method call with parameter p for the object
c returns true
, the owns method call with
parameter p for the object s returns true
,
and if the result of the invocation of the method
priceAskedFor with parameter p in object s
is less than or equals to the result of the method getMoney in
the object c, then execute the methods sell and buy
in objects s and c respectively with p as
parameter". These methods must have been defined in the appropriate
classes.
true
.
Rule ::= "rule" "{" <Rule Body> "}" Rule Body ::= <Declarations> <Local Declarations>? <Preconditions> <Actions> Declarations ::= "declarations" (<class name> <ident> ("," <ident>)* )* Local Declarations ::= "localdecl" (<class name> <ident> "=" <expression>)* Preconditions ::= "preconditions" (<expression>)* Actions ::= (Action)+ Action ::= "assert" "(" <expression> ")" | "retract" "(" <expression> ")" | "modified" "(" <expression> ")" | <expression>
rule walkInWumpusWorld { /* If the agent is in a room with a neighboring room that he knows is safe, then he should go to that room, if he hasn't visited it yet. */ declarations agents.Agent archer; localdecl places.Room currPos = archer.getCurrentPosition(); places.Room upperRoom = currPos.getUpperNeighbor(); preconditions upperRoom.isSafe(); agent.hasNotVisited(upperRoom); actions agent.moveTo(upperRoom); }
archer.getCurrentPosition().getUpperNeighbor()
could have
been used instead of upperRoom
in the condition and action
sections. We felt, though, that offering this facility to the user would
be valuable for the usability of our system.
true
for a given set of
objects, then the rule is said to be fireable, and is added to
the conflict set, where one of the rules is chosen to be fired
(which means to execute the statements of its action section).
rule BaseCase { // if n == 1 or n == 0, then the value is n. declarations jeops.examples.Fibonacci f; preconditions f.getN() <= 1; f.getValue() == -1; actions f.setValue(f.getN()); modified(f); // Yes, I modified f } rule GoDown { // if n >= 2, create two sons for the object declarations jeops.examples.Fibonacci f; preconditions f.getValue() == -1; f.getN() >= 2; f.getSon1() == null; actions jeops.examples.Fibonacci f1 = new jeops.examples.Fibonacci(f.getN() - 1); jeops.examples.Fibonacci f2 = new jeops.examples.Fibonacci(f.getN() - 2); f.setSon1(f1); f.setSon2(f2); assert(f1); // Let's tell our knowledge base assert(f2); // that these two sons exist. modified(f); } rule GoUp { // if both subproblems are solved, so let's solve this one declarations jeops.examples.Fibonacci f, f1, f2; preconditions f1 == f.getSon1(); f2 == f.getSon2(); f.getValue() == -1; f.getN() >= 2; f1 != null; f1.getValue() != -1; f2.getValue() != -1; actions f.setValue(f1.getValue() + f2.getValue()); retract(f1); // I don't need retract(f2); // them anymore... modified(f); }
assert
statement, as seen in the GoDown
rule. In this way,assert(obj)
retract
statement, as
in the rule GoUp. As you may have figured out,
retract(obj)
modified(obj)
import jeops.engine.KnowledgeBase; import jeops.examples.Fibonacci; /** * A test class for the best inference engine for Java. * * @author Carlos Figueira Filho <a href="mailto:csff@di.ufpe.br" * >csff@di.ufpe.br</a> * @version 1.0 09 May 1999 */ public class TestFibo { public static void main(String args[]) { 1 Fibonacci f = new Fibonacci(6); // What is the 6th // element of the series? 2 KnowledgeBase kb = new KnowledgeBase("fibo.rules"); 3 kb.assert(f); 4 kb.run(); 5 System.out.println("fibo(6) = " + f.getValue()); } }
kb.run()
method returns. In this way, retrieving the new information that
the "agent" has learned becomes as simple as a method
invocation.
setRuleSorter(RuleSorter)
method in the knowledge base.
This method should be invoked only when there are no objects in the
current conflict set, or they can be lost and the result of a call
to the run()
method can be impredictable. As a rule of
thumb, you can assume that the conflict set is empty after the
initialization of the knowledge base, or either after the
flush()
method has been called, or right after a
successful call to run()
.
1 Fibonacci f = new Fibonacci(6); // What is the 6th // element of the series? 2 KnowledgeBase kb = new KnowledgeBase("fibo.rules"); 2.5 kb.setRuleSorter(new jeops.engine.MRURuleSorter()); 3 kb.assert(f); 4 kb.run(); 5 System.out.println("fibo(6) = " + f.getValue());