Skip to content

Commit

Permalink
Update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
OlivierHnt committed Nov 18, 2023
1 parent 9c1283e commit 49d6c8e
Show file tree
Hide file tree
Showing 8 changed files with 122 additions and 181 deletions.
1 change: 0 additions & 1 deletion docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ makedocs(;
"Manual" => [
"Constructing intervals" => "manual/construction.md",
"Usage" => "manual/usage.md",
"Decorations" => "manual/decorations.md",
"API" => "manual/api.md"
]
]
Expand Down
16 changes: 0 additions & 16 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +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.
126 changes: 107 additions & 19 deletions docs/src/manual/construction.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
# 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
Expand All @@ -14,31 +12,52 @@ 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.

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`.

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

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.
The submodule `IntervalArithmetic.Symbols` exports the infix operator `..` and `±` as an alias for `interval`.

```@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 +81,72 @@ The various string formats are as follows:
```@repl construction
I"0.1"
```



## More on decorations

```
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.
133 changes: 0 additions & 133 deletions docs/src/manual/decorations.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,136 +3,3 @@ DocTestSetup = quote
using IntervalArithmetic
end
```

# Decorations

Decorations are flags, or labels, attached to intervals to indicate the status of a given interval as the result of evaluating a function on an initial interval. The combination of an interval $X$ and a decoration $d$ is called a decorated interval.

The allowed decorations and their ordering are as follows:
`com` > `dac` > `def` > `trv` > `ill`.

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, nonempty subset of the domain of $f$; $f$ is continuous on the interval $X$; and the resulting interval $f(X)$ is bounded.

- `dac` ("defined & continuous"): $X$ is a nonempty subset of $\mathrm{Dom}(f)$, and $f$ is continuous on $X$.

- `def` ("defined"): $X$ is a nonempty 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"): Not an Interval (an error occurred), e.g. $\mathrm{Dom}(f) = \emptyset$.

An example will be given at the end of this section.

## Initialisation

The simplest way to create a `Interval` is as follows:
```
julia> X = Interval(3, 4)
[3, 4]
```

By default, decorations are not displayed. The following turns on display of decorations:
```
julia> setdisplay(decorations=true)
Display parameters:
- format: standard
- decorations: true
- significant figures: 6
julia> X
[3, 4]_com
```

To parse string, for decorated interval add `_dec` at the end of the string otherwise decoration is determined using `decoration` function.

If no decoration is explicitly specified when a `Interval` is created, then it is initialised with a decoration according to its interval `X`:

- `com`: if `X` is nonempty and bounded;
- `dac` if `X` is unbounded;
- `trv` if `X` is empty.


An explicit decoration may be provided for advanced use:
```
julia> Interval(3, 4, dac)
[3, 4]_dac
julia> Interval(X, def)
[3, 4]_def
```
Here, a new `Interval` was created by extracting the interval from another one and appending a different decoration.

## Action of functions

A decoration is the combination of an interval together with the sequence of functions that it has passed through. Here are some examples:

```
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.

```@meta
DocTestSetup = nothing
```
9 changes: 4 additions & 5 deletions docs/src/manual/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ the following options, specified by keyword arguments (type `?setdisplay` to get

```@repl
using IntervalArithmetic
setdisplay() # default values
a = interval(1.1, pi)
a = interval(1.1, pi) # default display
setdisplay(; sigdigits = 10)
a
setdisplay(:full)
Expand Down Expand Up @@ -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
2 changes: 1 addition & 1 deletion src/intervals/interval_operations/overlap.jl
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ function overlap(a::BareInterval, b::BareInterval)
isempty_interval(a) && return Overlap.first_empty
isempty_interval(b) && return Overlap.second_empty

# States with both intervals nonempty
# States with both intervals non-empty
sup(a) < inf(b) && return Overlap.before
inf(a) != sup(a) && inf(b) != sup(b) && sup(a) == inf(b) && return Overlap.meets
inf(a) < inf(b) && sup(a) < sup(b) && sup(a) > inf(b) && return Overlap.overlaps
Expand Down
4 changes: 2 additions & 2 deletions src/intervals/parsing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@ For more details, see sections 9.7 and 12.11 of the IEEE Standard 1788-2015.
julia> setdisplay(:full);
julia> parse(BareInterval{Float64}, "[1, 2]")
Interval{Float64}(1.0, 2.0)
BareInterval{Float64}(1.0, 2.0)
julia> parse(BareInterval{Float64}, "[1, 2]")
Interval{Float64}(1.0, 2.0)
BareInterval{Float64}(1.0, 2.0)
julia> parse(BareInterval{Float64}, "[1,]")
BareInterval{Float64}(1.0, Inf)
Expand Down
Loading

0 comments on commit 49d6c8e

Please sign in to comment.