コード例 #1
0
ファイル: Rete.cs プロジェクト: KristenWegner/expergent
 /// <summary>
 /// Delete_alpha_memories the specified amem.
 /// </summary>
 /// <param name="amem">The amem.</param>
 private void delete_alpha_memory(AlphaMemory amem)
 {
     Console.WriteLine(amem);
     throw new Exception();
 }
コード例 #2
0
ファイル: Rete.cs プロジェクト: KristenWegner/expergent
        /// <summary>
        /// The function for creating new negative nodes is similar to the ones for creating beta memories
        /// and join nodes. However, one additional consideration is important with negative conditions,
        /// and also with conjunctive negations. Any time there is a variable &lt;v&gt; which is tested in a negative
        /// condition and bound in one or more other (positive) conditions, at least one of these positive
        /// conditions must come before the negative condition. Recall that when we add a production to
        /// the network, the network-construction routines are given a list of its conditions in some order. If
        /// all conditions are positive, any order will work. Negative conditions require the aforementioned
        /// constraint on the order, though, because negative nodes need to be able to access the appropriate
        /// variable bindings in tokens, and the tokens "seen" by negative nodes indicate only variable
        /// bindings from earlier conditions, i.e., conditions higher up in the network.
        /// </summary>
        /// <param name="parent">The parent.</param>
        /// <param name="am">The am.</param>
        /// <param name="tests">The tests.</param>
        /// <returns></returns>
        private ReteNode build_or_share_negative_node(ReteNode parent, AlphaMemory am, ICollection<TestAtJoinNode> tests)
        {
            foreach (ReteNode child in parent.Children)
            {
                if (child.Type == ReteNodeType.Negative)
                {
                    NegativeNode negativenodeChild = (NegativeNode) child;
                    if (negativenodeChild.AlphaMemory == am)
                    {
                        if (negativenodeChild.Tests.Count == 0 && tests.Count == 0)
                        {
                            return child;
                        }
                        else
                        {
                            //Need to compare tests...
                            throw new ApplicationException("Unhandled...");
                        }
                    }
                }
            }

            NegativeNode new_node = new NegativeNode();
            new_node.Type = ReteNodeType.Negative; // "negative";
            new_node.Parent = parent;

            parent.Children.AddToFront(new_node);

            foreach (TestAtJoinNode test in tests)
            {
                new_node.Tests.Add(test);
            }
            new_node.AlphaMemory = am;

            am.Successors.AddToFront(new_node);
            ++am.ReferenceCount;
            new_node.NearestAncestorWithSameAmem = find_nearest_ancestor_with_same_amem(parent, am);
            update_new_node_with_matches_from_above(new_node);

            // *** Right Unlinking ***
            if (new_node.Items.Count == 0)
            {
                am.Successors.Remove(new_node);
                new_node.IsRightUnlinked = true;
            }
            // *** End Right Unlinking ***

            return new_node;
        }
