"wipe" facts

vranoch
2012-04-18
2012-11-23
  • vranoch
    vranoch
    2012-04-18

    Hello. Is there any way how to "wipe" all facts at once without reevaluating pattern matching for each single retract - e.g. to prepare the environment for the next independant run? The (reset ) command calls RemoveAllFacts which in a loop calls Retract for every fact. This actually can take quite a long time.

    Thanks Vranoch.

     
  • Gary Riley
    Gary Riley
    2012-04-18

    No, there isn't a way to do this.

     
  • vranoch
    vranoch
    2012-04-18

    Thanks, however, would it be feasible to implement this? Something similar works with instances - delayed pattern matching. What principles this functionality is based on?

    Thanks Vranoch

     
  • Gary Riley
    Gary Riley
    2012-04-19

    Delayed pattern matching for objects is primarily useful if you're making lots of changes to slots. Rather than triggering pattern matching for each slot value change, you make all the changes and then process a single update of the instance. The creation, update, or deletion of instances is still done one instance at a time, so you're not processing all instances at once. Implementing a wipe is feasible, but would require fairly detailed knowledge of the CLIPS internals.

    CLIPS> (reset)
    CLIPS> (defclass A (is-a USER))
    CLIPS> (watch instances)
    CLIPS> (watch activations)
    CLIPS> (defrule match (object (is-a A)) =>)
    CLIPS> (make-instance a1 of A)
    ==> instance [a1] of A
    ==> Activation 0      match: [a1]
    [a1]
    CLIPS> (make-instance a2 of A)
    ==> instance [a2] of A
    ==> Activation 0      match: [a2]
    [a2]
    CLIPS> (reset)
    <== instance [initial-object] of INITIAL-OBJECT
    <== instance [a1] of A
    <== Activation 0      match: [a1]
    <== instance [a2] of A
    <== Activation 0      match: [a2]
    ==> instance [initial-object] of INITIAL-OBJECT
    CLIPS> 
    (make-instance a1 of A)
    ==> instance [a1] of A
    ==> Activation 0      match: [a1]
    [a1]
    CLIPS> (make-instance a2 of A)
    ==> instance [a2] of A
    ==> Activation 0      match: [a2]
    [a2]
    CLIPS> 
    (object-pattern-match-delay
       (printout t "Start" crlf)
       (send [a1] delete)
       (send [a2] delete)
       (printout t "End" crlf))
    Start
    <== instance [a1] of A
    <== instance [a2] of A
    End
    <== Activation 0      match: <stale instance [a1]>
    <== Activation 0      match: <stale instance [a2]>
    CLIPS>
    
     
  • vranoch
    vranoch
    2012-04-19

    hmm … that is unfortunately not my case :-( . Actually, what I need to do is to repeatedly process new sets of facts against the same set of rules. That is, I need to clean the environment before asserting new set of facts. Since I found out that (reset ) may take quite a long time I create a new environment and (bload ) the rules for every single run. I would still like to avoid repeated reading of rules. Is there any other way?

     
  • Gary Riley
    Gary Riley
    2012-04-20

    You'd be better off fully understanding the problem before you start devising solutions to fix it. If retracting all of the facts to return the system to its initial state is computationally expensive, then it's likely that building the state by asserting the facts was also computationally expensive. If you can optimize your rules so that the reset is more efficient, you'll likely optimize your execution performance as well.

    For example, suppose you've written a highly inefficient deffunction that is called from the LHS of a rule (and could be invoked either by an assert or retract of a fact). If you add wipe functionality that clears out the system state without performing retractions, you'll bypass this inefficient code when performing a reset, but you'll still end up calling it when your program is executing as it performs asserts and retracts.

    There are a number of things you can do to look for performance issues. The profiling command in section 13.16 of the Basic Programming Guide can help you find issues with the procedural portions of your code like deffunctions and can sometimes be helpful when analyzing your rules. If your program is modular and you can easily exclude groups of rules, you can run your program excluding some of your rules and see if performance improves. Another trick is to run your program after issuing a (watch facts) command. If you see facts being quickly asserted and/or retracted and then there's a long pause after a particular assertion or retraction, you can focus on rules with patterns that would match that fact.

    After that it becomes a bit more esoteric and you have to have a bit more knowledge about the program in question: number of rules, complexity of rules, number of facts, and how frequently the facts change. Once you're able to identify if there are rules causing issues, there are some general tips on improving performance in Appendix F of the Basic Programming Guide.

    If you're using CLIPS 6.24, you should try using version 6.3 as there are some performance improvements primarily for systems with large numbers of facts.

     
  • vranoch
    vranoch
    2012-04-20

    thanks a lot for hints. Coincidentally, I have just finished an upgrade from 6.24 to 6.30 - primarily because of its UTF8 support. Thanks for it, that was a good job. 

    It is already some time when I tested the cleaning of environment up. Then I decided to re-create it for each run. I should perhaps do some new specific tests to see whether the problem does really exist or not in fact.