|
ReteEngine 1.0
A rules engine and builder
|
The ExistsNode class represents a node in a Rete network that implements the "exists" condition. It tracks partial matches from the left (beta) side and facts from the right (alpha) side, ensuring that a token is only propagated to successors if at least one matching fact exists on the right. The node maintains a count of how many right facts currently block each left token, allowing it to efficiently determine when to assert or retract tokens based on changes in the right memory. This node is essential for implementing rules that require the existence of certain conditions without needing to specify all possible combinations of facts. <Remark> As a side note, in a rete network, the ExistsNode and the NotNode are very similar in structure and logic, with the main difference being that the ExistsNode propagates tokens when at least one match exists, while the NotNode propagates tokens only when no matches exist. This means that the ExistsNode will assert tokens when the count of blocking facts is greater than zero, whereas the NotNode will assert tokens when the count is zero. Both nodes must carefully manage their internal state to ensure correct propagation of tokens based on changes in the right memory.</Remark>. More...
Public Member Functions | |
| ExistsNode (string name, Func< Token, object, bool > constraint) | |
| The constructor for the ExistsNode takes a name for debugging purposes and a join constraint function that determines whether a given left token and right fact should be considered a match. The join constraint is a critical component of the node, as it defines the logic for how tokens and facts are evaluated against each other to determine whether a token should be blocked or allowed to propagate. The nodeName parameter is used for identification and debugging, allowing developers to easily trace the flow of tokens through the network and understand which nodes are responsible for certain matches or failures. The joinConstraint function should return true if the token and fact satisfy the conditions for a match, and false otherwise. This allows for flexible and powerful rule definitions based on the specific requirements of the application using the Rete engine. | |
| void | AddSuccessor (IReteNode node) |
| Adds a successor node to this ExistsNode. When a new successor is added, the node must "Refresh" it with the current valid state of tokens. This means that for each token currently in the leftMatches dictionary that has a count of zero (indicating it is not blocked by any right facts), the node will assert that token to the new successor. This ensures that the new successor node is immediately aware of all currently valid tokens and can properly propagate them further down the network. The Refresh process is crucial for maintaining consistency in the Rete network, especially when nodes are added dynamically after some tokens have already been processed. By refreshing the new successor with the current state, we ensure that it can function correctly without missing any relevant tokens or facts. | |
| void | Assert (object factOrToken) |
| The Assert method is the main entry point for handling incoming data to this node. It can receive either a Token (from the left/beta side) or a single fact (from the right/alpha side). The method determines the type of the input and delegates to the appropriate handler method (AssertLeft for tokens and AssertRight for facts). This design allows the node to maintain a clear separation of logic for handling different types of inputs while still providing a unified interface for asserting data into the node. The Assert method is responsible for ensuring that the internal state of the node is updated correctly based on the incoming data, which in turn affects how tokens are propagated to successor nodes. | |
| void | AssertLeft (Token token) |
| Handles incoming partial matches from the Left (Beta side) by evaluating them against the current facts in the right memory. For each token asserted from the left, the node checks how many facts in the right memory match it according to the join constraint. The count of matching facts is stored in the leftMatches dictionary. If at least one match exists (count > 0), the token is immediately propagated to successor nodes. This ensures that only tokens that satisfy the "exists" condition are allowed to propagate, while those that do not have any matching facts on the right are effectively blocked and not sent downstream. | |
| void | AssertRight (object fact) |
| Handles incoming single facts from the Right (Alpha side) by adding them to the right memory and checking if they match any currently active left tokens. For each fact asserted from the right, the node iterates through all tokens in the leftMatches dictionary and evaluates the join constraint against the new fact. If a match is found, the count for that token is incremented. If this is the first matching fact for that token (count changes from 0 to 1), the token is propagated to successor nodes. This ensures that when a new fact is added that satisfies the "exists" condition for any token, those tokens are activated and sent downstream, while tokens that do not have any matching facts remain blocked. | |
| void | Retract (object factOrToken) |
| The Retract method is responsible for handling the removal of either a Token (from the left/beta side) or a single fact (from the right/alpha side). Similar to the Assert method, it determines the type of input and delegates to the appropriate handler method (RetractLeft for tokens and RetractRight for facts). When retracting a token from the left, the node checks if it was previously active (count > 0) and if so, it propagates a retraction to successor nodes. When retracting a fact from the right, the node removes it from the right memory and checks if this causes any previously blocked tokens to become active again. If a token's count changes from 1 to 0 due to the retraction of a fact, it means that token is no longer blocked and should be retracted from successor nodes. This ensures that the node maintains an accurate representation of which tokens are currently valid based on the presence or absence of matching facts in the right memory. | |
| void | RetractLeft (Token token) |
| Retracts a token from the left side by removing it from the leftMatches dictionary. If the token was previously active (count > 0), it propagates a retraction to successor nodes. This ensures that when a token is removed from the left side, any downstream nodes that were relying on that token being active are notified and can update their state accordingly. The node does not need to check for matches against the right memory when retracting a token, as the presence of matching facts only affects whether a token is active or not, and once a token is retracted, it is no longer relevant regardless of the right memory state. | |
| void | RetractRight (object fact) |
| Retracts a fact from the right side by removing it from the right memory and checking if this causes any previously blocked tokens to become active again. For each token in the leftMatches dictionary, if the retracted fact matches the token according to the join constraint, the count for that token is decremented. If this causes the count to change from 1 to 0, it means that token is no longer blocked by any facts on the right and should be retracted from successor nodes. This ensures that when a fact is removed from the right side, any tokens that were previously blocked by that fact are properly updated and downstream nodes are notified of their new state. | |
| void | Refresh (object factOrToken, string propertyName) |
| Forces a downstream node to sync with this node's current valid tokens. This is used when a new successor node is added, or when an existing successor node needs to be refreshed due to changes in the network. The method takes either a Token or a fact and a property name (for fact refreshes) and determines which type of refresh to perform. For token refreshes, it checks if the token is currently blocked or not and propagates an assert if it is valid. For fact refreshes, it checks all tokens against the refreshed fact and updates their counts accordingly, propagating asserts or retracts as needed based on the new state of matches. This method ensures that successor nodes are always in sync with the current state of this ExistsNode, allowing for correct propagation of tokens based on the latest information. | |
| void | RefreshLeft (Token token) |
| Refreshes a token from the left side by checking if it is currently blocked or not and propagating an assert if it is valid. This method is used when a new successor node is added or when an existing successor node needs to be refreshed due to changes in the network. If the token is not currently in the leftMatches dictionary, it means it has not been processed yet, so we call AssertLeft to evaluate it against the current right memory and update its state accordingly. This ensures that any new or updated tokens are properly evaluated and propagated to successor nodes based on their current validity. | |
| void | RefreshRight (object fact, string propertyName) |
| Refreshes a fact from the right side by checking all tokens against the refreshed fact and updating their counts accordingly. This method is used when a new successor node is added or when an existing successor node needs to be refreshed due to changes in the network. For each token in the leftMatches dictionary, if the refreshed fact matches the token according to the join constraint, we check if it was previously blocked (count == 0) and if so, we increment the count and propagate an assert to successor nodes. If it was previously active (count > 0), we simply update the count without propagating since it is already valid. This ensures that any changes to facts on the right side are properly reflected in the state of tokens and that successor nodes are kept up-to-date with the current valid tokens based on the latest information. | |
| void | DebugPrint (object fact, int level=0) |
| Prints the internal state of this ExistsNode for debugging purposes. This method provides a visual representation of the current tokens in the leftMatches dictionary, the facts in the rightMemory, and how they are related in terms of blocking. The output includes the name of the node, the number of left tokens and right facts, and for each left token, it shows how many right facts are currently blocking it. | |
The ExistsNode class represents a node in a Rete network that implements the "exists" condition. It tracks partial matches from the left (beta) side and facts from the right (alpha) side, ensuring that a token is only propagated to successors if at least one matching fact exists on the right. The node maintains a count of how many right facts currently block each left token, allowing it to efficiently determine when to assert or retract tokens based on changes in the right memory. This node is essential for implementing rules that require the existence of certain conditions without needing to specify all possible combinations of facts. <Remark> As a side note, in a rete network, the ExistsNode and the NotNode are very similar in structure and logic, with the main difference being that the ExistsNode propagates tokens when at least one match exists, while the NotNode propagates tokens only when no matches exist. This means that the ExistsNode will assert tokens when the count of blocking facts is greater than zero, whereas the NotNode will assert tokens when the count is zero. Both nodes must carefully manage their internal state to ensure correct propagation of tokens based on changes in the right memory.</Remark>.
| ReteCore.ExistsNode.ExistsNode | ( | string | name, |
| Func< Token, object, bool > | constraint ) |
The constructor for the ExistsNode takes a name for debugging purposes and a join constraint function that determines whether a given left token and right fact should be considered a match. The join constraint is a critical component of the node, as it defines the logic for how tokens and facts are evaluated against each other to determine whether a token should be blocked or allowed to propagate. The nodeName parameter is used for identification and debugging, allowing developers to easily trace the flow of tokens through the network and understand which nodes are responsible for certain matches or failures. The joinConstraint function should return true if the token and fact satisfy the conditions for a match, and false otherwise. This allows for flexible and powerful rule definitions based on the specific requirements of the application using the Rete engine.
| name | The name of this node as identification. |
| constraint | The condition to be used as the 'EXISTS' constraint. |
| void ReteCore.ExistsNode.AddSuccessor | ( | IReteNode | node | ) |
Adds a successor node to this ExistsNode. When a new successor is added, the node must "Refresh" it with the current valid state of tokens. This means that for each token currently in the leftMatches dictionary that has a count of zero (indicating it is not blocked by any right facts), the node will assert that token to the new successor. This ensures that the new successor node is immediately aware of all currently valid tokens and can properly propagate them further down the network. The Refresh process is crucial for maintaining consistency in the Rete network, especially when nodes are added dynamically after some tokens have already been processed. By refreshing the new successor with the current state, we ensure that it can function correctly without missing any relevant tokens or facts.
| node | The node to add this node to as a successor. |
| void ReteCore.ExistsNode.Assert | ( | object | factOrToken | ) |
The Assert method is the main entry point for handling incoming data to this node. It can receive either a Token (from the left/beta side) or a single fact (from the right/alpha side). The method determines the type of the input and delegates to the appropriate handler method (AssertLeft for tokens and AssertRight for facts). This design allows the node to maintain a clear separation of logic for handling different types of inputs while still providing a unified interface for asserting data into the node. The Assert method is responsible for ensuring that the internal state of the node is updated correctly based on the incoming data, which in turn affects how tokens are propagated to successor nodes.
| factOrToken | The fact or token this operation is acting upon. |
Implements ReteCore.IReteNode.
| void ReteCore.ExistsNode.AssertLeft | ( | Token | token | ) |
Handles incoming partial matches from the Left (Beta side) by evaluating them against the current facts in the right memory. For each token asserted from the left, the node checks how many facts in the right memory match it according to the join constraint. The count of matching facts is stored in the leftMatches dictionary. If at least one match exists (count > 0), the token is immediately propagated to successor nodes. This ensures that only tokens that satisfy the "exists" condition are allowed to propagate, while those that do not have any matching facts on the right are effectively blocked and not sent downstream.
| token | The token this operation is acting upon. |
| void ReteCore.ExistsNode.AssertRight | ( | object | fact | ) |
Handles incoming single facts from the Right (Alpha side) by adding them to the right memory and checking if they match any currently active left tokens. For each fact asserted from the right, the node iterates through all tokens in the leftMatches dictionary and evaluates the join constraint against the new fact. If a match is found, the count for that token is incremented. If this is the first matching fact for that token (count changes from 0 to 1), the token is propagated to successor nodes. This ensures that when a new fact is added that satisfies the "exists" condition for any token, those tokens are activated and sent downstream, while tokens that do not have any matching facts remain blocked.
| fact | The fact this operation is acting upon. |
| void ReteCore.ExistsNode.DebugPrint | ( | object | fact, |
| int | level = 0 ) |
Prints the internal state of this ExistsNode for debugging purposes. This method provides a visual representation of the current tokens in the leftMatches dictionary, the facts in the rightMemory, and how they are related in terms of blocking. The output includes the name of the node, the number of left tokens and right facts, and for each left token, it shows how many right facts are currently blocking it.
| fact | The fact whose information is to be output. |
| level | A level of indentation. |
Implements ReteCore.IReteNode.
| void ReteCore.ExistsNode.Refresh | ( | object | factOrToken, |
| string | propertyName ) |
Forces a downstream node to sync with this node's current valid tokens. This is used when a new successor node is added, or when an existing successor node needs to be refreshed due to changes in the network. The method takes either a Token or a fact and a property name (for fact refreshes) and determines which type of refresh to perform. For token refreshes, it checks if the token is currently blocked or not and propagates an assert if it is valid. For fact refreshes, it checks all tokens against the refreshed fact and updates their counts accordingly, propagating asserts or retracts as needed based on the new state of matches. This method ensures that successor nodes are always in sync with the current state of this ExistsNode, allowing for correct propagation of tokens based on the latest information.
| factOrToken | The fact or token this operation is acting upon. |
| propertyName | The name of the property in the fact cell that is being updated. |
Implements ReteCore.IReteNode.
| void ReteCore.ExistsNode.RefreshLeft | ( | Token | token | ) |
Refreshes a token from the left side by checking if it is currently blocked or not and propagating an assert if it is valid. This method is used when a new successor node is added or when an existing successor node needs to be refreshed due to changes in the network. If the token is not currently in the leftMatches dictionary, it means it has not been processed yet, so we call AssertLeft to evaluate it against the current right memory and update its state accordingly. This ensures that any new or updated tokens are properly evaluated and propagated to successor nodes based on their current validity.
| token | The token this operation is acting upon. |
| void ReteCore.ExistsNode.RefreshRight | ( | object | fact, |
| string | propertyName ) |
Refreshes a fact from the right side by checking all tokens against the refreshed fact and updating their counts accordingly. This method is used when a new successor node is added or when an existing successor node needs to be refreshed due to changes in the network. For each token in the leftMatches dictionary, if the refreshed fact matches the token according to the join constraint, we check if it was previously blocked (count == 0) and if so, we increment the count and propagate an assert to successor nodes. If it was previously active (count > 0), we simply update the count without propagating since it is already valid. This ensures that any changes to facts on the right side are properly reflected in the state of tokens and that successor nodes are kept up-to-date with the current valid tokens based on the latest information.
| fact | The fact this operation is acting upon. |
| propertyName | The name of the property in the fact cell that is being updated. |
| void ReteCore.ExistsNode.Retract | ( | object | factOrToken | ) |
The Retract method is responsible for handling the removal of either a Token (from the left/beta side) or a single fact (from the right/alpha side). Similar to the Assert method, it determines the type of input and delegates to the appropriate handler method (RetractLeft for tokens and RetractRight for facts). When retracting a token from the left, the node checks if it was previously active (count > 0) and if so, it propagates a retraction to successor nodes. When retracting a fact from the right, the node removes it from the right memory and checks if this causes any previously blocked tokens to become active again. If a token's count changes from 1 to 0 due to the retraction of a fact, it means that token is no longer blocked and should be retracted from successor nodes. This ensures that the node maintains an accurate representation of which tokens are currently valid based on the presence or absence of matching facts in the right memory.
| factOrToken | The fact or token this operation is acting upon. |
Implements ReteCore.IReteNode.
| void ReteCore.ExistsNode.RetractLeft | ( | Token | token | ) |
Retracts a token from the left side by removing it from the leftMatches dictionary. If the token was previously active (count > 0), it propagates a retraction to successor nodes. This ensures that when a token is removed from the left side, any downstream nodes that were relying on that token being active are notified and can update their state accordingly. The node does not need to check for matches against the right memory when retracting a token, as the presence of matching facts only affects whether a token is active or not, and once a token is retracted, it is no longer relevant regardless of the right memory state.
| token | The token this operation is acting upon. |
| void ReteCore.ExistsNode.RetractRight | ( | object | fact | ) |
Retracts a fact from the right side by removing it from the right memory and checking if this causes any previously blocked tokens to become active again. For each token in the leftMatches dictionary, if the retracted fact matches the token according to the join constraint, the count for that token is decremented. If this causes the count to change from 1 to 0, it means that token is no longer blocked by any facts on the right and should be retracted from successor nodes. This ensures that when a fact is removed from the right side, any tokens that were previously blocked by that fact are properly updated and downstream nodes are notified of their new state.
| fact | The fact this operation is acting upon. |