# `ExDatalog.Knowledge`
[🔗](https://github.com/thanos/ex_datalog/blob/v0.5.0/lib/ex_datalog/knowledge.ex#L1)

The complete knowledge base produced by Datalog evaluation.

Contains the derived fact sets for every relation, along with evaluation
statistics (iteration count, duration, relation sizes, termination reason).

The name reflects what this struct *is*: after applying all rules to all
facts until no new facts can be derived, you have a **knowledge base** —
every relation fully materialised, every derivable fact present. You then
*query* this knowledge with `get/2` and `match/3`.

When provenance tracking is enabled (via `explain: true`), the `provenance`
field records which rule derived each fact. Base facts (EDB) are attributed
as `:base`. This field is `nil` when provenance tracking is disabled,
ensuring zero overhead for the common case.

## Termination

The `stats.termination` field indicates how evaluation ended:

- `:fixpoint` — all derivable facts were computed; the knowledge base is
  complete.
- `:iteration_limit` — evaluation stopped because `max_iterations` was
  reached; the knowledge base may be incomplete.
- `:timeout` — evaluation stopped because `timeout_ms` elapsed; the
  knowledge base may be incomplete.

Callers **must** check `stats.termination` to distinguish a complete result
from a truncated one. Returning `{:ok, knowledge}` does not guarantee the
fixpoint was reached.

## Access functions

- `get/2` — all tuples for a relation.
- `match/3` — tuples matching a pattern (`:_` for wildcard).
- `size/2` — number of tuples in a relation.
- `relations/1` — list of all relation names in the knowledge base.

# `provenance`

```elixir
@type provenance() :: %{
  fact_origins: %{
    required(String.t()) =&gt; %{required(tuple()) =&gt; non_neg_integer() | :base}
  },
  rules: %{required(non_neg_integer()) =&gt; ExDatalog.IR.Rule.t()}
}
```

# `stats`

```elixir
@type stats() :: %{
  iterations: non_neg_integer(),
  duration_us: non_neg_integer(),
  relation_sizes: %{required(String.t()) =&gt; non_neg_integer()},
  capabilities: ExDatalog.Capabilities.t(),
  termination: termination()
}
```

# `t`

```elixir
@type t() :: %ExDatalog.Knowledge{
  provenance: provenance() | nil,
  relations: %{required(String.t()) =&gt; MapSet.t(tuple())},
  stats: stats()
}
```

# `termination`

```elixir
@type termination() :: :fixpoint | :iteration_limit | :timeout
```

# `get`

```elixir
@spec get(t(), String.t()) :: MapSet.t(tuple())
```

Returns all tuples for a relation as a MapSet.

## Examples

    iex> knowledge = %ExDatalog.Knowledge{relations: %{"parent" => MapSet.new([{:alice, :bob}])}, stats: %{iterations: 1, duration_us: 0, relation_sizes: %{"parent" => 1}}}
    iex> ExDatalog.Knowledge.get(knowledge, "parent") |> MapSet.to_list()
    [{:alice, :bob}]

# `match`

```elixir
@spec match(t(), String.t(), [term()]) :: MapSet.t(tuple())
```

Returns tuples matching a pattern.

The pattern is a list where `:_` matches any value and other values match
exactly. Useful for querying specific facts.

## Examples

    iex> knowledge = %ExDatalog.Knowledge{relations: %{"parent" => MapSet.new([{:alice, :bob}, {:carol, :dave}, {:alice, :carol}])}, stats: %{iterations: 1, duration_us: 0, relation_sizes: %{"parent" => 3}}}
    iex> ExDatalog.Knowledge.match(knowledge, "parent", [:alice, :_]) |> MapSet.to_list() |> Enum.sort()
    [{:alice, :bob}, {:alice, :carol}]

# `relations`

```elixir
@spec relations(t()) :: [String.t()]
```

Returns all relation names present in the knowledge base.

## Examples

    iex> knowledge = %ExDatalog.Knowledge{relations: %{"parent" => MapSet.new(), "ancestor" => MapSet.new()}, stats: %{iterations: 1, duration_us: 0, relation_sizes: %{}}}
    iex> Enum.sort(ExDatalog.Knowledge.relations(knowledge))
    ["ancestor", "parent"]

# `size`

```elixir
@spec size(t(), String.t()) :: non_neg_integer()
```

Returns the number of tuples in a relation.

## Examples

    iex> knowledge = %ExDatalog.Knowledge{relations: %{"parent" => MapSet.new([{:alice, :bob}, {:carol, :dave}])}, stats: %{iterations: 1, duration_us: 0, relation_sizes: %{"parent" => 2}}}
    iex> ExDatalog.Knowledge.size(knowledge, "parent")
    2

---

*Consult [api-reference.md](api-reference.md) for complete listing*
