# `intervals`

This library provides:

- an `interval_protocol` protocol and an `interval` object implementing the 13 Allen base interval relations plus interval pair classification using `relation/3`

- an `interval_algebra_protocol` protocol and an `interval_algebra` object implementing Allen relation algebra predicates over the 13 base relation atoms

- an `interval_relation_set_protocol` protocol and an `interval_relation_set` object implementing canonical relation-set operations over Allen base relation atoms

- an `interval_constraint_network_protocol` protocol and an `interval_constraint_network` object implementing first interval constraint-network predicates over canonical relation sets, including batch refinement, explanation lists, and network inspection/comparison helpers

The `interval` object works on interval terms represented as `i(Start, End)`. The `interval_algebra` object works on relation atoms such as `before`, `overlaps`, and `contains`. The `interval_relation_set` object works on canonical ordered duplicate-free lists of relation atoms. The `interval_constraint_network` object works on `network(Nodes, Constraints)` terms whose pair constraints are relation sets. Internally, the `interval_constraint_network` object compiles that public representation to an a dense indexed form for propagation and for most query operations, while still returning ordinary `network/2` terms at the API boundary.

The `interval_algebra::compose/3` predicate returns canonical ordered duplicate-free lists of base relation atoms.

## Practical limits

The `interval_constraint_network` object is intended for small-to-medium symbolic networks. It uses a complete `network(Nodes, Constraints)` representation, so the number of stored pair constraints grows quadratically with the number of nodes. Propagation is based on path consistency and now uses an internal dense indexed representation with direct pair access, a reverse node-to-index table, and scheduled-pair tracking to avoid repeated linear worklist duplicate checks. This substantially reduces overhead relative to a purely list-based implementation, but the representation is still dense and updates still rebuild parts of the internal matrix before the result is decompiled back to a public `network/2` term.

In practice, the network predicates are suitable for moderate qualitative temporal reasoning workloads, but they should not be treated as a large-scale or latency-sensitive temporal CSP solver. Exact limits depend on the Prolog backend, network density, how often closure is recomputed, and how often callers invoke single-step API operations that must compile or decompile the public network representation.

## API documentation

Open the ../../apis/library_index.html#intervals link in a web browser.

## Loading

To load all entities in this library, load the `loader.lgt` file:

    | ?- logtalk_load(intervals(loader)).

## Testing

To test this library predicates, load the `tester.lgt` file:

    | ?- logtalk_load(intervals(tester)).

## Examples

Classify two valid intervals according to their unique Allen base relation:

    | ?- interval::new(1, 3, I1), interval::new(3, 5, I2), interval::relation(I1, I2, Relation).
    Relation = meets.

Compose two Allen base relation atoms:

    | ?- interval_algebra::compose(meets, met_by, Relations).
    Relations = [finishes, finished_by, equal].

Normalize an Allen relation set:

    | ?- interval_relation_set::normalize([during, before, during], RelationSet).
    RelationSet = [before, during].

Propagate interval constraints across a small symbolic network:

    | ?- interval_constraint_network::new([a, b, c], Network0),
         interval_constraint_network::refine(Network0, a, b, [before], Network1),
         interval_constraint_network::refine(Network1, b, c, [before], Network2),
         interval_constraint_network::path_consistency(Network2, Network3),
         interval_constraint_network::relation(Network3, a, c, RelationSet).
    RelationSet = [before].

Check whether a query is entailed by the current symbolic constraints:

    | ?- interval_constraint_network::entails(Network3, a, c, [before, meets]).
    true.

Inspect a simple explanation for an entailed relation:

    | ?- interval_constraint_network::entails(Network3, a, c, [before], Explanation).
    Explanation = propagated(b, [before], [before], [before]).

Inspect a simple contradiction explanation after closure:

    | ?- interval_constraint_network::contradiction(Closure, Explanation).
    Explanation = contradiction(a, c, propagated(b, [before], [before], [before])).

Refine and propagate in a single operation that fails on contradiction:

    | ?- interval_constraint_network::new([a, b, c], Network0),
         interval_constraint_network::refine_propagate(Network0, a, b, [before], Network1).
    Network1 = ...

Post a batch of constraints and propagate them in one step:

    | ?- interval_constraint_network::refine_propagate(Network0, [constraint(a, b, [before]), constraint(b, c, [before])], Network1).
    Network1 = ...

Collect direct and propagated changes while propagating:

    | ?- interval_constraint_network::propagate(Network2, Network3, Changes).
    Changes = [...].

Query which node triples caused the propagated refinements:

    | ?- interval_constraint_network::propagation_triples(Changes, Triples).
    Triples = [triple(a, b, c)].

List all immediate explanations supporting an entailed query:

    | ?- interval_constraint_network::entailment_explanations(Network3, a, c, [before, meets], Explanations).
    Explanations = [propagated(b, [before], [before], [before])].

List all contradiction explanations currently present in an inconsistent network:

    | ?- interval_constraint_network::contradiction_explanations(Closure, Explanations).
    Explanations = [...].

Inspect a closure and compare networks by generality or equivalence:

    | ?- interval_constraint_network::constraints(Network3, Constraints).
    Constraints = [constraint(a, b, [before]), constraint(a, c, [before]), constraint(b, c, [before])].

    | ?- interval_constraint_network::subsumes(Network0, Network3).
    true.

    | ?- interval_constraint_network::equivalent(Network3, Network5).
    true.