Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make decorated interval the default #590

Merged
merged 33 commits into from
Dec 1, 2023
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
c421962
Make decorated interval the default
OlivierHnt Oct 30, 2023
ecfc3ef
Remove warning
OlivierHnt Oct 30, 2023
f9d5afe
Fix decoration
OlivierHnt Oct 30, 2023
25d6630
Fix tests
OlivierHnt Oct 30, 2023
731df23
Fix tests
OlivierHnt Oct 30, 2023
d20e2df
Fix NaI
OlivierHnt Nov 1, 2023
01921a0
Minor cleanup
OlivierHnt Nov 13, 2023
0b14d21
Add docstring for `_unsafe_bareinterval`
OlivierHnt Nov 13, 2023
e9271ff
Remove decoration `bad` in favour of a new field
OlivierHnt Nov 13, 2023
45990ac
Minor cleanup
OlivierHnt Nov 14, 2023
1390772
Remove `signbit`
OlivierHnt Nov 14, 2023
70c9abf
Fix `pow` and cleanup
OlivierHnt Nov 14, 2023
56cec04
Fix tests
OlivierHnt Nov 14, 2023
5991c5b
Special display for unguaranteed interval
OlivierHnt Nov 14, 2023
9c1283e
Cleanup
OlivierHnt Nov 18, 2023
49d6c8e
Update docs
OlivierHnt Nov 18, 2023
cb6c91e
Fix doctest
OlivierHnt Nov 18, 2023
736971f
Do not error for missing docstring
OlivierHnt Nov 18, 2023
bde155f
Rename `guarantee` to `isguaranteed`
OlivierHnt Nov 27, 2023
d1ab589
Delete empty file decorations.md
OlivierHnt Nov 27, 2023
ad4bc09
Fix missing field infos in docstring
OlivierHnt Nov 27, 2023
0dd6a75
Update `isguaranteed` docstring
OlivierHnt Nov 27, 2023
795dd3b
Update docs
OlivierHnt Nov 27, 2023
a0f88ce
Ensures `NaN` is converted to a NaI
OlivierHnt Nov 28, 2023
1df80e0
Update docs
OlivierHnt Nov 28, 2023
ecbb119
Minor cleanup
OlivierHnt Nov 28, 2023
fb730de
Fix typo
OlivierHnt Dec 1, 2023
d7fcc98
Fix error for boolean functions from Base
OlivierHnt Dec 1, 2023
5d7dbf2
Add docstrings
OlivierHnt Dec 1, 2023
7844416
Fix bug
OlivierHnt Dec 1, 2023
5fb425d
Fix `StackOverflow`
OlivierHnt Dec 1, 2023
7b2def0
Fix `StackOverFlow`
OlivierHnt Dec 1, 2023
dfb71a6
Set correct cuurent version
OlivierHnt Dec 1, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ makedocs(;
"Manual" => [
"Constructing intervals" => "manual/construction.md",
"Usage" => "manual/usage.md",
"Decorations" => "manual/decorations.md",
"API" => "manual/api.md"
]
]
],
warnonly = true
)

