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

Interval abstract type hierarchy #178

Open
JeffreySarnoff opened this issue Nov 25, 2016 · 16 comments
Open

Interval abstract type hierarchy #178

JeffreySarnoff opened this issue Nov 25, 2016 · 16 comments

Comments

@JeffreySarnoff
Copy link

We need to standardize the way Intervals are typed in the abstract and concrete.
We already agree that the fields for 2-tuple interval are called lo, hi and appear in that order.

ValidatedNumerics now has:

abstract AbstractInterval <: Real
immutable Interval{T<:Real} <: AbstractInterval
    lo :: T
    hi :: T
    # ...
end

There are very useful intervals that do not have Real endpoints (robotics uses DualNumbers and other not simply real valued values .. 3D animation may use Quaternions and there the intervals may be cell/body orientations that exist and are to be interpolated and Complex intervals get a good deal of ink. When I was writing experimental code to investigate the representation and handling of interval-valued information with Julia, it became obvious (to me, then) that there was real power in allowing Julia to handle the specialization and letting us code specialized handling.

We need to let AbstractInterval be less limited. And we do not want to jump from that higher abstraction to some immutable type directly -- that is too coarse a step. So, there should be an intermediate level of abstraction: e.g. one for Reals, and, as/when needed one for Complex, one for DualNumbers ...

I am open to suggestion about the way to form the names. We have at least to possible starts:

abstract AbstractInterval <: Number # or a tuple of 2 or more --but the type system does
                                  # not fully utilize that sort of embedding yet

# one of these or an alternative
abstract AbstractRealInterval{T<:Real} <: AbstractInterval
abstract AbsRealInterval{T<:Real}      <: AbstractInterval
abstract AnyRealInterval{T<:Real}      <: AbstractInterval
abstract RealIntervals{T<:Real}        <: AbstractInterval

# now immutables, the type checking passes through
# idk if there is any time cost to doing it this way -- seems precompile timey, so perhaps not
immutable RealInterval{T} <: AbsRealInterval{T}
     lo::T
     hi::T
     # ....
end
@ChrisRackauckas
Copy link
Contributor

3D animation may use Quaternions and there the intervals may be cell/body orientations that exist and are to be interpolated and Complex intervals get a good deal of ink.

But those aren't strictly intervals because they don't have orderings. They're product spaces of intervals, but not intervals.

robotics uses DualNumbers and other not simply real valued values

DualNumbers subtype the reals.

@JeffreySarnoff
Copy link
Author

JeffreySarnoff commented Nov 25, 2016

I can order Quaternions (I use half of them, that simplifies matters some). The real part of a Dual Number is a subtype of the reals -- it is a real. The dual part of a dual number pulls things into a different algebra, no more real than is a complex number. and Product Space or no -- the type structure and access still works (I know, I have made them and arithmetically combined them).

@ChrisRackauckas
Copy link
Contributor

I can order Quaternions (I use half of them, that simplifies matters some).

You can always put an ordering on them, but the point is there's no canonical ordering.

The real part of a Dual Number is a subtype of the reals -- it is a real. The dual part of a dual number pulls things into a different algebra, no more real than is a complex number.

But in Julia they are subtypes of reals.

@JeffreySarnoff
Copy link
Author

JeffreySarnoff commented Nov 25, 2016 via email

@JeffreySarnoff
Copy link
Author

at the moment:

typealias ReComp Union{Real,Complex}

immutable Dual{T<:ReComp} <: Number
    value::T
    epsilon::T
end

@JeffreySarnoff
Copy link
Author

JeffreySarnoff commented Nov 25, 2016

the complex imaginary part and the dual number's dual part are not isomorphic in any group theoretic sense: imim=-1 dudu=0, as it appears to me. And although I don't remember the purpose, I have seen complex dual numbers. We want to be able to create such things (maybe not that one, but others) by doing something simple like Complex(aDual,bDual) or DualNumber(aComplex,bComplex). That is something at which Julia is very good, as long as we fixup non-identicals.

@lbenet
Copy link
Member

lbenet commented Nov 25, 2016

If I recall correctly, the initial decision to restrict Interval{T} to T<:Reals was related to the "one dimensional" character of the straight forward concept of an interval. One can certainly extended them to the complex numbers, which is actually of interest, but a couple of things has to be reviewed carefully, probably along the lines you suggest (defining other abstract types). For instance, we should only allow certain methods to work with RealIntervals{T}.

As far as combining Interval with other types, the root finding methods we have exploit ForwardDiff. I have also played with TaylorSeries types (Taylor1 specifically) and Intervals with a rather smooth a nice interaction, which is the kind of things we presented at JuliaCon 2016. In that case, working with Taylor1{Interval{T}} is convenient.

@JeffreySarnoff
Copy link
Author

Yes, I understand. By introducing the more specific abstractions, we gain all that fine tuning without having to hard code any refinement beyond the requirements of a given kind of an interval's endpoint domain.

@dpsanders
Copy link
Member

Do you have a specific example of the kind of thing that would be required and is not currently possible? As @lbenet mentioned, you can already make a Dual or a Complex with a (real) Interval inside. Isn't that enough? Admittedly, that does not allow us to use "complex intervals" given by a complex midpoint and a real radius, but in any case that does not fit into the (lo, hi) framework.

I forget why we made Interval a subtype of Real, rather than just of Number. I suppose that to use the Julia promote machinery, all that is actually required is for it to be a subtype of Number?

In any case, I feel like a redesign may need to wait until we have traits in Julia, at which point it will presumably be able to say that "this type behaves like an interval" in a more sensible way.

@dpsanders
Copy link
Member

I tried

abstract AbstractInterval <: Number
abstract AbstractRealInterval{T<:Real} <: AbstractInterval

immutable Interval{T<:Real} <: AbstractRealInterval{T}

which seems to work, except that it breaks using complex intervals in the complex.jl test file!

@JeffreySarnoff
Copy link
Author

The reason to treat fields and domains as abstractly subsumptive and also as concretely integrative is the ease that Julia gives to the next person or, say, CERN group to get a great deal by providing a proscriptive design + a realization that implements little more than the novelty they bring.

I have found, over and over, that there is a steep and often unrelenting real cost (more design complexity aor more time aor more space) that stepping on Julia's constructive desire to work with types that know how to flow about and within one-another. Even when two types are not used one as input to the other, they exert subtle influence in multidispatch through shared or distinguished abstractions. And this is more pronounced with Number types.

The benefits that accompany getting it right -- with v0.6 certainly -- are important. This is how we design our work so that Julia "just works" when tomorrow another group develops an extension / solution / product. There is a causal connection: the more present and coherent is the abstractly typed harmonies of familiar realms of numberness, the less evident are source code page counts; much of what would have been part of getting some elaboration or utilization working cleanly and robustly is already available in a good version of "fall through" to appropriateness-in-handling.

Mixmashing number types, even just enough to stop some reasonable compositing or make less "just go ahead, it will work" some embedding of numerical / geometric types, it always negatively impacts some next work. That really has been my experience. Most of my time on any Julia project has been spent getting to the fifth or sixth rewrite, because something that [at least with v0.6] is so straightforward and simplifying works very well until I want apply the work to a model that is given with Complex or Dual or Quaternion or BoundingBox values. And it kicks because of some deep, unnecessary type missetting that was decided 18 or 30 months ago. And they are almost always resolvable with small adjustments, like an intermediate stage in the abstraction hierarchy or implementing a semantically consistent version of some small Base.function. That only happens with the purveyor's wanting it so.

With traits we will get some important additional organizational character. They are not meant to compete with types, rather to allow shared behavioral qualities to extend multidispatch logic with protodescriptive character. I am looking forward to that, and Protocols. We can make hay with abstractions that create their own level of intelligent scaffolding, too. Still, improving the abstractions we promulgate for numbers is worthwhile. The benefits outweigh the effort -- and, with DualNumbers, Quaternions, and some Geometrical Primitives, when pursued this -- the effort for each was a few days.

@dpsanders dpsanders changed the title We need to standardize common kinds of intervals Interval abstract type hierarchy Dec 9, 2016
@dpsanders
Copy link
Member

I am pretty sure that the correct way to think about complex intervals is e.g.

julia> x = (1..2) + (3..4)im
[1, 2] + [3, 4]*im

julia> typeof(x)
Complex{ValidatedNumerics.Interval{Float64}}

and "dual numbers" as

julia> ForwardDiff.Dual(1..2, 2..3)
Dual([1, 2],[2, 3])

julia> typeof(ans)
ForwardDiff.Dual{1,ValidatedNumerics.Interval{Float64}}

@JeffreySarnoff you are right that any function that expects Intervals will then fail. It is not very clear to me, however, what the solution is.

@JeffreySarnoff
Copy link
Author

JeffreySarnoff commented Feb 13, 2017 via email

@lbenet
Copy link
Member

lbenet commented Feb 13, 2017

I think I understand what you mean as "dual numbers" in this context. But, isn't it already that what is implemented for Complex{T<:Real} in Julia? Or do you want to exploit it in a different way?

@JeffreySarnoff
Copy link
Author

@dpsanders Yes, this is a sticky wicket. When I have run into similar issues, the way I resolved them was to recode the ops I needed using the (often imported) type's structure. That is highly time non-optimal. Really, the type system should support this sort of thing -- and afaik, it would not mind doing so if we gave them a nice approach.

@JeffreySarnoff
Copy link
Author

@lbenet dualnumbers


struct dual{T<:Real} <: Number
  re::T
  epsilon::T
end
# epsilon * epsilon == 0
  

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants