JESS: Problem with Jess wake up in multi-threaded environment

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

JESS: Problem with Jess wake up in multi-threaded environment

Steven Goncalo
Message
I think I am seeing an occasional problem with Jess not waking up properly when a Java Bean changes value.
 
I am using Jess in a multi-threaded Java program and connecting the Jess and Java parts of the program with a handful of Java beans using the dynamic change notification. I have a deadicated jess thread in my program that calls the Rete engine with the runUntilHalt command. I have a simple GUI tied into the java beans as a PropertyChangeListener, so my display sees the same change notices as Jess does. On overnight runs, I sometimes see the program hang up unexpectedly. The display shows that the last Java task completed normally and set the Java Bean properties to show that it had gone idle and Jess should evaluate its results. Both my display and a save-facts dump with the system in this hung state show that all the conditions look correct for Jess to fire the evaluation rules and sechedule another Java task, but the rules did not fire. If I used a GUI button that asserted a fact to tell jess to change one of my program parameters, the logjam cleared up and things restarted. Since this fact did interact with my other rules, I really couldn't convince my self that I wasn't somehow changing my data to make the dormant rules file.
 
I finally added a separate button to assert a totally unrelated fact and added an arbitraty rule to detect it.
 
(defrule wake-up "no interactions with other rules"
    ?f<-(cattle-prod)
    =>
    (retract ?f)
    (printout t "Woke up" crlf)
)
 
the button just called
    engine.assertString("(cattle-prod)");
 
With the system in the locked up state, asserting the wake fact would print the expected message and suddenly cause Jess to notice that the conditions of my other scheduling rules had been met and start firing them. At a minimum, this tells me that the changes in my beans did actually get delivered to Jess and that I don't have the Jess thread in some circular deadlock with other parts of my code. I wish I had a simple test case to demonstrate the problem, but so far I've only seen it in a large program that typically runs for many hours before hitting on whatever race condition triggers the problem.
 
As a temporary work-around, I can write a trivial Java thread that periodically hits Jess with a cattle-prod, but that seems ugly, even by my standards.
 
Does any of this sound familar? It looks like a Jess bug to me, but I'd be just as happy to find a fixable problem in my code. Are there any pathological issues with threading and Jess that I should check for in my code?
 
Reply | Threaded
Open this post in threaded view
|

Re: JESS: Problem with Jess wake up in multi-threaded environment

friedman_hill ernest j
Which version of Jess? It does sound like a race condition where
notifications are getting lost.

I think Steven Goncalo wrote:

> I think I am seeing an occasional problem with Jess not waking up properly
> when a Java Bean changes value.
>  
> I am using Jess in a multi-threaded Java program and connecting the Jess and
> Java parts of the program with a handful of Java beans using the dynamic
> change notification. I have a deadicated jess thread in my program that
> calls the Rete engine with the runUntilHalt command. I have a simple GUI
> tied into the java beans as a PropertyChangeListener, so my display sees the
> same change notices as Jess does. On overnight runs, I sometimes see the
> program hang up unexpectedly. The display shows that the last Java task
> completed normally and set the Java Bean properties to show that it had gone
> idle and Jess should evaluate its results. Both my display and a save-facts
> dump with the system in this hung state show that all the conditions look
> correct for Jess to fire the evaluation rules and sechedule another Java
> task, but the rules did not fire. If I used a GUI button that asserted a
> fact to tell jess to change one of my program parameters, the logjam cleared
> up and things restarted. Since this fact did interact with my other rules, I
> really couldn't convince my self that I wasn't somehow changing my data to
> make the dormant rules file.
>  
> I finally added a separate button to assert a totally unrelated fact and
> added an arbitraty rule to detect it.
>  
> (defrule wake-up "no interactions with other rules"
>     ?f<-(cattle-prod)
>     =>
>     (retract ?f)
>     (printout t "Woke up" crlf)
> )
>  
> the button just called
>     engine.assertString("(cattle-prod)");
>  
> With the system in the locked up state, asserting the wake fact would print
> the expected message and suddenly cause Jess to notice that the conditions
> of my other scheduling rules had been met and start firing them. At a
> minimum, this tells me that the changes in my beans did actually get
> delivered to Jess and that I don't have the Jess thread in some circular
> deadlock with other parts of my code. I wish I had a simple test case to
> demonstrate the problem, but so far I've only seen it in a large program
> that typically runs for many hours before hitting on whatever race condition
> triggers the problem.
>  
> As a temporary work-around, I can write a trivial Java thread that
> periodically hits Jess with a cattle-prod, but that seems ugly, even by my
> standards.
>  
> Does any of this sound familar? It looks like a Jess bug to me, but I'd be
> just as happy to find a fixable problem in my code. Are there any
> pathological issues with threading and Jess that I should check for in my
> code?
>  



---------------------------------------------------------
Ernest Friedman-Hill  
Advanced Software Research          Phone: (925) 294-2154
Sandia National Labs                FAX:   (925) 294-2234
PO Box 969, MS 9012                 [hidden email]
Livermore, CA 94550         http://herzberg.ca.sandia.gov

--------------------------------------------------------------------
To unsubscribe, send the words 'unsubscribe jess-users [hidden email]'
in the BODY of a message to [hidden email], NOT to the list
(use your own address!) List problems? Notify [hidden email].
--------------------------------------------------------------------

Reply | Threaded
Open this post in threaded view
|

JESS: How to stop firing rules (again)

Félix Gómez Cordero
In reply to this post by Steven Goncalo
Message
Hi all,
 
I posted the same question some weeks ago. I thought at that time that my problem was fixed... but it seems now that I was wrong! So I will explain it again...
 
