/// <summary> Assert from the right side is always going to be from an /// Alpha node. /// </summary> /// <param name="">factInstance /// </param> /// <param name="">engine /// /// </param> public override void assertRight(IFact rfact, Rete engine, IWorkingMemory mem) { // we only proceed if the fact hasn't already entered // the join node Index linx = new Index(new IFact[0]); IGenericMap <Object, Object> rightmem = (IGenericMap <Object, Object>)mem.getBetaRightMemory(this); rightmem.Put(rfact, rfact); // now that we've added the facts to the list, we // proceed with evaluating the fact IGenericMap <Object, Object> leftmem = (IGenericMap <Object, Object>)mem.getBetaLeftMemory(this); IEnumerator itr = leftmem.Values.GetEnumerator(); while (itr.MoveNext()) { IBetaMemory bmem = (IBetaMemory)itr.Current; int prevCount = bmem.matchCount(); if (evaluate(linx.Facts, rfact, engine)) { bmem.addMatch(rfact); } // When facts are asserted from the right, it can only // increase the match count, so basically it will never // need to propogate to successor nodes. if (prevCount == 0 && bmem.matchCount() != 0) { linx = new Index(new IFact[0]); // we have to retract try { propogateRetract(linx, engine, mem); } catch (RetractException e) { throw new AssertException("NotJion - " + e.Message); } } } }
/// <summary> Retract from the right works in the following order. /// 1. Remove the fact from the right memory /// 2. check which left memory matched /// 3. propogate the retract /// </summary> /// <param name="">factInstance /// </param> /// <param name="">engine /// /// </param> public override void retractRight(IFact rfact, Rete engine, IWorkingMemory mem) { Index linx = new Index(new IFact[0]); IGenericMap <Object, Object> rightmem = (IGenericMap <Object, Object>)mem.getBetaRightMemory(this); if (rightmem.RemoveWithReturn(rfact) != null) { // now we see the left memory matched and Remove it also IGenericMap <Object, Object> leftmem = (IGenericMap <Object, Object>)mem.getBetaLeftMemory(this); IEnumerator itr = leftmem.Values.GetEnumerator(); while (itr.MoveNext()) { IBetaMemory bmem = (IBetaMemory)itr.Current; int prevCount = bmem.matchCount(); if (bmem.matched(rfact)) { // we Remove the fact from the memory bmem.removeMatch(rfact); // since 1 or more matches prevents propogation // we don't need to propogate retract. if the // match count is now zero, we need to propogate // assert if (prevCount != 0 && bmem.matchCount() == 0) { try { propogateAssert(bmem.Index, engine, mem); } catch (AssertException e) { throw new RetractException("NotJion - " + e.Message); } } } } } }
/// <summary> Retract from the right works in the following order. /// 1. Remove the fact from the right memory /// 2. check which left memory matched /// 3. propogate the retract /// </summary> /// <param name="">factInstance /// </param> /// <param name="">engine /// /// </param> public override void retractRight(IFact rfact, Rete engine, IWorkingMemory mem) { IGenericMap <Object, Object> rightmem = (IGenericMap <Object, Object>)mem.getBetaRightMemory(this); rightmem.Remove(rfact); IGenericMap <Object, Object> leftmem = (IGenericMap <Object, Object>)mem.getBetaLeftMemory(this); IEnumerator itr = leftmem.Values.GetEnumerator(); while (itr.MoveNext()) { IBetaMemory bmem = (IBetaMemory)itr.Current; if (evaluate(bmem.LeftFacts, rfact, engine)) { bmem.removeMatch(rfact); if (bmem.matchCount() == 0) { propogateRetract(bmem.Index, engine, mem); } } } }
/// <summary> Assert from the right side is always going to be from an /// Alpha node. /// </summary> /// <param name="">factInstance /// </param> /// <param name="">engine /// /// </param> public override void assertRight(IFact rfact, Rete engine, IWorkingMemory mem) { IGenericMap <Object, Object> rightmem = (IGenericMap <Object, Object>)mem.getBetaRightMemory(this); rightmem.Put(rfact, rfact); IGenericMap <Object, Object> leftmem = (IGenericMap <Object, Object>)mem.getBetaLeftMemory(this); IEnumerator itr = leftmem.Values.GetEnumerator(); while (itr.MoveNext()) { IBetaMemory bmem = (IBetaMemory)itr.Current; if (evaluate(bmem.LeftFacts, rfact, engine)) { // now we propogate bmem.addMatch(rfact); if (bmem.matchCount() == 1) { propogateAssert(bmem.Index.add(rfact), 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); } } } } }
public void testPropogateNoMatch() { Console.WriteLine("testPropogateNoMatch"); // first create a rule engine instance Rete engine = new Rete(); NotJoin nj = new NotJoin(engine.nextNodeId()); HashedEqBNode bn2 = new HashedEqBNode(engine.nextNodeId()); Assert.IsNotNull(nj); // create a defclass Defclass dc = new Defclass(typeof(TestBean2)); // create deftemplate Deftemplate dtemp = dc.createDeftemplate("testBean2"); Assert.IsNotNull(dtemp); Binding[] binds = new Binding[1]; Binding b1 = new Binding(); b1.LeftIndex = (0); b1.IsObjectVar = (false); b1.LeftRow = (0); b1.RightIndex = (0); b1.VarName = ("var1"); binds[0] = b1; Binding[] binds2 = new Binding[1]; Binding b2 = new Binding(); b2.LeftIndex = (1); b2.IsObjectVar = (false); b2.LeftRow = (0); b2.RightIndex = (1); b2.VarName = ("var2"); binds2[0] = b2; // set the binding nj.Bindings = (binds); bn2.Bindings = (binds2); // now add the second Not to the first try { nj.addSuccessorNode(bn2, engine, engine.WorkingMemory); } catch (AssertException e) { Console.WriteLine(e.Message); } int count = 10; ArrayList data = new ArrayList(); for (int idx = 0; idx < count; idx++) { TestBean2 bean = new TestBean2(); bean.Attr1 = ("random" + idx); bean.Attr2 = (101 + idx); short s = 10001; bean.Attr3 = (s); long l = 10101018 + idx; bean.Attr4 = (l); bean.Attr5 = (1010101); bean.Attr6 = (1001.1001); IFact fact = dtemp.createFact(bean, dc, engine.nextFactId()); data.Add(fact); } IEnumerator itr = data.GetEnumerator(); while (itr.MoveNext()) { try { IFact f1 = (IFact)itr.Current; nj.assertLeft(new Index(new IFact[] { f1 }), engine, engine.WorkingMemory); nj.assertRight(f1, engine, engine.WorkingMemory); } catch (AssertException e) { Console.WriteLine(e.Message); } } IGenericMap <IFact, IFact> rbmem = (IGenericMap <IFact, IFact>)engine.WorkingMemory.getBetaRightMemory(nj); Assert.AreEqual(count, rbmem.Count); IGenericMap <Object, Object> lbmem = (IGenericMap <Object, Object>)engine.WorkingMemory.getBetaLeftMemory(nj); Assert.AreEqual(count, lbmem.Count); // now check the BetaMemory has matches Console.WriteLine(nj.toPPString()); IEnumerator mitr = lbmem.Values.GetEnumerator(); while (mitr.MoveNext()) { IBetaMemory btm = (IBetaMemory)mitr.Current; Assert.AreEqual(0, btm.matchCount()); Console.WriteLine("match count=" + btm.matchCount() + " - " + btm.toPPString()); } IGenericMap <Object, Object> lbmem2 = (IGenericMap <Object, Object>)engine.WorkingMemory.getBetaLeftMemory(bn2); Assert.AreEqual(count, lbmem2.Count); Console.WriteLine(bn2.toPPString()); IEnumerator mitr2 = lbmem2.Values.GetEnumerator(); engine.close(); // TODO need to update the test to check the match count // by getting the right memory }
public void testMatch() { // first create a rule engine instance Rete engine = new Rete(); NotJoin bn = new NotJoin(engine.nextNodeId()); Assert.IsNotNull(bn); // create a defclass Defclass dc = new Defclass(typeof(TestBean2)); // create deftemplate Deftemplate dtemp = dc.createDeftemplate("testBean2"); Assert.IsNotNull(dtemp); Binding[] binds = new Binding[1]; Binding b1 = new Binding(); b1.LeftIndex = (0); b1.IsObjectVar = (false); b1.LeftRow = (0); b1.RightIndex = (0); b1.VarName = ("var1"); binds[0] = b1; // set the binding bn.Bindings = (binds); int count = 10; ArrayList data = new ArrayList(); for (int idx = 0; idx < count; idx++) { TestBean2 bean = new TestBean2(); bean.Attr1 = ("random"); bean.Attr2 = (101); short s = 10001; bean.Attr3 = (s); long l = 10101018; bean.Attr4 = (l); bean.Attr5 = (1010101); bean.Attr6 = (1001.1001); IFact fact = dtemp.createFact(bean, dc, engine.nextFactId()); data.Add(fact); } IEnumerator itr = data.GetEnumerator(); while (itr.MoveNext()) { try { IFact f1 = (IFact)itr.Current; bn.assertLeft(new Index(new IFact[] { f1 }), engine, engine.WorkingMemory); bn.assertRight(f1, engine, engine.WorkingMemory); } catch (AssertException e) { Console.WriteLine(e.Message); } } IGenericMap <IFact, IFact> rbmem = (IGenericMap <IFact, IFact>)engine.WorkingMemory.getBetaRightMemory(bn); Assert.AreEqual(count, rbmem.Count); IGenericMap <Object, Object> lbmem = (IGenericMap <Object, Object>)engine.WorkingMemory.getBetaLeftMemory(bn); Assert.AreEqual(count, lbmem.Count); // now check the BetaMemory has matches Console.WriteLine(bn.toPPString()); IEnumerator mitr = lbmem.Values.GetEnumerator(); while (mitr.MoveNext()) { IBetaMemory btm = (IBetaMemory)mitr.Current; Assert.AreEqual(9, btm.matchCount()); Console.WriteLine("match count=" + btm.matchCount() + " - " + btm.toPPString()); } engine.close(); }