/// <summary> /// When adding a production that uses an NCC, we use the build-or-share-ncc-nodes function. /// Most of the work in this function is done by the helper function build-or-share-network-for- /// conditions, which builds or shares the whole subnetwork for the subconditions of the NCC. The /// rest of the build-or-share-ncc-nodes function then builds or shares the NCC and NCC partner /// nodes. /// </summary> /// <param name="parent">The parent.</param> /// <param name="c">The c.</param> /// <param name="earlier_conds">The earlier_conds.</param> /// <returns></returns> private ReteNode build_or_share_ncc_nodes(JoinNode parent, Condition c, List<LeftHandSideCondition> earlier_conds) { ReteNode bottom_of_subnetwork = build_or_share_network_for_conditions(parent, c.SubConditions, earlier_conds); foreach (ReteNode child in parent.Children) { if (child.Type == ReteNodeType.NCC && ((NCCNode) child).Partner.Parent == bottom_of_subnetwork) { return child; } } NCCNode new_node = new NCCNode(); NCCPartnerNode new_partner = new NCCPartnerNode(); new_node.Type = ReteNodeType.NCC; // "NCC"; new_partner.Type = ReteNodeType.NCCPartner; // "NCC-partner"; parent.IsHeadOfSubNetwork = true; new_node.Parent = parent; parent.Children.Add(new_node); new_partner.Parent = bottom_of_subnetwork; bottom_of_subnetwork.Children.AddToFront(new_partner); new_node.Partner = new_partner; new_partner.NCCNode = new_node; new_partner.NumberOfConjuncts = c.SubConditions.Count; update_new_node_with_matches_from_above(new_node); update_new_node_with_matches_from_above(new_partner); return new_node; }
/// <summary> /// Ncc_partner_node_left_activations the specified partner. /// </summary> /// <remarks> /// To handle an NCC partner node (left) activation, we take the new match from the subnetwork /// and build a "result" token to store it. (The pseudocode for this is shown in Figure 2.8.) Next we /// try to find the appropriate owner token in the NCC node's memory. (There might be one there, /// if this is a new subconditions match for an old preceding-conditions match, or there might not /// be one there, if this is an initial subconditions match for a new preceding-conditions match.) /// If we find an appropriate owner token, then we add the new result token to its local memory; /// if the number of results in the local memory changes from zero to one | indicating that the /// NCC was previously true but is now false | then we call the delete-descendents-of-token helper /// function to delete any tokens lower in the network that depend on this owner token. (This is /// similar to the negative-node-right-activation procedure on page 43.) On the other hand, if there /// isn't an appropriate owner token already in the NCC node's memory, then this new result token /// is placed in the new-result-buffer. (The NCC node will soon be activated and collect any new /// results from the buffer.) /// </remarks> /// <param name="partner">The partner.</param> /// <param name="t">The t.</param> /// <param name="w">The w.</param> private void ncc_partner_node_left_activation(NCCPartnerNode partner, Token t, WME w) { NCCNode nccNode = partner.NCCNode; Token new_result = make_token(partner, t, w); Token owners_t = t; WME owners_w = w; for (int i = 0; i < partner.NumberOfConjuncts; i++) { owners_w = owners_t.WME; owners_t = owners_t.Parent; } foreach (Token owner in nccNode.Items) { if (owner.Parent == owners_t && owner.WME == owners_w) { owner.NCCResults.Add(new_result); new_result.Owner = owner; delete_descendents_of_token(owner); } else { partner.NewResultBuffer.AddToFront(new_result); } } }