// Souffle - A Datalog Compiler
// Copyright (c) 2023, The Souffle Developers. All rights reserved
// Licensed under the Universal Permissive License v 1.0 as shown at:
// - https://opensource.org/licenses/UPL
// - <souffle root>/licenses/SOUFFLE-UPL.txt

.type Interval = [lb:number, ub:number]
.functor lub(a:Interval, b:Interval):Interval stateful
.functor glb(a:Interval, b:Interval):Interval stateful

.init ex1 = _ex1
.init ex2 = _ex2
.init ex3 = _ex3
.init ex4 = _ex4

.lattice Interval<> {
    Bottom -> [0, -1],
    Lub    -> @lub(_,_),
    Glb    -> @glb(_,_)
}

.comp _ex1 {
    // testing lub on a non-recursive relation Y
    .decl X(x:number)

    .decl R(
        x:number,
        i:Interval<>,
        j:Interval<>)
    .output R()

    X(42).

    R(x, [20, 30], [1, 2]),
    R(x, [0, 10], [6,10]) :-
        X(x).
}

.comp _ex2 {
    // testing lub on a recursive relation Y with non-recursive clauses
    .decl X(x:number)

    .decl R(
        x:number,
        i:Interval<>,
        j:Interval<>)
    .output R()

    X(42).

    R(x, [20, 30], [1, 40]),
    R(x, [0, 10], [6,10]) :-
        X(x).

    R(x, b, a) :-
        R(x, a, b).

}

.comp _ex3 {
    // testing glb
    .decl X(x:number, i:Interval<>)
    .decl Y(x:number, i:Interval<>)
    .decl R(x:number, i:Interval<>)
    .output R()

    X(0, [0,100]).
    Y(0, [50, 150]).

    R(x, i) :-
        X(x, i),
        Y(x, i).

}

.comp _ex4 {
    // testing glb
    .decl X(i:Interval<>)
    .decl Y(i:Interval)
    .decl R(i:Interval<>)
    .output R()

    X([0,100]).
    Y([50, 150]).

    R(i) :-
        X(i),
        Y(i).

    .decl A(i:Interval<>)
    .decl B(i:Interval<>)
    .decl C(i:Interval<>)
    .output C()

    A([-10, -1]).
    B([1, 100]).
    C(i) :- A(i), B(i).

}