コード例 #3
0
ファイル: Rete.cs プロジェクト: KristenWegner/expergent
        /// <summary>
        /// The next helper function is similar, except it handles join nodes rather than beta memory
        /// nodes. The two additional arguments specify the alpha memory to which the join node must
        /// be attached and the variable binding consistency checks it must perform. Note that there is no
        /// need to call update-new-node-with-matches-from-above in this case, because a join node does not
        /// store any tokens, and a newly created join node has no children onto which join results should
        /// be passed.
        /// </summary>
        /// <param name="parent">The parent.</param>
        /// <param name="am">The am.</param>
        /// <param name="tests">The tests.</param>
        /// <returns></returns>
        private ReteNode build_or_share_join_node(BetaMemory parent, AlphaMemory am, ICollection<TestAtJoinNode> tests)
        {
            foreach (ReteNode child in parent.AllChildren)
            {
                if (child.Type == ReteNodeType.Join)
                {
                    JoinNode childJoinNode = (JoinNode) child;
                    if (childJoinNode.AlphaMemory == am)
                    {
                        if (childJoinNode.Tests.Count == 0 && tests.Count == 0)
                        {
                            return child;
                        }
                        else
                        {
                            if (childJoinNode.Tests.Count == tests.Count)
                            {
                                bool testsMatch = true;
                                foreach (TestAtJoinNode test in tests)
                                {
                                    if (childJoinNode.Tests.Contains(test) == false)
                                    {
                                        testsMatch = false;
                                        continue;
                                    }
                                }
                                if (testsMatch)
                                {
                                    return child;
                                }
            //Need to compare tests...
                                throw new ApplicationException("Unhandled...");
                            }
                        }
                    }
                }
            }

            JoinNode new_node = new JoinNode();
            new_node.Type = ReteNodeType.Join; // "join";
            new_node.Parent = parent;

            parent.Children.AddToFront(new_node);

            parent.AllChildren.AddToFront(new_node);

            foreach (TestAtJoinNode test in tests)
            {
                new_node.Tests.Add(test);
            }
            new_node.AlphaMemory = am;

            am.Successors.AddToFront(new_node);
            ++am.ReferenceCount;
            new_node.NearestAncestorWithSameAmem = find_nearest_ancestor_with_same_amem(parent, am);

            // *** Right Unlinking ***
            if (parent.Items.Count == 0)
            {
                am.Successors.Remove(new_node);
                new_node.IsRightUnlinked = true;
            }
            else if (am.Items.Count == 0)
            {
                if ((parent is DummyTopNode) == false)
                {
                    parent.Children.Remove(new_node);
                    new_node.IsRightUnlinked = true;
                }
            }
            // *** End Right Unlinking ***

            return new_node;
        }
コード例 #4
0
ファイル: Rete.cs プロジェクト: KristenWegner/expergent
        /// <summary>
        /// Finally, we have a helper function for creating a new alpha memory for a given condition,
        /// or finding an existing one to share. The implementation of this function depends on what type
        /// of alpha net implementation is used. If we use a traditional data
        /// ow network, as described in
        /// Section 2.2.1, then we simply start at the top of the alpha network and work our way down,
        /// sharing or building new constant test nodes:
        /// </summary>
        /// <param name="c">The c.</param>
        /// <returns></returns>
        private AlphaMemory build_or_share_alpha_memory(Condition c)
        {
            AlphaMemory am;

            int attributeHash = c.Attribute.GetHashCode();
            int valueHash = c.Value.GetHashCode();
            int idHash = c.Id.GetHashCode();

            if (_alpha_network.ContainsKey(attributeHash))
            {
                Dictionary<int, Dictionary<int, AlphaMemory>> valueDict = _alpha_network[attributeHash];
                if (valueDict.ContainsKey(valueHash))
                {
                    Dictionary<int, AlphaMemory> idDict = valueDict[valueHash];
                    if (idDict.ContainsKey(idHash))
                    {
                        am = idDict[idHash];
                        am.Conditions.Add(c.ToString());
                        return am;
                    }
                    else //no idHash
                    {
                        am = new AlphaMemory();
                        am.ReferenceCount = 0;
                        am.Label = "A" + (++_next_alpha_node);
                        am.Conditions.Add(c.ToString());
                        idDict.Add(idHash, am);
                    }
                }
                else //no valueHash
                {
                    am = new AlphaMemory();
                    am.ReferenceCount = 0;
                    am.Label = "A" + (++_next_alpha_node);
                    am.Conditions.Add(c.ToString());
                    Dictionary<int, AlphaMemory> idDict = new Dictionary<int, AlphaMemory>(THIRD_LEVEL_ALPHA_HASH_INITIAL_SIZE);
                    idDict.Add(idHash, am);
                    valueDict.Add(valueHash, idDict);
                }
            }
            else //no attribHash
            {
                am = new AlphaMemory();
                am.ReferenceCount = 0;
                am.Label = "A" + (++_next_alpha_node);
                am.Conditions.Add(c.ToString());
                Dictionary<int, AlphaMemory> idDict = new Dictionary<int, AlphaMemory>(THIRD_LEVEL_ALPHA_HASH_INITIAL_SIZE);
                idDict.Add(idHash, am);

                Dictionary<int, Dictionary<int, AlphaMemory>> valueDict = new Dictionary<int, Dictionary<int, AlphaMemory>>(SECOND_LEVEL_ALPHA_HASH_INITIAL_SIZE);
                valueDict.Add(valueHash, idDict);

                _alpha_network.Add(attributeHash, valueDict);
            }

            foreach (WME w in _working_memory)
            {
                if (check_constant_tests(w, c))
                {
                    alpha_memory_activation(am, w);
                }
            }

            return am;
        }
