<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <meta content="text/html; charset=ISO-8859-1"
      http-equiv="Content-Type">
    <title></title>
  </head>
  <body text="#000000" bgcolor="#ffffff">
    Anyone made progress on this?<br>
    <br>
    Mark<br>
    On 20/08/2010 17:02, Mark Proctor wrote:
    <blockquote cite="mid:4C6EA721.8020203@codehaus.org" type="cite">
      <meta http-equiv="content-type" content="text/html;
        charset=ISO-8859-1">
      In an effort to help encourage those thinking of learning more
      about the internals of rule engines. I have made a document on
      implementating left and right unlinking. I describe the initial
      paper in terms relevant to Drools users, and then how that can be
      implemented in Drools and a series of enhancements over the
      original paper. The task is actually surprisingly simple and you
      only need to learn a very small part of the Drools implementation
      to do it, as such it's a great getting started task. For really
      large stateful systems of hundreds or even thousands of rules and
      hundreds of thousands of facts it should save significant amounts
      of memory.<br>
      <a moz-do-not-send="true"
href="http://blog.athico.com/2010/08/left-and-right-unlinking-community.html">http://blog.athico.com/2010/08/left-and-right-unlinking-community.html</a><br>
      <br>
      Any takers?<br>
      <br>
      Mark<br>
      <br>
      <span style="font-weight: bold; font-size: 180%;">Introduction</span><br>
      The following paper describes Left and Right unlinking
      enhancements for Rete based networks:<br>
      <a moz-do-not-send="true"
        href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.45.6246">http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.45.6246

      </a><br>
      <br>
      A rete based rule engine consists of two parts of the network, the
      alpha nodes and the beta nodes. When an object is first inserted
      into the engine it is discriminated against by the object type
      Node, this is a one input and one output node. From there it may
      be further discriminated against by alpha nodes that constrain on
      literal values before reaching the right input of a join node in
      the beta part of the network. Join nodes have two inputs, left and
      right. The right input receives propagations consisting of a
      single object from the alpha part of the network. The left input
      receives propagations consisting of 1 or more objects, from the
      parent beta node. We refer to these propagating objects as
      LeftTuple and RightTuple, other engines also use the terms tokens
      or partial matches. When a tuple propagation reaches a left or
      right input it's stored in that inputs memory and it attempts to
      join with all possible tuples on the opposite side. If there are
      no tuples on the opposite side then no join can happen and the
      tuple just waits in the node's memory until a propagation from the
      opposite side attempts to join with it. If a given. It would be
      better if the engine could avoid populating that node's memory
      until both sides have tuples. Left and right unlinking are
      solutions to this problem.<br>
      <br>
      The paper proposes that a node can either be left unlinked or
      right unlinked, but not both, as then the rule would be completely
      disconnected from the network. Unlinking an input means that it
      will not receive any propagations and that the node's memory for
      that input is not populated, saving memory space. When the
      opposite side, which is still linked, receives a propagation the
      unlinked side is linked back in and receives all the none
      propagated tuples. As both sides cannot be unlinked, the paper
      describes a simple heuristic for choosing which side to unlink.
      Which ever side becomes empty first, then unlink the other. It
      says that on start up just arbitrarily chose to unlink one side as
      default. The initial hit from choosing the wrong side will be
      negligible, as the heuristic corrects this after the first set of
      propagations.<br>
      <br>
      If the left input becomes empty the right input is unlink, thus
      clearing the right input's memory too. The moment the left input
      receives a propagation it re-attaches the right input fully
      populating it's memory. The node can then attempt joins as normal.
      Vice-versa if the right input becomes empty it unlinks the left
      input. The moment the right input receives a propagation it
      re-attaches the left input fully populating it's memory so that
      the node can attempt to join as normal.<br>
      <br>
      <span style="font-weight: bold; font-size: 180%;">Implementing
        Left and Right Unlinking for shared Knowledge Bases</span><br>
      <br>
      The description of unlinking in the paper won't work for Drools or
      for other rule engines that share the knowledge base between
      multiple sessions. In Drools the session data is decoupled from
      the main knowledge base and multiple sessions can share the same
      knowledge base. The paper above describes systems where the
      session data is tightly coupled to the knowledge base and the
      knowledge base has only a single session. In shared systems a node
      input that is empty for one session might not be empty for
      another. Instead of physically unlinking the nodes, as described
      in the paper, an integer value can be used on the session's node
      memory that indicates if the node is unlinked for left, right or
      both inputs. When the propagating node attempts to propagate
      instead of just creating a left or right tuple and pushing it into
      the node. It'll first retrieve the node's memory and only create
      the tuple and propagate if it's linked.<br>
      <br>
      This is great as it also avoids creating tuple objects that would
      just be discarded afterwards as there would be nothing to join
      with, making things lighter on the GC. However it means the engine
      looks up the node memory twice, once before propagating to the
      node and also inside of the node as it attempt to do joins.
      Instead the node memory should be looked up once, prior to
      propagating and then passed as an argument, avoiding the double
      lookup.<br>
      <br>
      Traditional Rete has memory per alpha node, for each literal
      constraint, in the network. Drools does not have alpha memory,
      instead facts are pulled from the object type node. This means
      that facts may needlessly evaluate in the alpha part of the
      network, only to be refused addition to the node memory
      afterwards. Rete supports something called &#8220;node sharing&#8221;, where
      multiple rules with similar constructs use the same nodes in the
      network. For this reason shared nodes cannot easily be unlinked.
      As a compromise when the alpha node is no longer shared, the
      network can do a node memory lookup, prior to doing the evaluation
      and check if that section of the network is unlinked and avoid
      attempting the evaluation if it is. This allows for left and right
      unlinking to be used in a engine such as Drools.<br>
      <br>
      <span style="font-weight: bold; font-size: 180%;">Using Left and
        Right Unlinking at the Same Time</span><br>
      <br>
      The original paper describes an implantation in which a node
      cannot have both the left and right inputs unlinked for the same
      node. Building on the extension above to allow unlinking to work
      with a shared knowledge base the initial linking status value can
      be set to both left and right being unlinked. However in this
      initial state, where both sides are unlinked, the leaf node's
      right input isn't just waiting for a left propagation so the right
      can re-link itself (which it can't as the left is unlinked too).
      It's also waiting to receive it's first propagation, when it does
      it will link the left input back in. This will then tell it's
      parent node's right input to also do the same, i.e. wait for it's
      first right input propagation and link in the left when it
      happens. If it already has a right propagation it'll just link in
      the left anyway. This will trickle up until the root is finally
      linked in and propagations can happen as normally, and the rule's
      nodes return to the above heuristics for when to link and unlink
      the nodes.<br>
      <br>
      <span style="font-weight: bold; font-size: 180%;">Avoid
        Unnecessary Eager Propagations</span><br>
      <br>
      A rule always eagerly propagates all joins, regardless of whether
      the child node can undertake joins too, for instance of there is
      no propagates for the leaf node then no rules can fire, and the
      eager propagations are wasted work. Unlinking can be extended to
      try to prevent some level of eager propagations. Should the leaf
      node become right unlinked and that right input also become empty
      it will unlink the left too (so both sides are unlinked) and go
      back to waiting for the first right propagation, at which point
      it'll re-link the left. If the parent node also has it's right
      input unlinked at the point that it's child node unlinks the left
      it will do this too. It will repeat this up the chain until it
      reaches a node that has both left and right linked in. This stops
      any further eager matching from occurring that we know can't
      result in an activation until the leaf node has at least one right
      input.<br>
      <br>
      <span style="font-size: 180%;"><span style="font-weight: bold;">Heuristics

          to Avoid Churn from Excessive and Unnecessary Unlinking</span></span><br>
      <br>
      The only case where left and right linking would be a bad idea is
      in situations that would cause a "churn&#8221;. Churn is when a node
      with have a large amount of right input memory is continually
      caused to be linked in and linked out, forcing those nodes to be
      repeatedly populated which causes a slow down. However heuristics
      can be used here too, to avoid unnecessary unlinking. The first
      time an input becomes empty unlink the opposite and store a time
      stamp (integer counter for fact handles from the WM). Then have a
      minimum delta number, say 100. The next time it attempts to
      unlink, calculate the delta of the current time stamp (integer
      counter on fact handle) and the time stamp of the node which last
      unlinked (which was recorded at the point of unlinking) if it's
      less than 100 then do nothing and don't unlink until it's 100 or
      more. If it's 100 or more then unlink and as well as storing the
      unlink time stamp, then take the delta of 100 or more and apply a
      multiple (2, 3, 4 etc depending on how steep you want it to rise,
      3 is a good starting number) and store it. Such as if the delta is
      100 then store 300. The next time the node links and attempts to
      unlink it must be a delta of 300 or more, the time after that 900
      the time after that 2700.<br>
      <pre wrap="">
<fieldset class="mimeAttachmentHeader"></fieldset>
_______________________________________________
rules-dev mailing list
<a class="moz-txt-link-abbreviated" href="mailto:rules-dev@lists.jboss.org">rules-dev@lists.jboss.org</a>
<a class="moz-txt-link-freetext" href="https://lists.jboss.org/mailman/listinfo/rules-dev">https://lists.jboss.org/mailman/listinfo/rules-dev</a>
</pre>
    </blockquote>
    <br>
  </body>
</html>