/// <summary> Clear will Clear the lists /// </summary> public override void clear(IWorkingMemory mem) { IGenericMap <Object, Object> leftmem = mem.getBetaLeftMemory(this); IGenericMap <Object, Object> rightmem = (IGenericMap <Object, Object>)mem.getBetaRightMemory(this); // first we iterate over the list for each fact // and Clear it. foreach (object item in leftmem.Keys) { ((IBetaMemory)leftmem.Get(item)).clear(); } /* * IEnumerator itr = leftmem.Keys.GetEnumerator(); * // first we iterate over the list for each fact * // and Clear it. * while (itr.MoveNext()) * { * IBetaMemory bmem = (IBetaMemory) leftmem.Get(itr.Current); * bmem.clear(); * } */ // now that we've cleared the list for each fact, we // can Clear the Creshendo.rete.util.Map. leftmem.Clear(); rightmem.Clear(); }
/// <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> /// assertLeft takes an array of facts. Since the Current join may be /// joining against one or more objects, we need to pass all /// previously matched facts. /// </summary> /// <param name="linx">The linx.</param> /// <param name="engine">The engine.</param> /// <param name="mem">The mem.</param> public override void assertLeft(Index linx, Rete engine, IWorkingMemory mem) { IGenericMap <Object, Object> leftmem = mem.getBetaLeftMemory(this); leftmem.Put(linx, linx); //foreach(IFact rfcts in ((IGenericMap<IFact, IFact>)mem.getBetaRightMemory(this)).Values) //{ // propogateAssert(linx.add(rfcts), engine, mem); //} IGenericMap <IFact, IFact> rightmem = (IGenericMap <IFact, IFact>)mem.getBetaRightMemory(this); foreach (IFact rfcts in rightmem.Values) { propogateAssert(linx.add(rfcts), engine, mem); } //IEnumerator itr = rightmem.Values.GetEnumerator(); //while (itr.MoveNext()) //{ // IFact rfcts = (IFact)itr.Current; // // now we propogate // propogateAssert(linx.add(rfcts), 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> the implementation just propogates the assert down the network /// </summary> public override void assertFact(IFact fact, Rete engine, IWorkingMemory mem) { IAlphaMemory alpha = (IAlphaMemory)mem.getAlphaMemory(this); alpha.addPartialMatch(fact); propogateAssert(fact, engine, mem); }
public override void assertRight(IFact rfact, Rete engine, IWorkingMemory mem) { long time = LeftTime; TemporalHashedAlphaMem rightmem = (TemporalHashedAlphaMem) mem.getBetaRightMemory(this); EqHashIndex inx = new EqHashIndex(NodeUtils.getRightValues(binds, rfact)); rightmem.addPartialMatch(inx, 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); // since there may be key collisions, we iterate over the // values of the HashMap. If we used keySet to iterate, // we could encounter a ClassCastException in the case of // key collision. IEnumerator itr = leftmem.Values.GetEnumerator(); try { while (itr.MoveNext()) { Index linx = (Index) itr.Current; if (evaluate(linx.Facts, rfact, time)) { // now we propogate propogateAssert(linx.add(rfact), engine, mem); } else { propogateRetract(linx.add(rfact), engine, mem); } } } catch (RetractException e) { // we shouldn't Get a retract exception. if we do, it's a bug } }
/// <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) { // Get the memory for the node HashedNeqAlphaMemory rightmem = (HashedNeqAlphaMemory) mem.getBetaRightMemory(this); NotEqHashIndex inx = new NotEqHashIndex(NodeUtils.getRightBindValues(binds, rfact)); rightmem.addPartialMatch(inx, rfact); bool zm = rightmem.zeroMatch(inx); IGenericMap<Object, Object> leftmem = (IGenericMap<Object, Object>) mem.getBetaLeftMemory(this); IEnumerator itr = leftmem.Values.GetEnumerator(); while (itr.MoveNext()) { Index linx = (Index) itr.Current; if (evaluate(linx.Facts, rfact)) { if (!zm) { try { propogateRetract(linx, engine, mem); } catch (RetractException e) { throw new AssertException("NotJion - " + e.Message); } } } } }
/// <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> Remove a successor node /// </summary> /// <param name="">node /// </param> /// <param name="">engine /// </param> /// <param name="">mem /// @throws AssertException /// /// </param> public virtual void removeSuccessorNode(BaseNode node, Rete engine, IWorkingMemory mem) { if (removeNode(node)) { // we retract the memories first, before removing the node 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.retractFact((IFact)itr.Current, engine, mem); } else if (node is BaseJoin) { BaseJoin next = (BaseJoin)node; next.retractRight((IFact)itr.Current, 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; Index inx = new Index(new IFact[] {(IFact) itr.Current}); next.assertLeft(inx, engine, mem); } } } } }
/// <summary> Retracting from the left is different than retractRight for couple /// of reasons. /// <ul> /// <li> NotJoin will only propogate the facts from the left</li> /// <li> NotJoin never needs to merge the left and right</li> /// </ul> /// </summary> /// <param name="">factInstance /// </param> /// <param name="">engine /// /// </param> public override void retractLeft(Index linx, Rete engine, IWorkingMemory mem) { IGenericMap <Object, Object> leftmem = (IGenericMap <Object, Object>)mem.getBetaLeftMemory(this); leftmem.Remove(linx); propogateRetract(linx, engine, mem); }
public ExecutionContext(ISessionInternal session, IWorkingMemory workingMemory, IAgendaInternal agenda, IEventAggregator eventAggregator) { Session = session; WorkingMemory = workingMemory; Agenda = agenda; EventAggregator = eventAggregator; }
/// <summary> if all the facts have not expired, the method returns true. If a fact has /// expired, the method will retract the fact. /// </summary> /// <param name="">inx /// </param> /// <param name="">engine /// </param> /// <param name="">mem /// </param> /// <returns> /// /// </returns> protected internal virtual bool checkFacts(Index inx, Rete engine, IWorkingMemory mem) { IFact[] facts = inx.Facts; bool fresh = true; long current = (DateTime.Now.Ticks - 621355968000000000) / 10000; for (int idx = 0; idx < facts.Length; idx++) { if (facts[idx] is ITemporalFact) { TemporalDeffact tf = (TemporalDeffact)facts[idx]; if (tf.ExpirationTime < current) { // the fact has expired fresh = false; try { engine.retractFact(tf); } catch (RetractException e) { // we do nothing } } } } return(fresh); }
public ExecutionContext(ISession session, IWorkingMemory workingMemory, IAgenda agenda, IEventAggregator eventAggregator) { Session = session; WorkingMemory = workingMemory; Agenda = agenda; EventAggregator = eventAggregator; }
/// <summary> /// method for propogating the retract /// </summary> /// <param name="inx">The inx.</param> /// <param name="engine">The engine.</param> /// <param name="mem">The mem.</param> protected internal virtual void propogateRetract(Index inx, Rete engine, IWorkingMemory mem) { for (int idx = 0; idx < successorNodes.Length; idx++) { BaseJoin node = successorNodes[idx] as BaseJoin; if (node != null) { node.retractLeft(inx, engine, mem); } else { TerminalNode tnode = successorNodes[idx] as TerminalNode; if (tnode != null) { tnode.retractFacts(inx, engine, mem); } } //BaseNode node = successorNodes[idx]; //if (node is BaseJoin) //{ // ((BaseJoin) node).retractLeft(inx, engine, mem); //} //else if (node is TerminalNode) //{ // ((TerminalNode) node).retractFacts(inx, 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) { // Get the memory for the node HashedNeqAlphaMemory rightmem = (HashedNeqAlphaMemory)mem.getBetaRightMemory(this); NotEqHashIndex inx = new NotEqHashIndex(NodeUtils.getRightBindValues(binds, rfact)); rightmem.addPartialMatch(inx, rfact); bool zm = rightmem.zeroMatch(inx); IGenericMap <Object, Object> leftmem = (IGenericMap <Object, Object>)mem.getBetaLeftMemory(this); IEnumerator itr = leftmem.Values.GetEnumerator(); while (itr.MoveNext()) { Index linx = (Index)itr.Current; if (evaluate(linx.Facts, rfact)) { if (!zm) { 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) { NotEqHashIndex inx = new NotEqHashIndex(NodeUtils.getRightBindValues(binds, rfact)); HashedNeqAlphaMemory rightmem = (HashedNeqAlphaMemory)mem.getBetaRightMemory(this); // first we Remove the fact from the right rightmem.removePartialMatch(inx, rfact); bool zm = rightmem.zeroMatch(inx); // 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()) { Index linx = (Index)itr.Current; if (evaluate(linx.Facts, rfact)) { if (zm) { try { propogateAssert(linx, engine, mem); } catch (AssertException e) { throw new RetractException("NotJion - " + e.Message); } } } } }
/// <summary> Retract a fact from the node /// </summary> /// <param name="">factInstance /// </param> /// <param name="">engine /// /// </param> public override void retractFact(IFact fact, Rete engine, IWorkingMemory mem) { if (evaluate(fact)) { propogateRetract(fact, engine, mem); } }
public override void assertLeft(Index linx, Rete engine, IWorkingMemory mem) { long time = RightTime; IGenericMap<Object, Object> leftmem = (IGenericMap<Object, Object>) mem.getBetaLeftMemory(this); leftmem.Put(linx, linx); EqHashIndex inx = new EqHashIndex(NodeUtils.getLeftValues(binds, linx.Facts)); TemporalHashedAlphaMem rightmem = (TemporalHashedAlphaMem) mem.getBetaRightMemory(this); IEnumerator itr = rightmem.iterator(inx); if (itr != null) { try { while (itr.MoveNext()) { IFact vl = (IFact) itr.Current; if (vl != null) { if (vl.timeStamp() > time) { propogateAssert(linx.add(vl), engine, mem); } else { rightmem.removePartialMatch(inx, vl); propogateRetract(linx.add(vl), engine, mem); } } } } catch (RetractException e) { // there shouldn't be any retract exceptions } } }
/// <summary> /// assertLeft takes an array of facts. Since the Current join may be /// joining against one or more objects, we need to pass all /// previously matched facts. /// </summary> /// <param name="linx">The linx.</param> /// <param name="engine">The engine.</param> /// <param name="mem">The mem.</param> public override void assertLeft(Index linx, Rete engine, IWorkingMemory mem) { IGenericMap <Object, Object> leftmem = (IGenericMap <Object, Object>)mem.getBetaLeftMemory(this); // we create a new list for storing the matches. // any fact that isn't in the list will be evaluated. IBetaMemory bmem = new BetaMemoryImpl(linx); leftmem.Put(bmem.Index, bmem); IGenericMap <IFact, IFact> rightmem = (IGenericMap <IFact, IFact>)mem.getBetaRightMemory(this); int prevCount = bmem.matchCount(); IEnumerator itr = rightmem.Values.GetEnumerator(); while (itr.MoveNext()) { IFact rfcts = (IFact)itr.Current; if (evaluate(linx.Facts, rfcts, engine)) { // it matched, so we Add it to the beta memory bmem.addMatch(rfcts); } } // since the Fact[] is entering the left for the first time, // if there are no matches, we merged the facts propogate. if (bmem.matchCount() == 0) { propogateAssert(linx, engine, mem); } }
public Session( IWorkingMemory workingMemory, IDateWriterService dateWriter) { _workingMemory = workingMemory; _dateWriter = dateWriter; }
/// <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> assertLeft takes an array of facts. Since the Current join may be /// joining against one or more objects, we need to pass all /// previously matched facts. /// </summary> /// <param name="">factInstance /// </param> /// <param name="">engine /// /// </param> public override void assertLeft(Index linx, Rete engine, IWorkingMemory mem) { IGenericMap <Object, Object> leftmem = (IGenericMap <Object, Object>)mem.getBetaLeftMemory(this); IBetaMemory bmem = new BetaMemoryImpl(linx); leftmem.Put(linx, bmem); IGenericMap <Object, Object> rightmem = (IGenericMap <Object, Object>)mem.getBetaRightMemory(this); IEnumerator itr = rightmem.Keys.GetEnumerator(); if (itr != null) { while (itr.MoveNext()) { IFact vl = (IFact)itr.Current; // we have to evaluate the function if (vl != null && evaluate(linx.Facts, vl, engine)) { bmem.addMatch(vl); } } } if (bmem.matchCount() > 0) { propogateAssert(linx, 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) { // Get the memory for the node HashedNeqAlphaMemory rightmem = (HashedNeqAlphaMemory)mem.getBetaRightMemory(this); NotEqHashIndex inx = new NotEqHashIndex(NodeUtils.getRightBindValues(binds, rfact)); rightmem.addPartialMatch(inx, rfact); // now that we've added the facts to the list, we // proceed with evaluating the fact // else we compare the fact to all facts in the left IGenericMap <Object, Object> leftmem = (IGenericMap <Object, Object>)mem.getBetaLeftMemory(this); // since there may be key collisions, we iterate over the // values of the HashMap. If we used keySet to iterate, // we could encounter a ClassCastException in the case of // key collision. IEnumerator itr = leftmem.Values.GetEnumerator(); while (itr.MoveNext()) { Index linx = (Index)itr.Current; if (evaluate(linx.Facts, rfact)) { // now we propogate propogateAssert(linx.add(rfact), 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> /// </summary> /// <param name="inx"></param> /// <param name="engine"></param> /// <param name="mem"></param> public override void assertFacts(Index inx, Rete engine, IWorkingMemory mem) { LinkedActivation act = new LinkedActivation(theRule, inx); act.TerminalNode = this; // fire the activation immediately engine.fireActivation(act); }
/// <summary> Retract simply propogates it down the network /// </summary> public override void retractFact(IFact fact, Rete engine, IWorkingMemory mem) { IAlphaMemory alpha = (IAlphaMemory) mem.getAlphaMemory(this); if (alpha.removePartialMatch(fact) != null) { propogateRetract(fact, engine, mem); } }
public ExecutionContext(ISessionInternal session, IWorkingMemory workingMemory, IAgendaInternal agenda, IEventAggregator eventAggregator, IIdGenerator idGenerator) { Session = session; WorkingMemory = workingMemory; Agenda = agenda; EventAggregator = eventAggregator; IdGenerator = idGenerator; UnlinkQueue = new Queue <Activation>(); }
/// <summary> /// Subclasses need to implement Clear and make sure all /// memories are cleared properly. /// </summary> /// <param name="mem">The mem.</param> public virtual void clear(IWorkingMemory mem) { IGenericMap <Object, Object> leftmem = (IGenericMap <Object, Object>)mem.getBetaLeftMemory(this); leftmem.Clear(); HashedAlphaMemoryImpl rightmem = (HashedAlphaMemoryImpl)mem.getBetaRightMemory(this); rightmem.clear(); }
/// <summary> Retract simply propogates it down the network /// </summary> public override void retractFact(IFact fact, Rete engine, IWorkingMemory mem) { IAlphaMemory alpha = (IAlphaMemory)mem.getAlphaMemory(this); if (alpha.removePartialMatch(fact) != null) { propogateRetract(fact, engine, mem); } }
/// <summary> /// </summary> /// <param name="">factInstance /// </param> /// <param name="">engine /// /// </param> public override void assertFact(IFact fact, Rete engine, IWorkingMemory mem) { if (evaluate(fact)) { // if watch is on, we notify the engine. Rather than // create an event class here, we let Rete do that. propogateAssert(fact, engine, mem); } }
internal Session(INetwork network, IAgenda agenda, IWorkingMemory workingMemory, IEventAggregator eventAggregator) { _network = network; _workingMemory = workingMemory; _agenda = agenda; _eventAggregator = eventAggregator; _executionContext = new ExecutionContext(this, _workingMemory, _agenda, _eventAggregator); _network.Activate(_executionContext); }
/// <summary> /// The terminal nodes doesn't have a memory, so the method /// does nothing. /// </summary> /// <param name="mem"></param> public override void clear(IWorkingMemory mem) { IGenericMap <Object, Object> tmem = (IGenericMap <Object, Object>)mem.getTerminalMemory(this); if (tmem != null) { tmem.Clear(); } }
public Session(AuthorityContext authorityContext, INetwork network, ILoggerFactory loggerFactory) { _authorityContext = authorityContext; _network = network; _factIndex = new FactIndex(); _workingMemory = new WorkingMemory(loggerFactory); _stopwatch = Stopwatch.StartNew(); }
/// <summary> /// Instantiates a new Inference Engine with the specified threading model, using a business objects binder for asserting facts and evaluating functions. /// </summary> /// <param name="businessObjectsBinder">The business object binder that the engine must use.</param> /// <param name="threadingModelType">The threading model type that the engine must support.</param> public IEImpl(IBinder businessObjectsBinder, ThreadingModelTypes threadingModelType) { initialized = false; // instantiate a new working memory wm = WorkingMemoryFactory.NewWorkingMemory(threadingModelType); // set the binder Binder = businessObjectsBinder; }
/// <summary> /// Retracts the facts. /// </summary> /// <param name="inx">The inx.</param> /// <param name="engine">The engine.</param> /// <param name="mem">The mem.</param> public override void retractFacts(Index inx, Rete engine, IWorkingMemory mem) { IGenericMap <Object, Object> tmem = (IGenericMap <Object, Object>)mem.getTerminalMemory(this); LinkedActivation act = (LinkedActivation)tmem.RemoveWithReturn(inx); if (act != null) { engine.Agenda.removeActivation(act); } }
/// <param name="">facts /// </param> /// <param name="">engine /// /// </param> public override void assertFacts(Index inx, Rete engine, IWorkingMemory mem) { long time = (DateTime.Now.Ticks - 621355968000000000)/10000; if (theRule.ExpirationDate > 0 && time > theRule.EffectiveDate && time < theRule.ExpirationDate) { LinkedActivation act = new LinkedActivation(theRule, inx); act.TerminalNode = this; // fire the activation immediately engine.fireActivation(act); } }
/// <summary> /// Adds the successor node. /// </summary> /// <param name="node">The node.</param> /// <param name="engine">The engine.</param> /// <param name="mem">The mem.</param> public override void addSuccessorNode(BaseNode node, Rete engine, IWorkingMemory mem) { if (node is BaseJoin) { addSuccessorNode((BaseJoin) node, engine, mem); } else { addSuccessorNode((TerminalNode) node, engine, mem); } }
/// <summary> The implementation checks to see if the rule is active before it tries to /// assert the fact. It checks in the following order. /// 1. is the expiration date greater than zero /// 2. is the current time > the effective date /// 3. is the current time the expiration date /// </summary> /// <param name="">facts /// </param> /// <param name="">engine /// /// </param> public override void assertFacts(Index inx, Rete engine, IWorkingMemory mem) { long time = (DateTime.Now.Ticks - 621355968000000000)/10000; if (theRule.ExpirationDate > 0 && time > theRule.EffectiveDate && time < theRule.ExpirationDate) { LinkedActivation act = new LinkedActivation(theRule, inx); act.TerminalNode = this; IGenericMap<Object, Object> tmem = (IGenericMap<Object, Object>) mem.getTerminalMemory(this); tmem.Put(act.Index, act); // Add the activation to the current module's activation list. engine.Agenda.addActivation(act); } }
/// <summary> assertLeft takes an array of facts. Since the Current join may be /// joining against one or more objects, we need to pass all /// previously matched facts. /// </summary> /// <param name="">factInstance /// </param> /// <param name="">engine /// /// </param> public override void assertLeft(Index linx, Rete engine, IWorkingMemory mem) { IGenericMap<Object, Object> leftmem = (IGenericMap<Object, Object>) mem.getBetaLeftMemory(this); leftmem.Put(linx, linx); NotEqHashIndex inx = new NotEqHashIndex(NodeUtils.getLeftBindValues(binds, linx.Facts)); HashedNeqAlphaMemory rightmem = (HashedNeqAlphaMemory) mem.getBetaRightMemory(this); Object[] objs = rightmem.iterator(inx); // if the right side has 1 or more matches, we propogate the original // index down the network. We don't Add any facts to the index if (objs != null && objs.Length > 0) { propogateAssert(linx, engine, mem); } }
/// <summary> assertLeft takes an array of facts. Since the Current join may be /// joining against one or more objects, we need to pass all /// previously matched facts. /// </summary> /// <param name="">factInstance /// </param> /// <param name="">engine /// /// </param> public override void assertLeft(Index linx, Rete engine, IWorkingMemory mem) { IGenericMap<Object, Object> leftmem = (IGenericMap<Object, Object>) mem.getBetaLeftMemory(this); leftmem.Put(linx, linx); // need to think the getLeftValues through better to // account for cases when a join has no bindings NotEqHashIndex inx = new NotEqHashIndex(NodeUtils.getLeftBindValues(binds, linx.Facts)); HashedNeqAlphaMemory rightmem = (HashedNeqAlphaMemory) mem.getBetaRightMemory(this); if (rightmem.zeroMatch(inx)) { propogateAssert(linx, engine, mem); } }
/// <summary> assertLeft takes an array of facts. Since the Current join may be /// joining against one or more objects, we need to pass all /// previously matched facts. /// </summary> /// <param name="">factInstance /// </param> /// <param name="">engine /// /// </param> public override void assertLeft(Index linx, Rete engine, IWorkingMemory mem) { IGenericMap<Object, Object> leftmem = (IGenericMap<Object, Object>) mem.getBetaLeftMemory(this); leftmem.Put(linx, linx); // need to think the getLeftValues through better to // account for cases when a join has no bindings NotEqHashIndex inx = new NotEqHashIndex(NodeUtils.getLeftBindValues(binds, linx.Facts)); HashedNeqAlphaMemory rightmem = (HashedNeqAlphaMemory) mem.getBetaRightMemory(this); Object[] objs = rightmem.iterator(inx); if (objs != null && objs.Length > 0) { for (int idx = 0; idx < objs.Length; idx++) { IFact rfcts = (IFact) objs[idx]; // now we propogate propogateAssert(linx.add(rfcts), engine, mem); } } }
/// <summary> Method will call checkFacts() first to make sure none of the facts have /// expired. An activation is only created if the facts are valid. /// </summary> /// <param name="">facts /// </param> /// <param name="">engine /// /// </param> public override void assertFacts(Index inx, Rete engine, IWorkingMemory mem) { // first check the facts and make sure they didn't expire if (checkFacts(inx, engine, mem)) { LinkedActivation act = new LinkedActivation(theRule, inx); act.TerminalNode = this; if (temporal) { engine.fireActivation(act); } else { IGenericMap<Object, Object> tmem = (IGenericMap<Object, Object>) mem.getTerminalMemory(this); tmem.Put(inx, act); // Add the activation to the current module's activation list. engine.Agenda.addActivation(act); } } }
/// <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) { HashedNeqAlphaMemory rightmem = (HashedNeqAlphaMemory) mem.getBetaRightMemory(this); NotEqHashIndex inx = new NotEqHashIndex(NodeUtils.getRightBindValues(binds, rfact)); rightmem.addPartialMatch(inx, rfact); IGenericMap<Object, Object> leftmem = (IGenericMap<Object, Object>) mem.getBetaLeftMemory(this); IEnumerator itr = leftmem.Values.GetEnumerator(); int after = rightmem.count(inx); while (itr.MoveNext()) { Index linx = (Index) itr.Current; if (evaluate(linx.Facts, rfact)) { if (after == 1) { propogateAssert(linx, engine, mem); } } } }
/// <summary> assertLeft takes an array of facts. Since the Current join may be joining /// against one or more objects, we need to pass all previously matched /// facts. /// /// </summary> /// <param name="">factInstance /// </param> /// <param name="">engine /// /// </param> public override void assertLeft(Index linx, Rete engine, IWorkingMemory mem) { IGenericMap<Object, Object> leftmem = (IGenericMap<Object, Object>) mem.getBetaLeftMemory(this); IBetaMemory bmem = new BetaMemoryImpl(linx); leftmem.Put(linx, bmem); IGenericMap<Object, Object> rightmem = (IGenericMap<Object, Object>) mem.getBetaRightMemory(this); IEnumerator itr = rightmem.Keys.GetEnumerator(); if (itr != null) { while (itr.MoveNext()) { IFact vl = (IFact) itr.Current; // we have to evaluate the function if (vl != null && evaluate(linx.Facts, vl, engine)) { bmem.addMatch(vl); propogateAssert(linx.add(vl), 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> 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> retract right is a dummy, so it does nothing. /// </summary> public override void retractRight(IFact rfact, Rete engine, IWorkingMemory mem) { }
/// <summary> /// </summary> public override void retractLeft(Index linx, Rete engine, IWorkingMemory mem) { IGenericMap<Object, Object> leftmem = (IGenericMap<Object, Object>) mem.getBetaLeftMemory(this); int prev = leftmem.Count; if (leftmem.ContainsKey(linx)) { // the memory Contains the key, so we retract and propogate leftmem.Remove(linx); } if (prev != 0 && leftmem.Count == 0) { propogateRetract(linx, engine, mem); } }
/// <summary> Clear the memory /// </summary> public override void clear(IWorkingMemory mem) { ((IGenericMap<Object, Object>) mem.getBetaLeftMemory(this)).Clear(); }
/// <summary> Assert will first pass the facts to the parameters. Once the /// parameters are set, it should call execute to Get the result. /// </summary> public override void assertLeft(Index linx, Rete engine, IWorkingMemory mem) { IGenericMap<Object, Object> leftmem = (IGenericMap<Object, Object>) mem.getBetaLeftMemory(this); if (!leftmem.ContainsKey(linx)) { Parameters = linx.Facts; IReturnVector rv = func.executeFunction(engine, params_Renamed); if (!rv.firstReturnValue().BooleanValue) { IBetaMemory bmem = new BetaMemoryImpl(linx); leftmem.Put(bmem.Index, bmem); } // only propogate if left memories count is zero if (leftmem.Count == 0) { propogateAssert(linx, 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 abstract override void assertRight(IFact rfact, Rete engine, IWorkingMemory mem);
/// <summary> Retracting from the left requires that we propogate the /// /// </summary> /// <param name="">factInstance /// </param> /// <param name="">engine /// /// </param> public abstract override void retractLeft(Index linx, Rete engine, IWorkingMemory mem);
/// <summary> Clear the memory. for now the method does not /// Remove all the successor nodes. need to think it over a bit. /// </summary> public override void clear(IWorkingMemory mem) { IAlphaMemory am = (IAlphaMemory) mem.getAlphaMemory(this); am.clear(); }
/// <summary> Retract the fact to the succeeding nodes. ObjectTypeNode does not call /// assertEvent, since it's not that important and doesn't really /// help debugging. /// </summary> /// <param name="">fact /// </param> /// <param name="">engine /// /// </param> public override void retractFact(IFact fact, Rete engine, IWorkingMemory mem) { if (fact.Deftemplate == deftemplate) { ((IAlphaMemory) mem.getAlphaMemory(this)).removePartialMatch(fact); for (int idx = 0; idx < successorNodes.Length; idx++) { Object node = successorNodes[idx]; if (node is BaseAlpha) { ((BaseAlpha) node).retractFact(fact, engine, mem); } else if (node is BaseJoin) { ((BaseJoin) node).retractRight(fact, engine, mem); } } IEnumerator itr2 = successor2.GetEnumerator(); while (itr2.MoveNext()) { BaseNode node = (BaseNode) itr2.Current; if (node is BaseAlpha) { ((BaseAlpha) node).retractFact(fact, engine, mem); } else if (node is BaseJoin) { ((BaseJoin) node).retractRight(fact, engine, mem); } else if (node is TerminalNode) { Index inx = new Index(new IFact[] {fact}); ((TerminalNode) node).retractFacts(inx, engine, mem); } } } }
public virtual void assertSecondSuccessors(IFact fact, Rete engine, IWorkingMemory mem) { IEnumerator itr = successor2.GetEnumerator(); while (itr.MoveNext()) { BaseNode node = (BaseNode) itr.Current; if (node is BaseAlpha) { ((BaseAlpha) node).assertFact(fact, engine, mem); } else if (node is BaseJoin) { ((BaseJoin) node).assertRight(fact, engine, mem); } else if (node is TerminalNode) { Index inx = new Index(new IFact[] {fact}); ((TerminalNode) node).assertFacts(inx, engine, mem); } } }
/// <summary> Propogate the fact using the normal way of iterating over the /// successors and calling assert on AlphaNodes and assertRight on /// BetaNodes. /// </summary> /// <param name="">fact /// </param> /// <param name="">engine /// </param> /// <param name="">mem /// @throws AssertException /// /// </param> public virtual void assertAllSuccessors(IFact fact, Rete engine, IWorkingMemory mem) { for (int idx = 0; idx < successorNodes.Length; idx++) { Object node = successorNodes[idx]; if (node is BaseAlpha) { ((BaseAlpha) node).assertFact(fact, engine, mem); } else if (node is BaseJoin) { ((BaseJoin) node).assertRight(fact, engine, mem); } else if (node is TerminalNode) { Index inx = new Index(new IFact[] {fact}); ((TerminalNode) node).assertFacts(inx, engine, mem); } } assertSecondSuccessors(fact, engine, mem); }
/// <summary> assert using HashMap approach /// /// </summary> /// <param name="">fact /// </param> /// <param name="">engine /// </param> /// <param name="">mem /// /// </param> public virtual void assertFactWithMap(IFact fact, Rete engine, IWorkingMemory mem) { Slot[] slots = fact.Deftemplate.AllSlots; // iterate over the slots for (int idx = 0; idx < slots.Length; idx++) { // only if the slot's node count is greater than zero // do we go ahead and lookup in the HashMap if (slots[idx].NodeCount > 0) { // iterate over the operators for (int ops = 0; ops < operators.Length; ops++) { CompositeIndex comIndex = new CompositeIndex(slots[idx].Name, operators[ops], fact.getSlotValue(idx)); Object node = entries.Get(comIndex); if (node != null) { if (node is BaseAlpha) { ((BaseAlpha) node).assertFact(fact, engine, mem); } else if (node is BaseJoin) { ((BaseJoin) node).assertRight(fact, engine, mem); } else if (node is TerminalNode) { Index inx = new Index(new IFact[] {fact}); ((TerminalNode) node).assertFacts(inx, engine, mem); } } } } } assertSecondSuccessors(fact, engine, mem); }
/// <summary> assert the fact and propogate. ObjectTypeNode does not call /// assertEvent, since it's not that important and doesn't really /// help debugging. /// </summary> /// <param name="">fact /// </param> /// <param name="">engine /// /// </param> public override void assertFact(IFact fact, Rete engine, IWorkingMemory mem) { // ObjectTypeNode doesn't bother checking the deftemplate. ((IAlphaMemory) mem.getAlphaMemory(this)).addPartialMatch(fact); // if the number of succesor nodes is less than (slot count * opCount) if (gauranteeUnique && fact.Deftemplate.AllSlots.Length > 0 && successorNodes.Length > (fact.Deftemplate.AllSlots.Length*operators.Length)) { assertFactWithMap(fact, engine, mem); } else { assertAllSuccessors(fact, engine, mem); } }