/// <summary> /// it's unlikely 2 rules are identical, except for the name. The implementation /// gets the current memory and propogates, but I wonder how much sense this /// makes in a real production environment. An user really shouldn't be deploying /// identical rules with different rule name. /// </summary> /// <param name="node">The node.</param> /// <param name="engine">The engine.</param> /// <param name="mem">The mem.</param> public virtual void addSuccessorNode(TerminalNode node, Rete engine, IWorkingMemory mem) { if (addNode(node)) { // first, we Get the memory for this node IGenericMap <Object, Object> leftmem = (IGenericMap <Object, Object>)mem.getBetaLeftMemory(this); // now we iterate over the entry set IEnumerator itr = leftmem.Values.GetEnumerator(); while (itr.MoveNext()) { Object omem = itr.Current; if (omem is IBetaMemory) { IBetaMemory bmem = (IBetaMemory)omem; Index left = bmem.Index; // iterate over the matches IGenericMap <Object, Object> rightmem = (IGenericMap <Object, Object>)mem.getBetaRightMemory(this); IEnumerator ritr = rightmem.Keys.GetEnumerator(); while (ritr.MoveNext()) { IFact rfcts = (IFact)ritr.Current; // merge the left and right fact into a new Array node.assertFacts(left.add(rfcts), engine, mem); } } } } }
/// <summary> /// Method is used to pass a fact to the successor nodes /// </summary> /// <param name="inx">The inx.</param> /// <param name="engine">The engine.</param> /// <param name="mem">The mem.</param> protected internal virtual void propogateAssert(Index inx, Rete engine, IWorkingMemory mem) { for (int idx = 0; idx < successorNodes.Length; idx++) { BaseJoin baseJoin = successorNodes[idx] as BaseJoin; if (baseJoin != null) { baseJoin.assertLeft(inx, engine, mem); return; } TerminalNode terminalNode = successorNodes[idx] as TerminalNode; if (terminalNode != null) { terminalNode.assertFacts(inx, engine, mem); return; } //BaseNode node = successorNodes[idx]; //if (node is BaseJoin) //{ // ((BaseJoin) node).assertLeft(inx, engine, mem); //} //else if (node is TerminalNode) //{ // ((TerminalNode) node).assertFacts(inx, engine, mem); //} } }
/// <summary> NotJoin has to have a special addSuccessorNode since it needs /// to just propogate the left facts if it has zero matches. /// </summary> public override void addSuccessorNode(TerminalNode node, Rete engine, IWorkingMemory mem) { if (addNode(node)) { // first, we Get the memory for this node IGenericMap <Object, Object> leftmem = (IGenericMap <Object, Object>)mem.getBetaLeftMemory(this); // now we iterate over the entry set IEnumerator itr = leftmem.Values.GetEnumerator(); while (itr.MoveNext()) { Object omem = itr.Current; if (omem is IBetaMemory) { IBetaMemory bmem = (IBetaMemory)omem; EqHashIndex inx = new EqHashIndex(NodeUtils.getLeftValues(binds, bmem.LeftFacts)); HashedAlphaMemoryImpl rightmem = (HashedAlphaMemoryImpl)mem.getBetaRightMemory(this); // we don't bother adding the right fact to the left, since // the right side is already Hashed if (rightmem.count(inx) == 0) { node.assertFacts(bmem.Index, engine, mem); } } } } }
/// <summary> Set the Current node in the sequence of 1-input nodes. /// The Current node can be an AlphaNode or a LIANode. /// </summary> /// <param name="">node /// /// </param> public override void addSuccessorNode(BaseNode node, Rete engine, IWorkingMemory mem) { if (addNode(node)) { // if there are matches, we propogate the facts to // the new successor only IAlphaMemory alpha = (IAlphaMemory)mem.getAlphaMemory(this); if (alpha.size() > 0) { IEnumerator itr = alpha.GetEnumerator(); while (itr.MoveNext()) { if (node is BaseAlpha) { BaseAlpha next = (BaseAlpha)node; next.assertFact((IFact)itr.Current, engine, mem); } else if (node is BaseJoin) { BaseJoin next = (BaseJoin)node; next.assertRight((IFact)itr.Current, engine, mem); } else if (node is TerminalNode) { TerminalNode next = (TerminalNode)node; Index inx = new Index(new IFact[] { (IFact)itr.Current }); next.assertFacts(inx, engine, mem); } } } } }
/// <summary> NotJoin has to have a special addSuccessorNode since it needs /// to just propogate the left facts if it has zero matches. /// </summary> public override void addSuccessorNode(TerminalNode node, Rete engine, IWorkingMemory mem) { if (addNode(node)) { // first, we Get the memory for this node IGenericMap<Object, Object> leftmem = (IGenericMap<Object, Object>) mem.getBetaLeftMemory(this); // now we iterate over the entry set IEnumerator itr = leftmem.Values.GetEnumerator(); while (itr.MoveNext()) { Object omem = itr.Current; if (omem is IBetaMemory) { IBetaMemory bmem = (IBetaMemory) omem; EqHashIndex inx = new EqHashIndex(NodeUtils.getLeftValues(binds, bmem.LeftFacts)); HashedAlphaMemoryImpl rightmem = (HashedAlphaMemoryImpl) mem.getBetaRightMemory(this); // we don't bother adding the right fact to the left, since // the right side is already Hashed if (rightmem.count(inx) == 0) { node.assertFacts(bmem.Index, engine, mem); } } } } }
/// <summary> Add a successor node /// </summary> public override void addSuccessorNode(BaseNode node, Rete engine, IWorkingMemory mem) { if (!containsNode(successorNodes, node) && !successor2.Contains(node)) { if (node is BaseJoin || node is TerminalNode) { successor2.Add(node); } else { // we test to see if the operator is ==, nil, not nil // if the node isn't BaseJoin, it should be BaseAlpha BaseAlpha ba = (BaseAlpha)node; if (ba.Operator == Constants.LESS || ba.Operator == Constants.GREATER || ba.Operator == Constants.LESSEQUAL || ba.Operator == Constants.GREATEREQUAL || ba.Operator == Constants.NOTEQUAL || ba.Operator == Constants.NOTNILL) { successor2.Add(node); } else { addNode(node); } } if (gauranteeUnique && node is AlphaNode) { // now we use CompositeIndex instead of HashString AlphaNode anode = (AlphaNode)node; entries.Put(anode.HashIndex, node); // we increment the node count for the slot deftemplate.getSlot(anode.slot.Id).incrementNodeCount(); } // if there are matches, we propogate the facts to // the new successor only IAlphaMemory alpha = (IAlphaMemory)mem.getAlphaMemory(this); if (alpha.size() > 0) { IEnumerator itr = alpha.GetEnumerator(); while (itr.MoveNext()) { IFact f = (IFact)itr.Current; if (node is BaseAlpha) { BaseAlpha next = (BaseAlpha)node; next.assertFact(f, engine, mem); } else if (node is BaseJoin) { BaseJoin next = (BaseJoin)node; next.assertRight(f, engine, mem); } else if (node is TerminalNode) { TerminalNode t = (TerminalNode)node; Index inx = new Index(new IFact[] { f }); t.assertFacts(inx, engine, mem); } } } } }
/// <summary> Propogate the assert to the successor nodes /// </summary> /// <param name="">fact /// </param> /// <param name="">engine /// /// </param> protected internal override void propogateAssert(IFact fact, Rete engine, IWorkingMemory mem) { for (int idx = 0; idx < successorNodes.Length; idx++) { BaseNode nNode = successorNodes[idx]; if (nNode is BaseJoin) { BaseJoin next = (BaseJoin) nNode; IFact[] newf = new IFact[] {fact}; next.assertLeft(new Index(newf), engine, mem); } else if (nNode is TerminalNode) { IFact[] newf = new IFact[] {fact}; TerminalNode tn = (TerminalNode) nNode; tn.assertFacts(new Index(newf), engine, mem); } } }
/// <summary> Method is used to pass a fact to the successor nodes /// </summary> /// <param name="">fact /// </param> /// <param name="">engine /// /// </param> protected internal virtual void propogateAssert(IFact fact, Rete engine, IWorkingMemory mem) { for (int idx = 0; idx < successorNodes.Length; idx++) { Object nNode = successorNodes[idx]; if (nNode is BaseAlpha) { BaseAlpha next = (BaseAlpha)nNode; next.assertFact(fact, engine, mem); } else if (nNode is BaseJoin) { BaseJoin next = (BaseJoin)nNode; next.assertRight(fact, engine, mem); } else if (nNode is TerminalNode) { TerminalNode next = (TerminalNode)nNode; Index inx = new Index(new IFact[] { fact }); next.assertFacts(inx, engine, mem); } } }
/// <summary> NotJoin has to have a special addSuccessorNode since it needs /// to just propogate the left facts if it has zero matches. /// </summary> public override void addSuccessorNode(TerminalNode node, Rete engine, IWorkingMemory mem) { if (addNode(node)) { // first, we Get the memory for this node IGenericMap <Object, Object> leftmem = (IGenericMap <Object, Object>)mem.getBetaLeftMemory(this); // now we iterate over the entry set IEnumerator itr = leftmem.Values.GetEnumerator(); while (itr.MoveNext()) { Object omem = itr.Current; if (omem is IBetaMemory) { IBetaMemory bmem = (IBetaMemory)omem; // iterate over the matches if (bmem.matchCount() == 0) { node.assertFacts(bmem.Index, engine, mem); } } } } }
/// <summary> NotJoin has to have a special addSuccessorNode since it needs /// to just propogate the left facts if it has zero matches. /// </summary> public override void addSuccessorNode(TerminalNode node, Rete engine, IWorkingMemory mem) { if (addNode(node)) { // first, we Get the memory for this node IGenericMap<Object, Object> leftmem = (IGenericMap<Object, Object>) mem.getBetaLeftMemory(this); // now we iterate over the entry set IEnumerator itr = leftmem.Values.GetEnumerator(); while (itr.MoveNext()) { Object omem = itr.Current; if (omem is IBetaMemory) { IBetaMemory bmem = (IBetaMemory) omem; // iterate over the matches if (bmem.matchCount() == 0) { node.assertFacts(bmem.Index, engine, mem); } } } } }
/// <summary> /// it's unlikely 2 rules are identical, except for the name. The implementation /// gets the current memory and propogates, but I wonder how much sense this /// makes in a real production environment. An user really shouldn't be deploying /// identical rules with different rule name. /// </summary> /// <param name="node">The node.</param> /// <param name="engine">The engine.</param> /// <param name="mem">The mem.</param> public virtual void addSuccessorNode(TerminalNode node, Rete engine, IWorkingMemory mem) { if (addNode(node)) { // first, we Get the memory for this node IGenericMap<Object, Object> leftmem = (IGenericMap<Object, Object>) mem.getBetaLeftMemory(this); // now we iterate over the entry set IEnumerator itr = leftmem.Values.GetEnumerator(); while (itr.MoveNext()) { Object omem = itr.Current; if (omem is IBetaMemory) { IBetaMemory bmem = (IBetaMemory) omem; Index left = bmem.Index; // iterate over the matches IGenericMap<Object, Object> rightmem = (IGenericMap<Object, Object>) mem.getBetaRightMemory(this); IEnumerator ritr = rightmem.Keys.GetEnumerator(); while (ritr.MoveNext()) { IFact rfcts = (IFact) ritr.Current; // merge the left and right fact into a new Array node.assertFacts(left.add(rfcts), engine, mem); } } } } }