Interval arithmetic (just a few functions)

Dear list,

I have seen this nice package for interval arithmetic:

:- use_module(library(clpBNR)).

example :-
    X = 1,
    Y::real(-0.1, 0.1),
    {Z == X + Y},
    writeln(sum: Z).

What I am wondering is (I apologize if the question is trivial): The package clpBNR implements the arithmetic as a constraint solver, which is nice, but way to much for me (and maybe too slow, I don’t know). Is there a simpler, “functional” alternative, basically one that would just duplicate is/2. In my use case, the LHS of ==/2 is always a variable, and everything on the RHS is instantiated.

Best regards,

Matthias

1 Like

No, not a trivial question. You are correct that clpBNR implements real relational arithmetic over intervals. I think what you’re looking for is extending the current functional arithmetic system with a new interval numeric type, similar to bounded reals in Eclipse.

I’m not aware of any packages implementing bounded reals for SWI-Prolog but, now that rounding modes are supported, this could implemented in Prolog as a new isi predicate (with operator def.) which evaluates the RHS expression (containing bounded real values) and unifies the result with LHS. You would have to define the structure of a bounded real, e.g., (L,H), and write the code to perform the evaluation over expressions of mixed numeric types. (You could use the clpBNR primitives as a guide but they implement relational semantics rather than functional so not an exact fit; functional semantics would actually be simpler.) The complexity of this job depends on the set arithmetic functions you want to support.

1 Like

Thanks. In fact, the subset of arithmetic functions is rather small, not more than highschool mathematics. I want to use it to deal with the rounding errors of my students, example:

t-ratio in statistics, T = (D - Mu) / (S / sqrt(N)), but the D is already from a previous task, and whenever you see “dec2”, I suspect that my students truncate or round the result to maybe 2 digits.

writeln(tratio),
interval(5.7 ... 5.8, D),
interval(4.0 ... 4.0, Mu),
interval(3.8 ... 3.8, S),
interval(24.0 ... 24.0, N),
interval(dec2(frac(D - Mu, dec2(S / dec2(sqrt(N))))), T),
writeln(t --> T).

resulting in a “range” of 2.17 to 2.34 for the accepted solution.

When I am done, I’ll make a “pack” out of the intervals, and, of course, I would much appreciate if you could have a short glance at it.

If the functions you’re interested in are monotonic, the implementation is fairly straight forward. There may be the odd special case, e.g., division by an interval containing 0, but that should be manageable. There’s a fair amount of published material on interval arithmetic if you need the details.

One of clpBNR's primary concerns is correctness over the reals in the face of floating point rounding errors, i.e., whether any result is guaranteed to contain the real value of the expression. This determines whether rounding modes need to be controlled.

1 Like

I’ve seen the literature. 25 cases to distinguish for division :slight_smile:

1 Like

Another option (since you seem to only care about a few decimal places) you could use, library(clpfd) and use integer arithmetic (dividing the results by a suitable number at the end).

You may have to implement some approximation of sqrt(N), since I don’t think clpfd provides that.