deploydocs(;
Expand Down
15 changes: 0 additions & 15 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,3 @@ If you use the IntervalArithmetic library in your publication, research, teachin

- [MPFI.jl](https://github.com/andrioni/MPFI.jl), a Julia wrapper around the [MPFI C library](http://perso.ens-lyon.fr/nathalie.revol/software.html), a multiple-precision interval arithmetic library based on MPFR
- [Intervals.jl](https://github.com/invenia/Intervals.jl), an alternative implementation of basic interval functions by Invenia Technical Computing



## History

This project began in 2014 during a masters' course in the postgraduate programs of Mathematics and Physics at the Universidad Nacional Autónoma de México. It was initially written in Python, then reinitiated in 2015 and rewritten in Julia. We thank the participants of the courses for their contribution, energy and ideas.


## Support

Financial support is acknowledged from DGAPA-UNAM PAPIME grants PE-105911 and PE-107114, and DGAPA-UNAM PAPIIT grant IN-117214.

Luis Benet acknowledges support from *Cátedra Marcos Moshinsky* (2013).

David P. Sanders acknowledges a sabbatical fellowship from CONACYT and thanks Alan Edelman and the Julia group at MIT for hosting his sabbatical visit.
134 changes: 114 additions & 20 deletions docs/src/manual/construction.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
# Constructing intervals

Constructing an interval is the most basic operation in the library. The [`interval`](@ref) constructor is the standard way to create an interval. It accepts one or two values, and an optional bound type.
Constructing an interval is the most basic operation in the library. The [`interval`](@ref) constructor is the standard way to create an interval.

```@repl construction
using IntervalArithmetic
setformat(:full) # print the interval in full
setdisplay(:full) # print the interval in full
interval(0.1) # interval(Float64, 0.1)
interval(0.1, 0.2) # interval(Float64, 0.1, 0.2)
interval(3.1f0) # interval(Float32, 3.1f0)
Expand All @@ -14,31 +12,58 @@ interval(Inf) # not valid since infinity is not part of an interval
interval(3, 2) # not valid since the lower bound is strictly greater than the upper bound
```

The submodule `IntervalArithmetic.Symbols` exports the infix operator `..` as an alias for `interval`.
The above intervals came with a decoration. Decorations are flags, or labels, attached to intervals to indicate the status of a given interval. Decorated intervals provide valuable information on the result of evaluating a function on an initial interval.

OlivierHnt marked this conversation as resolved.
Show resolved Hide resolved
Moreover, an `Interval` comes with a boolean `isguaranteed` field which asserts the reliability of the interval. This field allows for `Interval` to interact, in generic code, with other number types by being set to `false` whenever a call to `convert(::{<:Interval}, ::Number)` occurs. A user interested in validated numerics should **always** have a resulting interval for which `isguaranteed` is true.

OlivierHnt marked this conversation as resolved.
Show resolved Hide resolved
In contrast, a `BareInterval` can be constructed via `bareinterval`. This interval type has no decorations and is always guaranteed (`isguaranteed` is always true). A `BareInterval` is not a subtype of `Real`, there are no allowed conversion with `Number`.

Suppose that a decorated interval $(X, d)$ is the result of evaluating a function $f$, or the composition of a sequence of functions, on an initial decorated interval $(X_0, d_0)$. The meaning of the resulting decoration $d$ is as follows:
- `com` (common): $X$ is a closed, bounded, non-empty subset of the domain of $f$; $f$ is continuous on the interval $X$; and the resulting interval $f(X)$ is bounded.
- `dac` (defined and continuous): $X$ is a non-empty subset of $\mathrm{Dom}(f)$, and $f$ is continuous on $X$.
- `def` (defined): $X$ is a non-empty subset of $\mathrm{Dom}(f)$, i.e. $f$ is defined at each point of $X$.
- `trv` (trivial): always true; gives no information
- `ill` (ill-formed): NaI (Not an Interval) (an error occurred), e.g. $\mathrm{Dom}(f) = \emptyset$.
Decorations follow the ordering `com > dac > def > trv > ill`.

Kolaru marked this conversation as resolved.
Show resolved Hide resolved
When constructing intervals, if no decoration is explicitly specified, then it is initialised with a decoration according to the underlying bare interval:
- `com`: if the interval is non-empty and bounded
- `dac`: if the interval is unbounded
- `trv`: if the interval is empty
- `ill`: if the interval is a NaI

lbenet marked this conversation as resolved.
Show resolved Hide resolved
An explicit decoration may be provided for advanced use.

```@repl construction
using IntervalArithmetic.Symbols
0.1..0.2 # interval(0.1, 0.2)
x = interval(1, 2, dac)
interval(x, def)
```

The [`±`](@ref) (`\pm<tab>`) infix operator creates the interval from the midpoint and the radius.
We strongly encourage the use of `interval` over `bareinterval` to better track, through decorations, the correctness of the computations. One using `BareInterval` should be well aware of the IEEE Standard 1788-2015 specifications. For instance, taking the square root of an interval discards the negative part of the interval which can be misleading if one expected an error to be thrown; on the other hand, the decoration registers this via the flag `trv` (trivial), see `sqrt(interval(-1, 1))` vs `sqrt(bareinterval(-1, 1))`.

The submodule `IntervalArithmetic.Symbols` exports the infix operator `..` and `±` as an alias for `interval`; this submodule must be explicitly imported.

```@repl construction
0 ± 1
using IntervalArithmetic.Symbols
0.1 .. 0.2 # interval(0.1, 0.2; format = :standard)
0.1 ± 0.2 # interval(0.1, 0.2; format = :midpoint)
```

The various string formats are as follows:
- No string parameter or `Empty` string ("[Empty]") returns an empty interval.
- `entire` ("[entire]") and "[,]" string returns entireinterval
- "[nai]" returns `Nai{Type}`
- "[m]" returns `Interval(m,m)`
- "[l, r]" returns `Interval(l, r)`
- "m?r" returns `Interval(m-r, m+r)`
- "m?ren" returns `Interval((m-r)en, (m+r)en)`
- "m?ru" or "m?rd" returns `Interval(m, m+r)` or `Interval(m-r, m)` respectively
- "m?" returns `Interval(m + 5 precision units, m - 5 precision units)`
- "m??" returns `Interval(-Inf, +Inf)`
- "m??u" or "m??d" returns `Interval(m, +Inf)` or `Interval(-Inf, m) respectively`
- no string parameter, `"Empty"` and `"[Empty]"` returns `emptyinterval()`
- `"entire"`, `"[entire]"` and `"[,]"` returns `entireinterval()`
- `"[nai]"` returns a `NaI`
- `"[m]"` returns `interval(m, m)`
- `"[l, r]"` returns `interval(l, r)`
- `"m?r"` returns `interval(m-r, m+r)`
- `"m?ren"` returns `interval((m-r)*1en, (m+r)*1en)`
- `"m?rd"` returns `interval(m-r, m)`
- `"m?ru"` returns `interval(m, m+r)`
- `"m?"` returns `interval(m + 5 precision units, m - 5 precision units)`
- `"m??"` returns `interval(-Inf, +Inf)`
- `"m??d"` returns `interval(-Inf, m)`
- `"m??u"` returns `Interval(m, +Inf)`
To add a specific decoration, add `"_dec"` at the end of the string.

!!! warning
Most real numbers cannot be exactly represented by floating-points. In such cases, the literal expression is rounded at parse time. To construct an interval enclosing the true real number, one must rely on the string constructor mentioned above.
Expand All @@ -62,3 +87,72 @@ The various string formats are as follows:
```@repl construction
I"0.1"
```



## More on decorations

OlivierHnt marked this conversation as resolved.
Show resolved Hide resolved
```
julia> X1 = Interval(0.5, 3)
[0.5, 3]_com

julia> sqrt(X1)
[0.707106, 1.73206]_com
```
In this case, both input and output are "common" intervals, meaning that they are closed and bounded, and that the resulting function is continuous over the input interval, so that fixed-point theorems may be applied. Since `sqrt(X1) ⊆ X1`, we know that there must be a fixed point of the function inside the interval `X1` (in this case, `sqrt(1) == 1`).

```
julia> X2 = Interval(3, ∞)
[3, ∞]_dac

julia> sqrt(X2)
[1.73205, ∞]_dac
```
Since the intervals are unbounded here, the maximum decoration possible is `dac`.

```
julia> X3 = Interval(-3, 4)
[-3, 4]_com

julia> sign(X3)
[-1, 1]_def
```
The `sign` function is discontinuous at 0, but is defined everywhere on the input interval, so the decoration is `def`.

```
julia> X4 = Interval(-3.5, 4.1)
[-3.5, 4.1]_com

julia> sqrt(X4)
[0, 2.02485]_trv
```
The negative part of `X` is discarded by the `sqrt` function, since its domain is `[0,∞]`. (This process of discarding parts of the input interval that are not in the domain is called "loose evaluation".) The fact that this occurred is, however, recorded by the resulting decoration, `trv`, indicating a loss of information: "nothing is known" about the relationship between the output interval and the input.


In this case, we know why the decoration was reduced to `trv`. But if this were just a single step in a longer calculation, a resulting `trv` decoration shows only that something like this happened *at some step*. For example:

```
julia> X5 = Interval(-3, 3)
[-3, 3]_com

julia> asin(sqrt(X5))
[0, 1.5708]_trv

julia> X6 = Interval(0, 3)
[0, 3]_com

julia> asin(sqrt(X6))
[0, 1.5708]_trv
```
In both cases, `asin(sqrt(X))` gives a result with a `trv` decoration, but
we do not know at which step this happened, unless we break down the function into its constituent parts:
```
julia> sqrt(X5)
[0, 1.73206]_trv

julia> sqrt(X6)
[0, 1.73206]_com
```
This shows that loose evaluation occurred in different parts of the expression in the two different cases.

In general, the `trv` decoration is thus used only to signal that "something unexpected" happened during the calculation. Often this is later used to split up the original interval into pieces and reevaluate the function on each piece to refine the information that is obtained about the function.
138 changes: 0 additions & 138 deletions docs/src/manual/decorations.md

This file was deleted.

25 changes: 12 additions & 13 deletions docs/src/manual/usage.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
## Display modes

There are several useful output representations for intervals, some of which we have already touched on. The display is controlled globally by the `setformat` function, which has
the following options, specified by keyword arguments (type `?setformat` to get help at the REPL):
There are several useful output representations for intervals, some of which we have already touched on. The display is controlled globally by the `setdisplay` function, which has
the following options, specified by keyword arguments (type `?setdisplay` to get help at the REPL):

- `format`: interval output format

Expand All @@ -17,17 +17,16 @@ the following options, specified by keyword arguments (type `?setformat` to get

```@repl
using IntervalArithmetic
setformat() # default values
a = interval(1.1, pi)
setformat(; sigdigits = 10)
a = interval(1.1, pi) # default display
setdisplay(; sigdigits = 10)
a
setformat(:full)
setdisplay(:full)
a
setformat(:midpoint)
setdisplay(:midpoint)
a
setformat(; sigdigits = 4)
setdisplay(; sigdigits = 4)
a
setformat(:standard)
setdisplay(:standard)
a
```

Expand All @@ -45,7 +44,7 @@ For example,

```@repl usage
using IntervalArithmetic
setformat(:full)
setdisplay(:full)
X = interval(0, 1)
Y = interval(1, 2)
X + Y
Expand All @@ -61,21 +60,21 @@ X - X

## Elementary functions

The main elementary functions are implemented. The functions for `Interval{Float64}` internally use routines from the correctly-rounded [`CRlibm` library](https://github.com/dpsanders/CRlibm.jl) where possible, i.e. for the following functions defined in that library:
The main elementary functions are implemented. The functions for `Interval{Float64}` internally use routines from the correctly-rounded [CRlibm library](https://github.com/dpsanders/CRlibm.jl) where possible, i.e. for the following functions defined in that library:
- `exp`, `expm1`
- `log`, `log1p`, `log2`, `log10`
- `sin`, `cos`, `tan`
- `asin`, `acos`, `atan`
- `sinh`, `cosh`

Other functions that are implemented for `Interval{Float64}` internally convert
to an `Interval{BigFloat}`, and then use routines from the `MPFR` library
to an `Interval{BigFloat}`, and then use routines from the MPFR library
(`BigFloat` in Julia):
- `^`
- `exp2`, `exp10`
- `atan`, `atanh`

Note, in particular, that in order to obtain correct rounding for the power function (`^`), intervals are converted to and from `BigFloat`; this implies a significant slow-down in this case.
In particular, in order to obtain correct rounding for the power function (`^`), intervals are converted to and from `BigFloat`; this implies a significant slow-down in this case.

For example,

Expand Down
Loading
Loading