-
Notifications
You must be signed in to change notification settings - Fork 70
Document package design choices #719
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
Draft
Kolaru
wants to merge
7
commits into
JuliaIntervals:master
Choose a base branch
from
Kolaru:document_philosophy
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
691ca5a
Draft philosophy doc
Kolaru 4b0afe3
Address comments
Kolaru a072150
Complete doc and normlize set operations
Kolaru 4faaa41
Fix Documenter problems
Kolaru e98731f
Fixes from Friday's call
Kolaru 09d83c9
Add missing export and functions
Kolaru e19e80c
Add decoration keyword argument to set operations
Kolaru File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
# Philosophy | ||
|
||
The goal of the `Interval` type is to be directly used to replace floating point | ||
number in arbitrary julia code, such that in any calculation, | ||
the resulting intervals are guaranteed to bound the true image of the starting | ||
intervals. | ||
|
||
So, essentially, we would like `Interval` to act as numbers and | ||
the julia ecosystem has evolved to use `Real` as the default supertype | ||
for numerical types that are not complex. | ||
Therefore, to ensure the widest compatiblity, | ||
our `Interval` type must be a subtype of `Real`. | ||
|
||
Then, for any function `f(x::Real)`, | ||
we want the following to hold for all real `x` in the interval `X` | ||
(note that it holds for **all** real numbers in `X`, | ||
even those that can not be represented as floating point numbers): | ||
```math | ||
f(x) \in f(X), \qquad \forall x \in X. | ||
``` | ||
|
||
At first glance, this is reasonable: | ||
all arithmetic operations are well-defined for both real numbers and intervals, | ||
therefore we can use multiple dispatch to define the interval behavior of | ||
operations such has `+`, `/`, `sin` or `log`. | ||
Then a code written for `Real`s can be used as is with `Interval`s. | ||
|
||
However, being a `Real` means way more than just being compatible with | ||
arithmetic operations. | ||
`Real`s are also expected to | ||
|
||
1. Be compatible with any other `Number` through promotion. | ||
2. Support comparison operations, such as `==` or `<`. | ||
3. Act as a container of a single element, | ||
e.g. `collect(x)` returns a 0-dimensional array containing `x`. | ||
|
||
Each of those points lead to specific design choice for `IntervalArithmetic.jl`, | ||
choices that we detail below. | ||
|
||
|
||
## Compatibility with other `Number`s | ||
|
||
In julia it is expected that `1 + 2.2` silently promoted the integer `1` | ||
to a `Float64` to be able to perform the addition. | ||
Following this logic, it means that `0.1 + interval(2.2, 2.3)` should | ||
silently promote `0.1` to an interval. | ||
|
||
However, in this case we can not guarantee that `0.1` is known exactly, | ||
because we do not know how it was produced in the first place. | ||
Following the julia convention is thus in contradiction with providing | ||
guaranteed result. | ||
|
||
In this case, we choose to be mostly silent, | ||
the information that a non-interval of unknown origin is recorded in the `NG` flag, | ||
but the calculation is not interrupted, and no warning is printed. | ||
|
||
For convenience, we provide the [`ExactReal`](@ref) and [`@exact`](@ref) macro | ||
to allow to explicitly mark a number as being exact, | ||
and not produce the `NG` flag when mixed with intervals. | ||
|
||
|
||
## Comparison operators | ||
|
||
We can extend our above definition of the desired behavior for two real numbers | ||
`x` and `y`, and their respective intervals `X` and `Y`. | ||
With this, we want to have, for any function`f`, | ||
for all `x` in `X` and all `y` in `Y`, | ||
``math | ||
f(x, y) \in f(X, Y), \qquad \forall x \in X, y \in Y. | ||
`` | ||
|
||
With this in mind, an operation such as `==` can easily be defined for intervals | ||
|
||
1. If the intervals are disjoints (`X ∩ Y === ∅`), then `X == Y` is `[false]`. | ||
2. If the intervals both contain a single element, | ||
and that element is the same for both, | ||
`X == Y` is `[true]`. | ||
3. Otherwise, we can not conclude anything, and `X == Y` must be `[false, true]`. | ||
|
||
Not that we use intervals in all case, because, according to our definition, | ||
the true result must be contained in the returned interval. | ||
However, this is not convenient, as any `if` statement would error when used | ||
with an interval. | ||
Instead, we have opted to return respectively `false` and `true` | ||
for cases 1 and 2, and to immediately error otherwise. | ||
|
||
In this way, we can return a more informative error, | ||
but we only do it when the result is ambiguous. | ||
|
||
This has a clear cost, however, in that some expected behaviors do not hold. | ||
For example, an `Interval` is not equal to itself. | ||
|
||
```julia> X = interval(1, 2) | ||
[1.0, 2.0]_com | ||
|
||
julia> X == X | ||
ERROR: ArgumentError: `==` is purposely not supported when the intervals are overlapping. See instead `isequal_interval` | ||
Stacktrace: | ||
[1] ==(x::Interval{Float64}, y::Interval{Float64}) | ||
@ IntervalArithmetic C:\Users\Kolaru\.julia\packages\IntervalArithmetic\XjBhk\src\intervals\real_interface.jl:86 | ||
[2] top-level scope | ||
@ REPL[6]:1. | ||
``` | ||
|
||
|
||
## Intervals as sets | ||
|
||
We have taken the perspective to always let `Interval`s act as if they were numbers. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we want to avoid the word "number": " |
||
|
||
But they are also sets of numbers, | ||
and it would be nice to use all set operations defined in julia on them. | ||
|
||
However, `Real` are also sets. For example, the following is valid | ||
|
||
```julia | ||
julia> 3 in 3 | ||
true | ||
``` | ||
|
||
Then what should `3 in interval(2, 6)` do? | ||
|
||
For interval as a set, it is clearly `true`. | ||
But for intervals as a subtype of `Real` this is equivalent to | ||
```julia | ||
3 == interval(2, 6) | ||
``` | ||
which must either be false (they are not the same things), | ||
or error as the result can not be established. | ||
|
||
To be safe, we decided to go one step further and disable | ||
**all** set operations from julia `Base` on intervals. | ||
These operations can instead be performed with the specific `*_interval` function, | ||
for example `in_interval` as a replacement for `in`, | ||
except for `setdiff`. | ||
We can not meaningfully define the set difference of two intervals, | ||
because our intervals are always closed, | ||
while the result of `setdiff` can be open. | ||
|
||
|
||
# Summary | ||
|
||
| | Functions | Behavior | Note | | ||
| :---- | :---- | :---- | :---- | | ||
| Arithmetic operations | `+`, `-`, `*`, `/`, `^` | Interval extension | Produce the `NG` flag when mixed with non-interval | | ||
| Other numeric function | `sin`, `exp`, `sqrt`, etc. | Interval extension | | | ||
| Boolean operations | `==`, `<`, `<=`, `iszero`, `isnan`, `isinteger`, `isfinite` | Error if the result can not be guaranteed to be either `true` or `false` | See [`isequal_interval`](@ref) to test equality of intervals, and [`isbounded`](@ref) to test the finiteness of the elements | | ||
| Set operations | `in`, `issubset`, `isdisjoint`, `issetequal`, `isempty`, `union`, `intersect` | Always error | Use the `*_interval` function instead (e.g. [`in_interval`](@ref)) | ||
| Exceptions | `≈`, `setdiff` | Always error | No meaningful interval extension | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this can be removed. What you wrote above, seems already very clear.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it doesn't hurt to have an example.