My one thread program works more or less as follow:
        1. Add facts 
        2. Run engine in order to check some things (through Rete#runUntilHalt())
        3. I stop the engine by calling (halt) from a rule that has an established salience of -100 which show a message like "ENGINE HAS STOPPED". This rule is fired when there is no one else left.
        4. Add more fatcs and modify some existing facts (these facts have inconsistent information until all of them are added)
        5. Check again all fact calling Rete#runUntilHalt())
        6. Stop engine...
        7. And so on ...
 
I have no problems when I add facts at the begining becase the engine is not still runing. Although before I run the engine in the step 2, and later on stops, it seems that when I add more facts or modify some actual facts, the
engine throws some unexpected errors due to the inconsistent facts... but the engine's supposed to be not running... If this could help I add and modify all those facts from differents java's functions.
 
I'v already tryed to user just Rete#run() because 'run' stops by itself but it doesn't work anyway.
 
This is my problem and is driving my crazy so I will appreciate any help... Thanks a million,
 
                                                                                                                                Félix.                                                                                                                      
 
 
 
Reply | Threaded
Open this post in threaded view
|

Re: JESS: How to stop firing rules (again)

Jason Morris


On 8/26/05, Félix Gómez Cordero <[hidden email]> wrote:
Hi all,
 
I posted the same question some weeks ago. I thought at that time that my problem was fixed... but it seems now that I was wrong! So I will explain it again...
 
 
Hi Flelix,
 
An ounce of source code is worth a pound of explanation.  :-D
Please post your actual code, and I bet the group can help you much faster.
 
Cheers,
Jason Morris
Co-Moderator Jess Listserver

 
-----------------------------------------------------
Morris Technical Solutions LLC
www.morristechnicalsolutions.com
[hidden email]
phone/fax: 503.692.1088
Reply | Threaded
Open this post in threaded view
|

Re: JESS: How to stop firing rules (again)

Félix Gómez Cordero
Hi Jason,
 
thanks for your answer, one of errors I get is throwed when I try to assert the next fact: (MAIN::call-method (id "13") (template call-method) (parent-method-id "9") (parent-id "12") (params "10")).
 
Error Message is:

Jess reported an error in routine factid

while executing (fact-id ?fact)

while executing deffunction fact-slot-value

while executing (fact-slot-value (fact-id ?fact) template)

while executing (eq (fact-slot-value (fact-id ?fact) template) imple-method)

while executing (or (eq (fact-slot-value (fact-id ?fact) template) imple-method) (eq (fact-slot-value (fact-id ?fact) template) global-method))

while executing (if (or (eq (fact-slot-value (fact-id ?fact) template) imple-method) (eq (fact-slot-value (fact-id ?fact) template) global-method)) then (return ?fact) else (if (eq (fact-slot-value (fact-id ?fact) template) class) then (return "-1") else (bind ?p-id (fact-slot-value (fact-id ?fact) parent-id)) (get-method-id ?p-id)))

while executing deffunction get-method-id

while executing (get-method-id ?p-id)

while executing (if (eq (fact-slot-value (fact-id ?fact) template) class) then (return "-1") else (bind ?p-id (fact-slot-value (fact-id ?fact) parent-id)) (get-method-id ?p-id))

while executing (if (or (eq (fact-slot-value (fact-id ?fact) template) imple-method) (eq (fact-slot-value (fact-id ?fact) template) global-method)) then (return ?fact) else (if (eq (fact-slot-value (fact-id ?fact) template) class) then (return "-1") else (bind ?p-id (fact-slot-value (fact-id ?fact) parent-id)) (get-method-id ?p-id)))

while executing deffunction get-method-id

while executing (get-method-id ?parent-id)

while executing (str-compare (get-method-id ?parent-id) (get-method-id ?param-id))

while executing (= (str-compare (get-method-id ?parent-id) (get-method-id ?param-id)) 0)

while executing 'test' CE

// The above functions are part of my rules, but the engine should not be running....

while executing rule LHS (Node2)

while executing rule LHS (MTELN)

while executing rule LHS (TECT).

Message: No such fact-id: -1.

at jess.MakeFactID.call(MiscFunctions.java:817)

at jess.FunctionHolder.call(FunctionHolder.java:30)

at jess.Funcall.execute(Funcall.java:266)

at jess.FuncallValue.resolveValue(FuncallValue.java:33)

at jess.Deffunction.call(Deffunction.java:164)

at jess.FunctionHolder.call(FunctionHolder.java:30)

at jess.Funcall.execute(Funcall.java:266)

at jess.FuncallValue.resolveValue(FuncallValue.java:33)

at jess.Eq.call(Funcall.java:1072)

..........

on the follow engine status:

ID: 0 (MAIN::initial-fact)

ID: 1 (MAIN::default-type (id "1") (template default-type) (parent-id "-2") (name "E"))

ID: 2 (MAIN::default-type (id "2") (template default-type) (parent-id "-2") (name "R"))

ID: 3 (MAIN::default-type (id "3") (template default-type) (parent-id "-2") (name "N"))

ID: 4 (MAIN::default-type (id "4") (template default-type) (parent-id "-2") (name "Cadena"))

ID: 5 (MAIN::default-type (id "5") (template default-type) (parent-id "-2") (name "Objeto"))

ID: 6 (MAIN::global-method (id "6") (parent-id "-1") (template global-method) (name "imprimir") (returned-type "-1") (params "7"))

ID: 7 (MAIN::parameter (id "7") (template parameter) (parent-id "6") (name "cadena") (type "4") (value nil))

ID: 8 (MAIN::class (id "8") (template class) (name "Clase") (implementation-method "9") (field "11"))

ID: 9 (MAIN::imple-method (id "9") (template imple-method) (method "-1") (name "metodo") (parent-id "8") (returned-type "1") (params "10") (body ))

ID: 10 (MAIN::parameter (id "10") (template parameter) (parent-id "9") (name "param") (type "1") (value nil))

ID: 11 (MAIN::imple-field (id "11") (template imple-field) (name "field") (parent-id "8") (type "1") (value nil))

 
I get similar errors messages sometimes (these errors are not shown always) when I modify facts. I modify and add facs from the next java methods:
 
// To assert facts
public static void assertFact(Fact f){
  try {
     
   // This call is not outstanding
   f.setSlotValue("id",new Value(FactIdProvider.INSTANCE.getNewFactId(),RU.STRING));
   
   
     engine.assertFact(f);
   
     facts.addFact(f);
   
  } catch (JessException e) {
   
   System.err.println(
    "Se produjo un error afirmando el hecho: "
     + f.toString());
   e.printStackTrace();
  }
 }
 
// To modify slot values
public static void setSlotValue(
  int factId,
  String slotName,
  String slotValue) {
  try {
   // Si esta vacio se establece a 'espacio en blanco'
   if (slotValue.equals("")){
    slotValue = " ";
    
   }
 
   // Se ejecuta la sentencia
   engine.executeCommand(
       "(modify " + factId + " (" + slotName + " " + slotValue + "))"); 
   
  
  } catch (JessException e) {
   System.err.println(
    "FactID como int: Se ha producido un error estableciendo el valor del slot "
     + slotName
     + " del hecho con id "
     + factId
     + " al valor "
     + slotValue);
   e.printStackTrace();
  }
 }
 
 
I hope this source code to help you to understand what I'm trying to do, thanks againg,
 
                                                                                            Felix.
 
 
 
----- Original Message -----
Sent: Saturday, August 27, 2005 8:21 AM
Subject: Re: JESS: How to stop firing rules (again)



On 8/26/05, Félix Gómez Cordero <[hidden email]> wrote:
Hi all,
 
I posted the same question some weeks ago. I thought at that time that my problem was fixed... but it seems now that I was wrong! So I will explain it again...
 
 
Hi Flelix,
 
An ounce of source code is worth a pound of explanation.  :-D
Please post your actual code, and I bet the group can help you much faster.
 
Cheers,
Jason Morris
Co-Moderator Jess Listserver

 
-----------------------------------------------------
Morris Technical Solutions LLC
www.morristechnicalsolutions.com
[hidden email]
phone/fax: 503.692.1088
Reply | Threaded
Open this post in threaded view
|

Re: JESS: How to stop firing rules (again)

friedman_hill ernest j
Felix,

The error is happening during pattern-matching, which is driven by
working memory changes (i.e., all matching involving a given fact
happens whenever that fact is asserted, retracted, or modified.)

The problems are happening during calls to fact-slot-value. It's easy
enough to fix this: don't do that, ever. There is never a reason to
call fact-slot-value on the left hand side of a rule -- you've already
got ahold of a fact (or if you don't, you can get it) and so you can
match the slots directly. Your problem is that you're calling fact-id
to get ahold of some nonexistent fact, then passing that nonexistent
fact's id (-1) to fact-slot-value, which is reporting that, indeed,
there's no such fact.

As an aside, the fact-id function is virtually never needed: it turns
a real integer into a Fact by doing a slow lookup. It's useful when
debugging from the command line, but there's never a need to use it
during normal Jess coding (although you might use it to restore links
when loading interconnected facts in from a flat file of some kind.)
If you're actually got a number and need a jess.Fact object, then use
it. But if you're got a fact binding, then it's already a jess.Fact
object.

I untangled your code extract into this, which *really* doesn't belong
on the LHS of a rule. Apparently this is part of a deffunction that
you're calling from a test CE -- i.e., from the LHS of a rule.

(if (or (eq (fact-slot-value (fact-id ?fact) template) imple-method)
        (eq (fact-slot-value (fact-id ?fact) template) global-method))
 then
    (return ?fact)
 else
    (if (eq (fact-slot-value (fact-id ?fact) template) class)
     then (return "-1")
 else
    (bind ?p-id (fact-slot-value (fact-id ?fact) parent-id))
    (get-method-id ?p-id)))

Now, you *could* simply add some "guard clauses." Just as in Java
code, you'd check things for null before using them, here you need to
check that ?fact isn't "-1" before continuing with this routine. But
the right thing to do is to break this all up and do it as pattern
matching instead. It would not only be vastly simpler, but it'd
probably be vastly more efficient, too.

I can't tell you exactly what to do, because you really need to
rethink the fundamental design. You've got this whole system designed
in a procedural way. Instead of using if-then logic on the LHS of a
rule, you instead what to write multiple rules, one for each case you
need to handle.

Something like

  (if (or (eq (fact-slot-value (fact-id ?fact) template) imple-method)
          (eq (fact-slot-value (fact-id ?fact) template) global-method))

could instead be written as something like

  (call-method (template imple-method | global-method))

if you followed my advice.

I think =?iso-8859-1?Q?F=E9lix_G=F3mez_Cordero?= wrote:
[Charset iso-8859-1 unsupported, filtering to ASCII...]

> Hi Jason,
>
> thanks for your answer, one of errors I get is throwed when I try to assert the next fact: (MAIN::call-method (id "13") (template call-method) (parent-method-id "9") (parent-id "12") (params "10")).
>
> Error Message is:
> Jess reported an error in routine factid
>
> while executing (fact-id ?fact)
>
> while executing deffunction fact-slot-value
>
> while executing (fact-slot-value (fact-id ?fact) template)
>
> while executing (eq (fact-slot-value (fact-id ?fact) template) imple-method)
>
> while executing (or (eq (fact-slot-value (fact-id ?fact) template) imple-method) (eq (fact-slot-value (fact-id ?fact) template) global-method))
>
> while executing (if (or (eq (fact-slot-value (fact-id ?fact) template) imple-method) (eq (fact-slot-value (fact-id ?fact) template) global-method)) then (return ?fact) else (if (eq (fact-slot-value (fact-id ?fact) template) class) then (return "-1") else (bind ?p-id (fact-slot-value (fact-id ?fact) parent-id)) (get-method-id ?p-id)))
>
> while executing deffunction get-method-id
>
> while executing (get-method-id ?p-id)
>
> while executing (if (eq (fact-slot-value (fact-id ?fact) template) class) then (return "-1") else (bind ?p-id (fact-slot-value (fact-id ?fact) parent-id)) (get-method-id ?p-id))
>
> while executing (if (or (eq (fact-slot-value (fact-id ?fact) template) imple-method) (eq (fact-slot-value (fact-id ?fact) template) global-method)) then (return ?fact) else (if (eq (fact-slot-value (fact-id ?fact) template) class) then (return "-1") else (bind ?p-id (fact-slot-value (fact-id ?fact) parent-id)) (get-method-id ?p-id)))
>
> while executing deffunction get-method-id
>
> while executing (get-method-id ?parent-id)
>
> while executing (str-compare (get-method-id ?parent-id) (get-method-id ?param-id))
>
> while executing (= (str-compare (get-method-id ?parent-id) (get-method-id ?param-id)) 0)
>
> while executing 'test' CE
>
> // The above functions are part of my rules, but the engine should not be running....
>
> while executing rule LHS (Node2)
>
> while executing rule LHS (MTELN)
>
> while executing rule LHS (TECT).
>
> Message: No such fact-id: -1.
>
> at jess.MakeFactID.call(MiscFunctions.java:817)
>
> at jess.FunctionHolder.call(FunctionHolder.java:30)
>
> at jess.Funcall.execute(Funcall.java:266)
>
> at jess.FuncallValue.resolveValue(FuncallValue.java:33)
>
> at jess.Deffunction.call(Deffunction.java:164)
>
> at jess.FunctionHolder.call(FunctionHolder.java:30)
>
> at jess.Funcall.execute(Funcall.java:266)
>
> at jess.FuncallValue.resolveValue(FuncallValue.java:33)
>
> at jess.Eq.call(Funcall.java:1072)
>
> .........
>
> on the follow engine status:
>
> ID: 0 (MAIN::initial-fact)
>
> ID: 1 (MAIN::default-type (id "1") (template default-type) (parent-id "-2") (name "E"))
>
> ID: 2 (MAIN::default-type (id "2") (template default-type) (parent-id "-2") (name "R"))
>
> ID: 3 (MAIN::default-type (id "3") (template default-type) (parent-id "-2") (name "N"))
>
> ID: 4 (MAIN::default-type (id "4") (template default-type) (parent-id "-2") (name "Cadena"))
>
> ID: 5 (MAIN::default-type (id "5") (template default-type) (parent-id "-2") (name "Objeto"))
>
> ID: 6 (MAIN::global-method (id "6") (parent-id "-1") (template global-method) (name "imprimir") (returned-type "-1") (params "7"))
>
> ID: 7 (MAIN::parameter (id "7") (template parameter) (parent-id "6") (name "cadena") (type "4") (value nil))
>
> ID: 8 (MAIN::class (id "8") (template class) (name "Clase") (implementation-method "9") (field "11"))
>
> ID: 9 (MAIN::imple-method (id "9") (template imple-method) (method "-1") (name "metodo") (parent-id "8") (returned-type "1") (params "10") (body ))
>
> ID: 10 (MAIN::parameter (id "10") (template parameter) (parent-id "9") (name "param") (type "1") (value nil))
>
> ID: 11 (MAIN::imple-field (id "11") (template imple-field) (name "field") (parent-id "8") (type "1") (value nil))
>
>
> I get similar errors messages sometimes (these errors are not shown always) when I modify facts. I modify and add facs from the next java methods:
>
> // To assert facts
> public static void assertFact(Fact f){
>   try {
>      
>    // This call is not outstanding
>    f.setSlotValue("id",new Value(FactIdProvider.INSTANCE.getNewFactId(),RU.STRING));
>    
>    
>      engine.assertFact(f);
>    
>      facts.addFact(f);
>    
>   } catch (JessException e) {
>    
>    System.err.println(
>     "Se produjo un error afirmando el hecho: "
>      + f.toString());
>    e.printStackTrace();
>   }
>  }
>
> // To modify slot values
> public static void setSlotValue(
>   int factId,
>   String slotName,
>   String slotValue) {
>   try {
>    // Si esta vacio se establece a 'espacio en blanco'
>    if (slotValue.equals("")){
>     slotValue = " ";
>    
>    }
>
>    // Se ejecuta la sentencia
>    engine.executeCommand(
>        "(modify " + factId + " (" + slotName + " " + slotValue + "))");
>    
>  
>   } catch (JessException e) {
>    System.err.println(
>     "FactID como int: Se ha producido un error estableciendo el valor del slot "
>      + slotName
>      + " del hecho con id "
>      + factId
>      + " al valor "
>      + slotValue);
>    e.printStackTrace();
>   }
>  }
>
>
> I hope this source code to help you to understand what I'm trying to do, thanks againg,
>
>                                                                                             Felix.
>
>
>
>   ----- Original Message -----
>   From: Jason Morris
>   To: [hidden email]
>   Sent: Saturday, August 27, 2005 8:21 AM
>   Subject: Re: JESS: How to stop firing rules (again)
>
>
>
>
>
>   On 8/26/05, F_lix G_mez Cordero <[hidden email]> wrote:
>     Hi all,
>
>     I posted the same question some weeks ago. I thought at that time that my problem was fixed... but it seems now that I was wrong! So I will explain it again...
>
>
>   Hi Flelix,
>
>   An ounce of source code is worth a pound of explanation.  :-D
>   Please post your actual code, and I bet the group can help you much faster.
>
>   Cheers,
>   Jason Morris
>   Co-Moderator Jess Listserver
>
>    
>   -----------------------------------------------------
>   Morris Technical Solutions LLC
>   www.morristechnicalsolutions.com
>   [hidden email]
>   phone/fax: 503.692.1088



---------------------------------------------------------
Ernest Friedman-Hill  
Advanced Software Research          Phone: (925) 294-2154
Sandia National Labs                FAX:   (925) 294-2234
PO Box 969, MS 9012                 [hidden email]
Livermore, CA 94550         http://herzberg.ca.sandia.gov

--------------------------------------------------------------------
To unsubscribe, send the words 'unsubscribe jess-users [hidden email]'
in the BODY of a message to [hidden email], NOT to the list
(use your own address!) List problems? Notify [hidden email].
--------------------------------------------------------------------

Reply | Threaded
Open this post in threaded view
|

Re: JESS: How to stop firing rules (again)

Félix Gómez Cordero
Hello Ernest,

thanks for your really good explanation, now I realize that I have a problem
desinng because I have placed on the LHS some responsibilities which weren't
its... That's due to I have to keep reference between facts and I do that
using a 'id' slot... That would be better done from Java... but I think that
it's too late becase my piece of software is almost finished... except for
this "little" lapse :). So I'd like to fix the problem in other manner so
that I wouldn't need to break up all my code...

Anyhow, if I add all my facts in one batch there are no exceptions. I find
problems problems just when running the engine (Rete#RunUntilHalt()) in
order to check constraints, then I wait the engine to stop and afterwards
adding/modifing/retracting facts. Is there any reason to think that I'm
re-running the engine when I call 'modify','retrarct' or 'assert' from Java?
If I can keep stopped the engine while processing the facts (because they
are inconsistent until the last one has been processed, for that reason I
get a nonexistent fact's id in fact-slot-value), I think that all will work
fine.

Thank for your help,

                                Filix.

PS. I'm sorry if my explanitions are too confused, it might be my english's
fault, although I'm not sure if they would be better in spanish...


----- Original Message -----
From: <[hidden email]>
To: <[hidden email]>
Sent: Saturday, August 27, 2005 9:42 PM
Subject: Re: JESS: How to stop firing rules (again)


> Felix,
>
> The error is happening during pattern-matching, which is driven by
> working memory changes (i.e., all matching involving a given fact
> happens whenever that fact is asserted, retracted, or modified.)
>
> The problems are happening during calls to fact-slot-value. It's easy
> enough to fix this: don't do that, ever. There is never a reason to
> call fact-slot-value on the left hand side of a rule -- you've already
> got ahold of a fact (or if you don't, you can get it) and so you can
> match the slots directly. Your problem is that you're calling fact-id
> to get ahold of some nonexistent fact, then passing that nonexistent
> fact's id (-1) to fact-slot-value, which is reporting that, indeed,
> there's no such fact.
>
> As an aside, the fact-id function is virtually never needed: it turns
> a real integer into a Fact by doing a slow lookup. It's useful when
> debugging from the command line, but there's never a need to use it
> during normal Jess coding (although you might use it to restore links
> when loading interconnected facts in from a flat file of some kind.)
> If you're actually got a number and need a jess.Fact object, then use
> it. But if you're got a fact binding, then it's already a jess.Fact
> object.
>
> I untangled your code extract into this, which *really* doesn't belong
> on the LHS of a rule. Apparently this is part of a deffunction that
> you're calling from a test CE -- i.e., from the LHS of a rule.
>
> (if (or (eq (fact-slot-value (fact-id ?fact) template) imple-method)
>        (eq (fact-slot-value (fact-id ?fact) template) global-method))
> then
>    (return ?fact)
> else
>    (if (eq (fact-slot-value (fact-id ?fact) template) class)
>     then (return "-1")
> else
>    (bind ?p-id (fact-slot-value (fact-id ?fact) parent-id))
>    (get-method-id ?p-id)))
>
> Now, you *could* simply add some "guard clauses." Just as in Java
> code, you'd check things for null before using them, here you need to
> check that ?fact isn't "-1" before continuing with this routine. But
> the right thing to do is to break this all up and do it as pattern
> matching instead. It would not only be vastly simpler, but it'd
> probably be vastly more efficient, too.
>
> I can't tell you exactly what to do, because you really need to
> rethink the fundamental design. You've got this whole system designed
> in a procedural way. Instead of using if-then logic on the LHS of a
> rule, you instead what to write multiple rules, one for each case you
> need to handle.
>
> Something like
>
>  (if (or (eq (fact-slot-value (fact-id ?fact) template) imple-method)
>          (eq (fact-slot-value (fact-id ?fact) template) global-method))
>
> could instead be written as something like
>
>  (call-method (template imple-method | global-method))
>
> if you followed my advice.
>
> I think =?iso-8859-1?Q?F=E9lix_G=F3mez_Cordero?= wrote:
> [Charset iso-8859-1 unsupported, filtering to ASCII...]
>> Hi Jason,
>>
>> thanks for your answer, one of errors I get is throwed when I try to
>> assert the next fact: (MAIN::call-method (id "13") (template call-method)
>> (parent-method-id "9") (parent-id "12") (params "10")).
>>
>> Error Message is:
>> Jess reported an error in routine factid
>>
>> while executing (fact-id ?fact)
>>
>> while executing deffunction fact-slot-value
>>
>> while executing (fact-slot-value (fact-id ?fact) template)
>>
>> while executing (eq (fact-slot-value (fact-id ?fact) template)
>> imple-method)
>>
>> while executing (or (eq (fact-slot-value (fact-id ?fact) template)
>> imple-method) (eq (fact-slot-value (fact-id ?fact) template)
>> global-method))
>>
>> while executing (if (or (eq (fact-slot-value (fact-id ?fact) template)
>> imple-method) (eq (fact-slot-value (fact-id ?fact) template)
>> global-method)) then (return ?fact) else (if (eq (fact-slot-value
>> (fact-id ?fact) template) class) then (return "-1") else (bind ?p-id
>> (fact-slot-value (fact-id ?fact) parent-id)) (get-method-id ?p-id)))
>>
>> while executing deffunction get-method-id
>>
>> while executing (get-method-id ?p-id)
>>
>> while executing (if (eq (fact-slot-value (fact-id ?fact) template) class)
>> then (return "-1") else (bind ?p-id (fact-slot-value (fact-id ?fact)
>> parent-id)) (get-method-id ?p-id))
>>
>> while executing (if (or (eq (fact-slot-value (fact-id ?fact) template)
>> imple-method) (eq (fact-slot-value (fact-id ?fact) template)
>> global-method)) then (return ?fact) else (if (eq (fact-slot-value
>> (fact-id ?fact) template) class) then (return "-1") else (bind ?p-id
>> (fact-slot-value (fact-id ?fact) parent-id)) (get-method-id ?p-id)))
>>
>> while executing deffunction get-method-id
>>
>> while executing (get-method-id ?parent-id)
>>
>> while executing (str-compare (get-method-id ?parent-id) (get-method-id
>> ?param-id))
>>
>> while executing (= (str-compare (get-method-id ?parent-id) (get-method-id
>> ?param-id)) 0)
>>
>> while executing 'test' CE
>>
>> // The above functions are part of my rules, but the engine should not be
>> running....
>>
>> while executing rule LHS (Node2)
>>
>> while executing rule LHS (MTELN)
>>
>> while executing rule LHS (TECT).
>>
>> Message: No such fact-id: -1.
>>
>> at jess.MakeFactID.call(MiscFunctions.java:817)
>>
>> at jess.FunctionHolder.call(FunctionHolder.java:30)
>>
>> at jess.Funcall.execute(Funcall.java:266)
>>
>> at jess.FuncallValue.resolveValue(FuncallValue.java:33)
>>
>> at jess.Deffunction.call(Deffunction.java:164)
>>
>> at jess.FunctionHolder.call(FunctionHolder.java:30)
>>
>> at jess.Funcall.execute(Funcall.java:266)
>>
>> at jess.FuncallValue.resolveValue(FuncallValue.java:33)
>>
>> at jess.Eq.call(Funcall.java:1072)
>>
>> .........
>>
>> on the follow engine status:
>>
>> ID: 0 (MAIN::initial-fact)
>>
>> ID: 1 (MAIN::default-type (id "1") (template default-type) (parent-id
>> "-2") (name "E"))
>>
>> ID: 2 (MAIN::default-type (id "2") (template default-type) (parent-id
>> "-2") (name "R"))
>>
>> ID: 3 (MAIN::default-type (id "3") (template default-type) (parent-id
>> "-2") (name "N"))
>>
>> ID: 4 (MAIN::default-type (id "4") (template default-type) (parent-id
>> "-2") (name "Cadena"))
>>
>> ID: 5 (MAIN::default-type (id "5") (template default-type) (parent-id
>> "-2") (name "Objeto"))
>>
>> ID: 6 (MAIN::global-method (id "6") (parent-id "-1") (template
>> global-method) (name "imprimir") (returned-type "-1") (params "7"))
>>
>> ID: 7 (MAIN::parameter (id "7") (template parameter) (parent-id "6")
>> (name "cadena") (type "4") (value nil))
>>
>> ID: 8 (MAIN::class (id "8") (template class) (name "Clase")
>> (implementation-method "9") (field "11"))
>>
>> ID: 9 (MAIN::imple-method (id "9") (template imple-method) (method "-1")
>> (name "metodo") (parent-id "8") (returned-type "1") (params "10")
>> (body ))
>>
>> ID: 10 (MAIN::parameter (id "10") (template parameter) (parent-id "9")
>> (name "param") (type "1") (value nil))
>>
>> ID: 11 (MAIN::imple-field (id "11") (template imple-field) (name "field")
>> (parent-id "8") (type "1") (value nil))
>>
>>
>> I get similar errors messages sometimes (these errors are not shown
>> always) when I modify facts. I modify and add facs from the next java
>> methods:
>>
>> // To assert facts
>> public static void assertFact(Fact f){
>>   try {
>>
>>    // This call is not outstanding
>>    f.setSlotValue("id",new
>> Value(FactIdProvider.INSTANCE.getNewFactId(),RU.STRING));
>>
>>
>>      engine.assertFact(f);
>>
>>      facts.addFact(f);
>>
>>   } catch (JessException e) {
>>
>>    System.err.println(
>>     "Se produjo un error afirmando el hecho: "
>>      + f.toString());
>>    e.printStackTrace();
>>   }
>>  }
>>
>> // To modify slot values
>> public static void setSlotValue(
>>   int factId,
>>   String slotName,
>>   String slotValue) {
>>   try {
>>    // Si esta vacio se establece a 'espacio en blanco'
>>    if (slotValue.equals("")){
>>     slotValue = " ";
>>
>>    }
>>
>>    // Se ejecuta la sentencia
>>    engine.executeCommand(
>>        "(modify " + factId + " (" + slotName + " " + slotValue + "))");
>>
>>
>>   } catch (JessException e) {
>>    System.err.println(
>>     "FactID como int: Se ha producido un error estableciendo el valor del
>> slot "
>>      + slotName
>>      + " del hecho con id "
>>      + factId
>>      + " al valor "
>>      + slotValue);
>>    e.printStackTrace();
>>   }
>>  }
>>
>>
>> I hope this source code to help you to understand what I'm trying to do,
>> thanks againg,
>>
>>
>> Felix.
>>
>>
>>
>>   ----- Original Message -----
>>   From: Jason Morris
>>   To: [hidden email]
>>   Sent: Saturday, August 27, 2005 8:21 AM
>>   Subject: Re: JESS: How to stop firing rules (again)
>>
>>
>>
>>
>>
>>   On 8/26/05, F_lix G_mez Cordero <[hidden email]> wrote:
>>     Hi all,
>>
>>     I posted the same question some weeks ago. I thought at that time
>> that my problem was fixed... but it seems now that I was wrong! So I will
>> explain it again...
>>
>>
>>   Hi Flelix,
>>
>>   An ounce of source code is worth a pound of explanation.  :-D
>>   Please post your actual code, and I bet the group can help you much
>> faster.
>>
>>   Cheers,
>>   Jason Morris
>>   Co-Moderator Jess Listserver
>>
>>
>>   -----------------------------------------------------
>>   Morris Technical Solutions LLC
>>   www.morristechnicalsolutions.com
>>   [hidden email]
>>   phone/fax: 503.692.1088
>
>
>
> ---------------------------------------------------------
> Ernest Friedman-Hill
> Advanced Software Research          Phone: (925) 294-2154
> Sandia National Labs                FAX:   (925) 294-2234
> PO Box 969, MS 9012                 [hidden email]
> Livermore, CA 94550         http://herzberg.ca.sandia.gov
>
> --------------------------------------------------------------------
> To unsubscribe, send the words 'unsubscribe jess-users [hidden email]'
> in the BODY of a message to [hidden email], NOT to the list
> (use your own address!) List problems? Notify [hidden email].
> --------------------------------------------------------------------
>
>


--------------------------------------------------------------------
To unsubscribe, send the words 'unsubscribe jess-users [hidden email]'
in the BODY of a message to [hidden email], NOT to the list
(use your own address!) List problems? Notify [hidden email].
--------------------------------------------------------------------

Reply | Threaded
Open this post in threaded view
|

Re: JESS: How to stop firing rules (again)

friedman_hill ernest j
I'm not sure how to say this any more clearly. Pattern matching
happens while facts are being asserted, modified, and retracted, and
*not* during a call to runUntilHalt(). "Running" means firing rules,
nothing more. There is no way to add facts to working memory and then
say "process them" -- it just doesn't work that way.

So beyond an overall redesign (which is by far the best choice here)
you have several other choices. First, you can simply rewrite things
so that they work if some of the facts are missing. This would be the
best thing to do, as it is in any kind of software development. If you
must call a Java method that can return null, then you have to check
for null before proceeding, right? This is the same thing. Simply
rewrite things to assume that some of the needed facts may be missing.

The problem is that because you're looking up facts in a deffunction
rather than matching them, the patterns won't be evaluated when the
later facts are asserted, so this option may not work for you.

A second, easy but very very ugly choice would be to use the "try"
function inside your deffunction to catch and hide the exceptions you
get from the missing facts. Again, this probably won't work because of
the lookup issue.

A third, more complex, choice would be to be sure to assert the facts
in an order such that the errors don't happen. It looks like you have
some facts referring to other facts, and the errors happen when the
referers have been asserted but not the referees. Make sure you assert
the referees first. This might mean doing a postorder traversal of
an object tree instead of an preorder traversal.


I think =?iso-8859-1?Q?F=E9lix_G=F3mez_Cordero?= wrote:
[Charset iso-8859-1 unsupported, filtering to ASCII...]

> Hello Ernest,
>
> thanks for your really good explanation, now I realize that I have a problem
> desinng because I have placed on the LHS some responsibilities which weren't
> its... That's due to I have to keep reference between facts and I do that
> using a 'id' slot... That would be better done from Java... but I think that
> it's too late becase my piece of software is almost finished... except for
> this "little" lapse :). So I'd like to fix the problem in other manner so
> that I wouldn't need to break up all my code...
>
> Anyhow, if I add all my facts in one batch there are no exceptions. I find
> problems problems just when running the engine (Rete#RunUntilHalt()) in
> order to check constraints, then I wait the engine to stop and afterwards
> adding/modifing/retracting facts. Is there any reason to think that I'm
> re-running the engine when I call 'modify','retrarct' or 'assert' from Java?
> If I can keep stopped the engine while processing the facts (because they
> are inconsistent until the last one has been processed, for that reason I
> get a nonexistent fact's id in fact-slot-value), I think that all will work
> fine.
>
> Thank for your help,
>
>                                 Filix.
>
> PS. I'm sorry if my explanitions are too confused, it might be my english's
> fault, although I'm not sure if they would be better in spanish...
>
>
> ----- Original Message -----
> From: <[hidden email]>
> To: <[hidden email]>
> Sent: Saturday, August 27, 2005 9:42 PM
> Subject: Re: JESS: How to stop firing rules (again)
>
>
> > Felix,
> >
> > The error is happening during pattern-matching, which is driven by
> > working memory changes (i.e., all matching involving a given fact
> > happens whenever that fact is asserted, retracted, or modified.)
> >
> > The problems are happening during calls to fact-slot-value. It's easy
> > enough to fix this: don't do that, ever. There is never a reason to
> > call fact-slot-value on the left hand side of a rule -- you've already
> > got ahold of a fact (or if you don't, you can get it) and so you can
> > match the slots directly. Your problem is that you're calling fact-id
> > to get ahold of some nonexistent fact, then passing that nonexistent
> > fact's id (-1) to fact-slot-value, which is reporting that, indeed,
> > there's no such fact.
> >
> > As an aside, the fact-id function is virtually never needed: it turns
> > a real integer into a Fact by doing a slow lookup. It's useful when
> > debugging from the command line, but there's never a need to use it
> > during normal Jess coding (although you might use it to restore links
> > when loading interconnected facts in from a flat file of some kind.)
> > If you're actually got a number and need a jess.Fact object, then use
> > it. But if you're got a fact binding, then it's already a jess.Fact
> > object.
> >
> > I untangled your code extract into this, which *really* doesn't belong
> > on the LHS of a rule. Apparently this is part of a deffunction that
> > you're calling from a test CE -- i.e., from the LHS of a rule.
> >
> > (if (or (eq (fact-slot-value (fact-id ?fact) template) imple-method)
> >        (eq (fact-slot-value (fact-id ?fact) template) global-method))
> > then
> >    (return ?fact)
> > else
> >    (if (eq (fact-slot-value (fact-id ?fact) template) class)
> >     then (return "-1")
> > else
> >    (bind ?p-id (fact-slot-value (fact-id ?fact) parent-id))
> >    (get-method-id ?p-id)))
> >
> > Now, you *could* simply add some "guard clauses." Just as in Java
> > code, you'd check things for null before using them, here you need to
> > check that ?fact isn't "-1" before continuing with this routine. But
> > the right thing to do is to break this all up and do it as pattern
> > matching instead. It would not only be vastly simpler, but it'd
> > probably be vastly more efficient, too.
> >
> > I can't tell you exactly what to do, because you really need to
> > rethink the fundamental design. You've got this whole system designed
> > in a procedural way. Instead of using if-then logic on the LHS of a
> > rule, you instead what to write multiple rules, one for each case you
> > need to handle.
> >
> > Something like
> >
> >  (if (or (eq (fact-slot-value (fact-id ?fact) template) imple-method)
> >          (eq (fact-slot-value (fact-id ?fact) template) global-method))
> >
> > could instead be written as something like
> >
> >  (call-method (template imple-method | global-method))
> >
> > if you followed my advice.
> >
> > I think =?iso-8859-1?Q?F=E9lix_G=F3mez_Cordero?= wrote:
> > [Charset iso-8859-1 unsupported, filtering to ASCII...]
> >> Hi Jason,
> >>
> >> thanks for your answer, one of errors I get is throwed when I try to
> >> assert the next fact: (MAIN::call-method (id "13") (template call-method)
> >> (parent-method-id "9") (parent-id "12") (params "10")).
> >>
> >> Error Message is:
> >> Jess reported an error in routine factid
> >>
> >> while executing (fact-id ?fact)
> >>
> >> while executing deffunction fact-slot-value
> >>
> >> while executing (fact-slot-value (fact-id ?fact) template)
> >>
> >> while executing (eq (fact-slot-value (fact-id ?fact) template)
> >> imple-method)
> >>
> >> while executing (or (eq (fact-slot-value (fact-id ?fact) template)
> >> imple-method) (eq (fact-slot-value (fact-id ?fact) template)
> >> global-method))
> >>
> >> while executing (if (or (eq (fact-slot-value (fact-id ?fact) template)
> >> imple-method) (eq (fact-slot-value (fact-id ?fact) template)
> >> global-method)) then (return ?fact) else (if (eq (fact-slot-value
> >> (fact-id ?fact) template) class) then (return "-1") else (bind ?p-id
> >> (fact-slot-value (fact-id ?fact) parent-id)) (get-method-id ?p-id)))
> >>
> >> while executing deffunction get-method-id
> >>
> >> while executing (get-method-id ?p-id)
> >>
> >> while executing (if (eq (fact-slot-value (fact-id ?fact) template) class)
> >> then (return "-1") else (bind ?p-id (fact-slot-value (fact-id ?fact)
> >> parent-id)) (get-method-id ?p-id))
> >>
> >> while executing (if (or (eq (fact-slot-value (fact-id ?fact) template)
> >> imple-method) (eq (fact-slot-value (fact-id ?fact) template)
> >> global-method)) then (return ?fact) else (if (eq (fact-slot-value
> >> (fact-id ?fact) template) class) then (return "-1") else (bind ?p-id
> >> (fact-slot-value (fact-id ?fact) parent-id)) (get-method-id ?p-id)))
> >>
> >> while executing deffunction get-method-id
> >>
> >> while executing (get-method-id ?parent-id)
> >>
> >> while executing (str-compare (get-method-id ?parent-id) (get-method-id
> >> ?param-id))
> >>
> >> while executing (= (str-compare (get-method-id ?parent-id) (get-method-id
> >> ?param-id)) 0)
> >>
> >> while executing 'test' CE
> >>
> >> // The above functions are part of my rules, but the engine should not be
> >> running....
> >>
> >> while executing rule LHS (Node2)
> >>
> >> while executing rule LHS (MTELN)
> >>
> >> while executing rule LHS (TECT).
> >>
> >> Message: No such fact-id: -1.
> >>
> >> at jess.MakeFactID.call(MiscFunctions.java:817)
> >>
> >> at jess.FunctionHolder.call(FunctionHolder.java:30)
> >>
> >> at jess.Funcall.execute(Funcall.java:266)
> >>
> >> at jess.FuncallValue.resolveValue(FuncallValue.java:33)
> >>
> >> at jess.Deffunction.call(Deffunction.java:164)
> >>
> >> at jess.FunctionHolder.call(FunctionHolder.java:30)
> >>
> >> at jess.Funcall.execute(Funcall.java:266)
> >>
> >> at jess.FuncallValue.resolveValue(FuncallValue.java:33)
> >>
> >> at jess.Eq.call(Funcall.java:1072)
> >>
> >> .........
> >>
> >> on the follow engine status:
> >>
> >> ID: 0 (MAIN::initial-fact)
> >>
> >> ID: 1 (MAIN::default-type (id "1") (template default-type) (parent-id
> >> "-2") (name "E"))
> >>
> >> ID: 2 (MAIN::default-type (id "2") (template default-type) (parent-id
> >> "-2") (name "R"))
> >>
> >> ID: 3 (MAIN::default-type (id "3") (template default-type) (parent-id
> >> "-2") (name "N"))
> >>
> >> ID: 4 (MAIN::default-type (id "4") (template default-type) (parent-id
> >> "-2") (name "Cadena"))
> >>
> >> ID: 5 (MAIN::default-type (id "5") (template default-type) (parent-id
> >> "-2") (name "Objeto"))
> >>
> >> ID: 6 (MAIN::global-method (id "6") (parent-id "-1") (template
> >> global-method) (name "imprimir") (returned-type "-1") (params "7"))
> >>
> >> ID: 7 (MAIN::parameter (id "7") (template parameter) (parent-id "6")
> >> (name "cadena") (type "4") (value nil))
> >>
> >> ID: 8 (MAIN::class (id "8") (template class) (name "Clase")
> >> (implementation-method "9") (field "11"))
> >>
> >> ID: 9 (MAIN::imple-method (id "9") (template imple-method) (method "-1")
> >> (name "metodo") (parent-id "8") (returned-type "1") (params "10")
> >> (body ))
> >>
> >> ID: 10 (MAIN::parameter (id "10") (template parameter) (parent-id "9")
> >> (name "param") (type "1") (value nil))
> >>
> >> ID: 11 (MAIN::imple-field (id "11") (template imple-field) (name "field")
> >> (parent-id "8") (type "1") (value nil))
> >>
> >>
> >> I get similar errors messages sometimes (these errors are not shown
> >> always) when I modify facts. I modify and add facs from the next java
> >> methods:
> >>
> >> // To assert facts
> >> public static void assertFact(Fact f){
> >>   try {
> >>
> >>    // This call is not outstanding
> >>    f.setSlotValue("id",new
> >> Value(FactIdProvider.INSTANCE.getNewFactId(),RU.STRING));
> >>
> >>
> >>      engine.assertFact(f);
> >>
> >>      facts.addFact(f);
> >>
> >>   } catch (JessException e) {
> >>
> >>    System.err.println(
> >>     "Se produjo un error afirmando el hecho: "
> >>      + f.toString());
> >>    e.printStackTrace();
> >>   }
> >>  }
> >>
> >> // To modify slot values
> >> public static void setSlotValue(
> >>   int factId,
> >>   String slotName,
> >>   String slotValue) {
> >>   try {
> >>    // Si esta vacio se establece a 'espacio en blanco'
> >>    if (slotValue.equals("")){
> >>     slotValue = " ";
> >>
> >>    }
> >>
> >>    // Se ejecuta la sentencia
> >>    engine.executeCommand(
> >>        "(modify " + factId + " (" + slotName + " " + slotValue + "))");
> >>
> >>
> >>   } catch (JessException e) {
> >>    System.err.println(
> >>     "FactID como int: Se ha producido un error estableciendo el valor del
> >> slot "
> >>      + slotName
> >>      + " del hecho con id "
> >>      + factId
> >>      + " al valor "
> >>      + slotValue);
> >>    e.printStackTrace();
> >>   }
> >>  }
> >>
> >>
> >> I hope this source code to help you to understand what I'm trying to do,
> >> thanks againg,
> >>
> >>
> >> Felix.
> >>
> >>
> >>
> >>   ----- Original Message -----
> >>   From: Jason Morris
> >>   To: [hidden email]
> >>   Sent: Saturday, August 27, 2005 8:21 AM
> >>   Subject: Re: JESS: How to stop firing rules (again)
> >>
> >>
> >>
> >>
> >>
> >>   On 8/26/05, F_lix G_mez Cordero <[hidden email]> wrote:
> >>     Hi all,
> >>
> >>     I posted the same question some weeks ago. I thought at that time
> >> that my problem was fixed... but it seems now that I was wrong! So I will
> >> explain it again...
> >>
> >>
> >>   Hi Flelix,
> >>
> >>   An ounce of source code is worth a pound of explanation.  :-D
> >>   Please post your actual code, and I bet the group can help you much
> >> faster.
> >>
> >>   Cheers,
> >>   Jason Morris
> >>   Co-Moderator Jess Listserver
> >>
> >>
> >>   -----------------------------------------------------
> >>   Morris Technical Solutions LLC
> >>   www.morristechnicalsolutions.com
> >>   [hidden email]
> >>   phone/fax: 503.692.1088
> >
> >
> >
> > ---------------------------------------------------------
> > Ernest Friedman-Hill
> > Advanced Software Research          Phone: (925) 294-2154
> > Sandia National Labs                FAX:   (925) 294-2234
> > PO Box 969, MS 9012                 [hidden email]
> > Livermore, CA 94550         http://herzberg.ca.sandia.gov
> >
> > --------------------------------------------------------------------
> > To unsubscribe, send the words 'unsubscribe jess-users [hidden email]'
> > in the BODY of a message to [hidden email], NOT to the list
> > (use your own address!) List problems? Notify [hidden email].
> > --------------------------------------------------------------------
> >
> >
>
>
> --------------------------------------------------------------------
> To unsubscribe, send the words 'unsubscribe jess-users [hidden email]'
> in the BODY of a message to [hidden email], NOT to the list
> (use your own address!) List problems? Notify [hidden email].
> --------------------------------------------------------------------
>



---------------------------------------------------------
Ernest Friedman-Hill  
Advanced Software Research          Phone: (925) 294-2154
Sandia National Labs                FAX:   (925) 294-2234
PO Box 969, MS 9012                 [hidden email]
Livermore, CA 94550         http://herzberg.ca.sandia.gov

--------------------------------------------------------------------
To unsubscribe, send the words 'unsubscribe jess-users [hidden email]'
in the BODY of a message to [hidden email], NOT to the list
(use your own address!) List problems? Notify [hidden email].
--------------------------------------------------------------------

Reply | Threaded
Open this post in threaded view
|

Re: JESS: How to stop firing rules (again)

Félix Gómez Cordero
Hello Ernest,

I've finally understood what you meant. I'm really sorry, I did not
understand you at the beginning bacause I had my own conception about how
jess worked and I didn't put enough attention on your mail's beginning and I
concentrated on the end, since it seemed to be my problem's solution.

I've alredy fixed it by adding a guard clause that blocks all the rules
until the facts addition period has finished. Then I modify the fact
involving that guard clause in order to match the rest of the patterns. I've
been also rewriting some code to remove calls to 'fact-id' that were,
indeed, unnecessary. Thanks againg for your help,

 Felix.



----- Original Message -----
From: <[hidden email]>
To: <[hidden email]>
Sent: Sunday, August 28, 2005 9:02 PM
Subject: Re: JESS: How to stop firing rules (again)


> I'm not sure how to say this any more clearly. Pattern matching
> happens while facts are being asserted, modified, and retracted, and
> *not* during a call to runUntilHalt(). "Running" means firing rules,
> nothing more. There is no way to add facts to working memory and then
> say "process them" -- it just doesn't work that way.
>
> So beyond an overall redesign (which is by far the best choice here)
> you have several other choices. First, you can simply rewrite things
> so that they work if some of the facts are missing. This would be the
> best thing to do, as it is in any kind of software development. If you
> must call a Java method that can return null, then you have to check
> for null before proceeding, right? This is the same thing. Simply
> rewrite things to assume that some of the needed facts may be missing.
>
> The problem is that because you're looking up facts in a deffunction
> rather than matching them, the patterns won't be evaluated when the
> later facts are asserted, so this option may not work for you.
>
> A second, easy but very very ugly choice would be to use the "try"
> function inside your deffunction to catch and hide the exceptions you
> get from the missing facts. Again, this probably won't work because of
> the lookup issue.
>
> A third, more complex, choice would be to be sure to assert the facts
> in an order such that the errors don't happen. It looks like you have
> some facts referring to other facts, and the errors happen when the
> referers have been asserted but not the referees. Make sure you assert
> the referees first. This might mean doing a postorder traversal of
> an object tree instead of an preorder traversal.
>
>
> I think =?iso-8859-1?Q?F=E9lix_G=F3mez_Cordero?= wrote:
> [Charset iso-8859-1 unsupported, filtering to ASCII...]
>> Hello Ernest,
>>
>> thanks for your really good explanation, now I realize that I have a
>> problem
>> desinng because I have placed on the LHS some responsibilities which
>> weren't
>> its... That's due to I have to keep reference between facts and I do that
>> using a 'id' slot... That would be better done from Java... but I think
>> that
>> it's too late becase my piece of software is almost finished... except
>> for
>> this "little" lapse :). So I'd like to fix the problem in other manner so
>> that I wouldn't need to break up all my code...
>>
>> Anyhow, if I add all my facts in one batch there are no exceptions. I
>> find
>> problems problems just when running the engine (Rete#RunUntilHalt()) in
>> order to check constraints, then I wait the engine to stop and afterwards
>> adding/modifing/retracting facts. Is there any reason to think that I'm
>> re-running the engine when I call 'modify','retrarct' or 'assert' from
>> Java?
>> If I can keep stopped the engine while processing the facts (because they
>> are inconsistent until the last one has been processed, for that reason I
>> get a nonexistent fact's id in fact-slot-value), I think that all will
>> work
>> fine.
>>
>> Thank for your help,
>>
>>                                 Filix.
>>
>> PS. I'm sorry if my explanitions are too confused, it might be my
>> english's
>> fault, although I'm not sure if they would be better in spanish...
>>
>>
>> ----- Original Message -----
>> From: <[hidden email]>
>> To: <[hidden email]>
>> Sent: Saturday, August 27, 2005 9:42 PM
>> Subject: Re: JESS: How to stop firing rules (again)
>>
>>
>> > Felix,
>> >
>> > The error is happening during pattern-matching, which is driven by
>> > working memory changes (i.e., all matching involving a given fact
>> > happens whenever that fact is asserted, retracted, or modified.)
>> >
>> > The problems are happening during calls to fact-slot-value. It's easy
>> > enough to fix this: don't do that, ever. There is never a reason to
>> > call fact-slot-value on the left hand side of a rule -- you've already
>> > got ahold of a fact (or if you don't, you can get it) and so you can
>> > match the slots directly. Your problem is that you're calling fact-id
>> > to get ahold of some nonexistent fact, then passing that nonexistent
>> > fact's id (-1) to fact-slot-value, which is reporting that, indeed,
>> > there's no such fact.
>> >
>> > As an aside, the fact-id function is virtually never needed: it turns
>> > a real integer into a Fact by doing a slow lookup. It's useful when
>> > debugging from the command line, but there's never a need to use it
>> > during normal Jess coding (although you might use it to restore links
>> > when loading interconnected facts in from a flat file of some kind.)
>> > If you're actually got a number and need a jess.Fact object, then use
>> > it. But if you're got a fact binding, then it's already a jess.Fact
>> > object.
>> >
>> > I untangled your code extract into this, which *really* doesn't belong
>> > on the LHS of a rule. Apparently this is part of a deffunction that
>> > you're calling from a test CE -- i.e., from the LHS of a rule.
>> >
>> > (if (or (eq (fact-slot-value (fact-id ?fact) template) imple-method)
>> >        (eq (fact-slot-value (fact-id ?fact) template) global-method))
>> > then
>> >    (return ?fact)
>> > else
>> >    (if (eq (fact-slot-value (fact-id ?fact) template) class)
>> >     then (return "-1")
>> > else
>> >    (bind ?p-id (fact-slot-value (fact-id ?fact) parent-id))
>> >    (get-method-id ?p-id)))
>> >
>> > Now, you *could* simply add some "guard clauses." Just as in Java
>> > code, you'd check things for null before using them, here you need to
>> > check that ?fact isn't "-1" before continuing with this routine. But
>> > the right thing to do is to break this all up and do it as pattern
>> > matching instead. It would not only be vastly simpler, but it'd
>> > probably be vastly more efficient, too.
>> >
>> > I can't tell you exactly what to do, because you really need to
>> > rethink the fundamental design. You've got this whole system designed
>> > in a procedural way. Instead of using if-then logic on the LHS of a
>> > rule, you instead what to write multiple rules, one for each case you
>> > need to handle.
>> >
>> > Something like
>> >
>> >  (if (or (eq (fact-slot-value (fact-id ?fact) template) imple-method)
>> >          (eq (fact-slot-value (fact-id ?fact) template) global-method))
>> >
>> > could instead be written as something like
>> >
>> >  (call-method (template imple-method | global-method))
>> >
>> > if you followed my advice.
>> >
>> > I think =?iso-8859-1?Q?F=E9lix_G=F3mez_Cordero?= wrote:
>> > [Charset iso-8859-1 unsupported, filtering to ASCII...]
>> >> Hi Jason,
>> >>
>> >> thanks for your answer, one of errors I get is throwed when I try to
>> >> assert the next fact: (MAIN::call-method (id "13") (template
>> >> call-method)
>> >> (parent-method-id "9") (parent-id "12") (params "10")).
>> >>
>> >> Error Message is:
>> >> Jess reported an error in routine factid
>> >>
>> >> while executing (fact-id ?fact)
>> >>
>> >> while executing deffunction fact-slot-value
>> >>
>> >> while executing (fact-slot-value (fact-id ?fact) template)
>> >>
>> >> while executing (eq (fact-slot-value (fact-id ?fact) template)
>> >> imple-method)
>> >>
>> >> while executing (or (eq (fact-slot-value (fact-id ?fact) template)
>> >> imple-method) (eq (fact-slot-value (fact-id ?fact) template)
>> >> global-method))
>> >>
>> >> while executing (if (or (eq (fact-slot-value (fact-id ?fact) template)
>> >> imple-method) (eq (fact-slot-value (fact-id ?fact) template)
>> >> global-method)) then (return ?fact) else (if (eq (fact-slot-value
>> >> (fact-id ?fact) template) class) then (return "-1") else (bind ?p-id
>> >> (fact-slot-value (fact-id ?fact) parent-id)) (get-method-id ?p-id)))
>> >>
>> >> while executing deffunction get-method-id
>> >>
>> >> while executing (get-method-id ?p-id)
>> >>
>> >> while executing (if (eq (fact-slot-value (fact-id ?fact) template)
>> >> class)
>> >> then (return "-1") else (bind ?p-id (fact-slot-value (fact-id ?fact)
>> >> parent-id)) (get-method-id ?p-id))
>> >>
>> >> while executing (if (or (eq (fact-slot-value (fact-id ?fact) template)
>> >> imple-method) (eq (fact-slot-value (fact-id ?fact) template)
>> >> global-method)) then (return ?fact) else (if (eq (fact-slot-value
>> >> (fact-id ?fact) template) class) then (return "-1") else (bind ?p-id
>> >> (fact-slot-value (fact-id ?fact) parent-id)) (get-method-id ?p-id)))
>> >>
>> >> while executing deffunction get-method-id
>> >>
>> >> while executing (get-method-id ?parent-id)
>> >>
>> >> while executing (str-compare (get-method-id ?parent-id) (get-method-id
>> >> ?param-id))
>> >>
>> >> while executing (= (str-compare (get-method-id ?parent-id)
>> >> (get-method-id
>> >> ?param-id)) 0)
>> >>
>> >> while executing 'test' CE
>> >>
>> >> // The above functions are part of my rules, but the engine should not
>> >> be
>> >> running....
>> >>
>> >> while executing rule LHS (Node2)
>> >>
>> >> while executing rule LHS (MTELN)
>> >>
>> >> while executing rule LHS (TECT).
>> >>
>> >> Message: No such fact-id: -1.
>> >>
>> >> at jess.MakeFactID.call(MiscFunctions.java:817)
>> >>
>> >> at jess.FunctionHolder.call(FunctionHolder.java:30)
>> >>
>> >> at jess.Funcall.execute(Funcall.java:266)
>> >>
>> >> at jess.FuncallValue.resolveValue(FuncallValue.java:33)
>> >>
>> >> at jess.Deffunction.call(Deffunction.java:164)
>> >>
>> >> at jess.FunctionHolder.call(FunctionHolder.java:30)
>> >>
>> >> at jess.Funcall.execute(Funcall.java:266)
>> >>
>> >> at jess.FuncallValue.resolveValue(FuncallValue.java:33)
>> >>
>> >> at jess.Eq.call(Funcall.java:1072)
>> >>
>> >> .........
>> >>
>> >> on the follow engine status:
>> >>
>> >> ID: 0 (MAIN::initial-fact)
>> >>
>> >> ID: 1 (MAIN::default-type (id "1") (template default-type) (parent-id
>> >> "-2") (name "E"))
>> >>
>> >> ID: 2 (MAIN::default-type (id "2") (template default-type) (parent-id
>> >> "-2") (name "R"))
>> >>
>> >> ID: 3 (MAIN::default-type (id "3") (template default-type) (parent-id
>> >> "-2") (name "N"))
>> >>
>> >> ID: 4 (MAIN::default-type (id "4") (template default-type) (parent-id
>> >> "-2") (name "Cadena"))
>> >>
>> >> ID: 5 (MAIN::default-type (id "5") (template default-type) (parent-id
>> >> "-2") (name "Objeto"))
>> >>
>> >> ID: 6 (MAIN::global-method (id "6") (parent-id "-1") (template
>> >> global-method) (name "imprimir") (returned-type "-1") (params "7"))
>> >>
>> >> ID: 7 (MAIN::parameter (id "7") (template parameter) (parent-id "6")
>> >> (name "cadena") (type "4") (value nil))
>> >>
>> >> ID: 8 (MAIN::class (id "8") (template class) (name "Clase")
>> >> (implementation-method "9") (field "11"))
>> >>
>> >> ID: 9 (MAIN::imple-method (id "9") (template imple-method) (method
>> >> "-1")
>> >> (name "metodo") (parent-id "8") (returned-type "1") (params "10")
>> >> (body ))
>> >>
>> >> ID: 10 (MAIN::parameter (id "10") (template parameter) (parent-id "9")
>> >> (name "param") (type "1") (value nil))
>> >>
>> >> ID: 11 (MAIN::imple-field (id "11") (template imple-field) (name
>> >> "field")
>> >> (parent-id "8") (type "1") (value nil))
>> >>
>> >>
>> >> I get similar errors messages sometimes (these errors are not shown
>> >> always) when I modify facts. I modify and add facs from the next java
>> >> methods:
>> >>
>> >> // To assert facts
>> >> public static void assertFact(Fact f){
>> >>   try {
>> >>
>> >>    // This call is not outstanding
>> >>    f.setSlotValue("id",new
>> >> Value(FactIdProvider.INSTANCE.getNewFactId(),RU.STRING));
>> >>
>> >>
>> >>      engine.assertFact(f);
>> >>
>> >>      facts.addFact(f);
>> >>
>> >>   } catch (JessException e) {
>> >>
>> >>    System.err.println(
>> >>     "Se produjo un error afirmando el hecho: "
>> >>      + f.toString());
>> >>    e.printStackTrace();
>> >>   }
>> >>  }
>> >>
>> >> // To modify slot values
>> >> public static void setSlotValue(
>> >>   int factId,
>> >>   String slotName,
>> >>   String slotValue) {
>> >>   try {
>> >>    // Si esta vacio se establece a 'espacio en blanco'
>> >>    if (slotValue.equals("")){
>> >>     slotValue = " ";
>> >>
>> >>    }
>> >>
>> >>    // Se ejecuta la sentencia
>> >>    engine.executeCommand(
>> >>        "(modify " + factId + " (" + slotName + " " + slotValue +
>> >> "))");
>> >>
>> >>
>> >>   } catch (JessException e) {
>> >>    System.err.println(
>> >>     "FactID como int: Se ha producido un error estableciendo el valor
>> >> del
>> >> slot "
>> >>      + slotName
>> >>      + " del hecho con id "
>> >>      + factId
>> >>      + " al valor "
>> >>      + slotValue);
>> >>    e.printStackTrace();
>> >>   }
>> >>  }
>> >>
>> >>
>> >> I hope this source code to help you to understand what I'm trying to
>> >> do,
>> >> thanks againg,
>> >>
>> >>
>> >> Felix.
>> >>
>> >>
>> >>
>> >>   ----- Original Message -----
>> >>   From: Jason Morris
>> >>   To: [hidden email]
>> >>   Sent: Saturday, August 27, 2005 8:21 AM
>> >>   Subject: Re: JESS: How to stop firing rules (again)
>> >>
>> >>
>> >>
>> >>
>> >>
>> >>   On 8/26/05, F_lix G_mez Cordero <[hidden email]> wrote:
>> >>     Hi all,
>> >>
>> >>     I posted the same question some weeks ago. I thought at that time
>> >> that my problem was fixed... but it seems now that I was wrong! So I
>> >> will
>> >> explain it again...
>> >>
>> >>
>> >>   Hi Flelix,
>> >>
>> >>   An ounce of source code is worth a pound of explanation.  :-D
>> >>   Please post your actual code, and I bet the group can help you much
>> >> faster.
>> >>
>> >>   Cheers,
>> >>   Jason Morris
>> >>   Co-Moderator Jess Listserver
>> >>
>> >>
>> >>   -----------------------------------------------------
>> >>   Morris Technical Solutions LLC
>> >>   www.morristechnicalsolutions.com
>> >>   [hidden email]
>> >>   phone/fax: 503.692.1088
>> >
>> >
>> >
>> > ---------------------------------------------------------
>> > Ernest Friedman-Hill
>> > Advanced Software Research          Phone: (925) 294-2154
>> > Sandia National Labs                FAX:   (925) 294-2234
>> > PO Box 969, MS 9012                 [hidden email]
>> > Livermore, CA 94550         http://herzberg.ca.sandia.gov
>> >
>> > --------------------------------------------------------------------
>> > To unsubscribe, send the words 'unsubscribe jess-users [hidden email]'
>> > in the BODY of a message to [hidden email], NOT to the list
>> > (use your own address!) List problems? Notify
>> > [hidden email].
>> > --------------------------------------------------------------------
>> >
>> >
>>
>>
>> --------------------------------------------------------------------
>> To unsubscribe, send the words 'unsubscribe jess-users [hidden email]'
>> in the BODY of a message to [hidden email], NOT to the list
>> (use your own address!) List problems? Notify
>> [hidden email].
>> --------------------------------------------------------------------
>>
>
>
>
> ---------------------------------------------------------
> Ernest Friedman-Hill
> Advanced Software Research          Phone: (925) 294-2154
> Sandia National Labs                FAX:   (925) 294-2234
> PO Box 969, MS 9012                 [hidden email]
> Livermore, CA 94550         http://herzberg.ca.sandia.gov
>
> --------------------------------------------------------------------
> To unsubscribe, send the words 'unsubscribe jess-users [hidden email]'
> in the BODY of a message to [hidden email], NOT to the list
> (use your own address!) List problems? Notify [hidden email].
> --------------------------------------------------------------------
>
>

--------------------------------------------------------------------
To unsubscribe, send the words 'unsubscribe jess-users [hidden email]'
in the BODY of a message to [hidden email], NOT to the list
(use your own address!) List problems? Notify [hidden email].
--------------------------------------------------------------------