The beta side of the network: a graph of Rete.Network.Node descriptions.
Internal. The compiler walks each production's sorted left hand side in order. It
adds one node per condition, under the nodes the previous condition produced. Node 0
is an artificial root, so the graph has a single entry point.
Parents are a list. A disjunction adds each branch as its own chain, and hands the union of the branch terminals to the next condition. So the branches re-converge on it. That is why the compiler never flattens the LHS to disjunctive normal form. DNF over the whole LHS costs work that is exponential in the number of disjunctions. To fan out for each condition costs only linear work.
Sharing requires equality and the same parent set. Equality alone is a correctness
bug. In a({:customer, cid}, {:order, cid, amt}) and b({:vendor, cid}, {:order, cid, amt}), the two order conditions are equal, but they sit under different parents.
Sharing them would let a :vendor token join a :customer's elements. A terminal keys
on the production's identity instead, so two rules with an identical LHS fire
independently.
{:or, []} is false, and the compiler builds nothing for a path through one.
Otherwise, a keyless condition after a false element would become an entry point the
alpha index feeds. An unsatisfiable rule would then fire on every fact. See
docs/design/network.md ยง4.
Summary
Functions
Adds one production, sharing nodes with everything already in the graph.
Adds every production to a new graph, in order.
The children of a node, in the order they were added.
Every node satisfying a predicate, by ascending id.
An empty graph containing only the root.
The node under an id, or nil.
The parents of a node.
The id of the artificial root every rule hangs from.
Every node whose only parent is the root: the entry points of the beta side.
Types
@type id() :: non_neg_integer()
Node ids, allocated in insertion order.
Functions
@spec add_production(t(), Rete.IR.Production.t()) :: t()
Adds one production, sharing nodes with everything already in the graph.
A production whose left hand side is unsatisfiable โ one that contains a
{:or, []} outside every branch that could avoid it โ adds nothing at all.
@spec build([Rete.IR.Production.t()]) :: t()
Adds every production to a new graph, in order.
Order matters only for id allocation, and therefore only for readability. The same productions, in the same order, always produce the same ids.
The children of a node, in the order they were added.
@spec filter(t(), (Rete.Network.Node.t() -> boolean())) :: [Rete.Network.Node.t()]
Every node satisfying a predicate, by ascending id.
@spec new() :: t()
An empty graph containing only the root.
@spec node(t(), id()) :: Rete.Network.Node.t() | nil
The node under an id, or nil.
The parents of a node.
@spec root_id() :: id()
The id of the artificial root every rule hangs from.
Every node whose only parent is the root: the entry points of the beta side.