コード例 #5
0
ファイル: Rete.cs プロジェクト: KristenWegner/expergent
        /// <summary>
        /// Whenever a new WME is filtered through the alpha network and reaches an alpha memory, we
        /// simply add it to the list of other WMEs in that memory, and inform each of the attached join
        /// nodes:
        /// </summary>
        /// <param name="node">The node.</param>
        /// <param name="w">The w.</param>
        private void alpha_memory_activation(AlphaMemory node, WME w)
        {
            ItemInAlphaMemory new_item = new ItemInAlphaMemory();
            new_item.WME = w;
            new_item.AlphaMemory = node;
            node.Items.Add(new_item);
            w.AlphaMemoryItems.AddToFront(new_item);

            // *** Neo Integration ***

            if (w.Value.TermType == TermType.EntityObject)
            {
                IFactProvider eo = (IFactProvider) w.Value.Value;
                if (eo.MyFactsHaveBeenAsserted == false)
                {
                    foreach (WME wme in eo.GenerateFactsForRelatedObject(w.Attribute.Value.ToString(), w.Identifier.Value as IFactProvider))
                    {
                        AddWME(wme);
                    }
                }
            }

            if (w.Value.TermType == TermType.ObjectRelation)
            {
                ObjectRelationBase orb = (ObjectRelationBase) w.Value.Value;
                foreach (RulesEnabledEntityObject eo in orb)
                {
                    if (eo.MyFactsHaveBeenAsserted == false)
                    {
                        foreach (WME wme in eo.GenerateFactsForObjectInCollection(w.Attribute.Value.ToString(), orb))
                        {
                            AddWME(wme);
                        }
                    }
                }
            }

            // *** End Neo Integration ***

            //The unlinking process changes the underlying collection so we need a new collection...
            BigList<ReteNode> successors = node.Successors.Clone();

            foreach (ReteNode successor in successors)
            {
                right_activation(successor, w);
            }
        }
コード例 #6
0
ファイル: Rete.cs プロジェクト: KristenWegner/expergent
 /// <summary>
 /// For right unlinking, we need to initialize the nearest-ancestor-with-same-amem fields on
 /// newly-created join and negative nodes. The find-nearest-ancestor-with-same-amem procedure
 /// finds the appropriate value. It starts at a given node and walks up the beta network, returning
 /// the first node it finds that uses a given alpha memory. Note that this node may be in the
 /// subnetwork for a conjunctive negation.
 /// </summary>
 /// <param name="node">The node.</param>
 /// <param name="am">The am.</param>
 /// <returns></returns>
 private ReteNode find_nearest_ancestor_with_same_amem(ReteNode node, AlphaMemory am)
 {
     if (node is DummyTopNode)
     {
         return null;
     }
     if (node.Type == ReteNodeType.Dummy)
     {
         return null;
     }
     if (node.Type == ReteNodeType.Join)
     {
         if (((JoinNode) node).AlphaMemory == am)
         {
             return node;
         }
     }
     if (node.Type == ReteNodeType.Negative)
     {
         if (((NegativeNode) node).AlphaMemory == am)
         {
             return node;
         }
     }
     if (node.Type == ReteNodeType.NCC)
     {
         return find_nearest_ancestor_with_same_amem(((NCCNode) node).Partner.Parent, am);
     }
     return find_nearest_ancestor_with_same_amem(node.Parent, am);
 }