# `Tempo.Network.Normalize`
[🔗](https://github.com/kipcole9/tempo/blob/v0.20.0/lib/tempo/network/normalize.ex#L1)

Reduce a `t:Tempo.Network.t/0` to a Simple Temporal Problem: a
set of boundary nodes and integer-weighted constraints of the single
shape `b₁ − b₂ ≤ k`.

Every period contributes a `start` and an `end` boundary; a single
shared origin `z₀` (`:origin`) anchors absolute dates. The network's
**finest unit** (the finest resolution among its dates) fixes the
integer axis: a date becomes its count of that unit relative to `z₀`,
a duration its count of that unit.

The output feeds `Tempo.Network.Solver`. Conversion is exact when the
network is uniform-unit (as the canonical year-grained chronologies
are); a duration expressed across units (e.g. years on a day axis)
uses nominal calendar lengths and is rounded.

# `boundary`

```elixir
@type boundary() :: Tempo.Network.Relation.boundary()
```

# `edge`

```elixir
@type edge() :: {boundary(), boundary(), integer(), source()}
```

A constraint `from − to ≤ weight`, tagged with the `source` that
produced it (an absolute bound, duration, sequence link, relation, or
the implicit non-negativity of a period) so the solver can build a
trace.

# `source`

```elixir
@type source() ::
  {:bound, :start | :end, :lower | :upper, term(), Tempo.t()}
  | {:duration, :min | :max, term(), Tempo.Duration.t()}
  | {:non_negative, term()}
  | {:sequence, term(), term()}
  | {:relation, Tempo.Network.Relation.t()}
```

# `t`

```elixir
@type t() :: %{nodes: [boundary()], edges: [edge()], unit: atom()}
```

# `finest_unit`

```elixir
@spec finest_unit(Tempo.Network.t()) :: atom()
```

The finest date resolution present in the network's period bounds.

Defaults to `:year` when the network carries no dated bounds.

### Examples

    iex> Tempo.Network.new()
    ...> |> Tempo.Network.add_period(:a, start: "1200-06-15")
    ...> |> Tempo.Network.Normalize.finest_unit()
    :day

# `normalize`

```elixir
@spec normalize(Tempo.Network.t()) :: t()
```

Normalise a network into `%{nodes, edges, unit}`.

### Arguments

* `network` is a `t:Tempo.Network.t/0`.

### Returns

* a map with `:nodes` (boundary variables including `:origin`),
  `:edges` (`{from, to, weight, source}` constraints meaning
  `from − to ≤ weight`), and `:unit` (the axis unit atom).

### Examples

    iex> network =
    ...>   Tempo.Network.new()
    ...>   |> Tempo.Network.add_period(:k1, start: ~o"1200Y", duration: {:at_least, ~o"P20Y"})
    iex> normalized = Tempo.Network.Normalize.normalize(network)
    iex> normalized.unit
    :year
    iex> Enum.any?(normalized.edges, &match?({{:start, :k1}, {:end, :k1}, -20, _}, &1))
    true

---

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