Rete.Network (Rete v0.2.0)

Copy Markdown View Source

A compiled rulebase: everything the engine needs, and nothing that changes.

Internal. A network is built once, from a set of ruleset modules, and it is then immutable. So any number of sessions can share one. Working memory, the agenda, and pending propagations belong to the engine, not here.

alphas      alpha node id => %Rete.Network.Node.Alpha{}
alpha_beta  alpha node id => the beta node ids it feeds
taxonomy    %Rete.Taxonomy{}, indexed: fact type => alpha node ids
graph       %Rete.Compiler.BetaGraph{}, the beta nodes and their edges
queries     {module, query name} => query node id
productions the productions compiled in, including generated helpers

A fact travels in three steps. Rete.Taxonomy.alpha_ids/2 maps its type to alpha node ids — the only place the taxonomy is consulted. Each alpha's arity-1 function turns the fact into a bindings map, or nil. Matching elements reach the beta nodes in alpha_beta. The engine propagates them along the graph's forward edges.

An alpha node id is the expression code of the conditions it was built from. That is why Rete.Compiler.disambiguate_codes/1 runs first. See docs/design/network.md §2.

Summary

Functions

The alpha nodes a fact must be offered to, resolved through the taxonomy.

The beta nodes an alpha node feeds.

Every beta node reachable from the root, by ascending id.

The children of a beta node.

Whether a fact is an internal marker rather than something a rule concluded.

The modules that contributed a production to the network, sorted.

Assembles a network from productions already sorted, classified and free of compound negations.

The beta node under an id, or nil.

Every production terminal, most salient first.

The query node a {module, name} pair refers to, or nil.

Every query in the network, as {module, name} pairs, sorted.

A {module, name} pair as it is written in source.

Types

t()

@type t() :: %Rete.Network{
  alpha_beta: %{required(term()) => [Rete.Compiler.BetaGraph.id()]},
  alphas: %{required(term()) => Rete.Network.Node.Alpha.t()},
  graph: Rete.Compiler.BetaGraph.t(),
  marker_types: MapSet.t(atom()),
  productions: [Rete.IR.Production.t()],
  queries: %{required({module(), atom()}) => Rete.Compiler.BetaGraph.id()},
  taxonomy: Rete.Taxonomy.t()
}

Functions

alphas_for(network, fact)

@spec alphas_for(t(), term()) :: [Rete.Network.Node.Alpha.t()]

The alpha nodes a fact must be offered to, resolved through the taxonomy.

beta_children(network, code)

@spec beta_children(t(), term()) :: [Rete.Compiler.BetaGraph.id()]

The beta nodes an alpha node feeds.

beta_nodes(network)

@spec beta_nodes(t()) :: [Rete.Network.Node.t()]

Every beta node reachable from the root, by ascending id.

children(network, id)

The children of a beta node.

marker?(network, fact)

@spec marker?(t(), term()) :: boolean()

Whether a fact is an internal marker rather than something a rule concluded.

modules(network)

@spec modules(t()) :: [module()]

The modules that contributed a production to the network, sorted.

This is what a session was built from. It is what tells apart a typo in a query name from a ruleset never passed to Rete.Session.new/2.

new(productions, taxo_data \\ [], opts \\ [])

Assembles a network from productions already sorted, classified and free of compound negations.

Most callers want Rete.Compiler.build/2, which runs the phases that get a production into that state.

node(network, id)

@spec node(t(), Rete.Compiler.BetaGraph.id()) :: Rete.Network.Node.t() | nil

The beta node under an id, or nil.

production_nodes(network)

@spec production_nodes(t()) :: [Rete.Network.Node.Production.t()]

Every production terminal, most salient first.

Ordered by {salience, internal_salience} descending. The internal tier makes an extracted negation helper run before the rule that negates its marker.

query(network, arg)

@spec query(
  t(),
  {module(), atom()}
) :: Rete.Network.Node.Query.t() | nil

The query node a {module, name} pair refers to, or nil.

query_refs(network)

@spec query_refs(t()) :: [{module(), atom()}]

Every query in the network, as {module, name} pairs, sorted.

ref_string(arg)

@spec ref_string({module(), atom()}) :: String.t()

A {module, name} pair as it is written in source.

iex> Rete.Network.ref_string({MyApp.Orders, :summary})
"MyApp.Orders.summary"