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: whole-LHS DNF costs work exponential in the number of disjunctions, while fanning out per 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.