Rete.Network (Rete v0.1.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 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, which is 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, and the engine propagates along the graph's forward edges.

An alpha node id is the expression code of the conditions it was built from, which 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.

What a session was built from. That is the difference between a typo in a query name and 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"