I'd say this is a bug.  `sin(5)` works, so `ode23(f, 0, [0,1])` should
work too by promoting `y0=0` and `tspan=[0,1]` to appropriate types.
Note that `eltype(tspan)` needs to be promoted to some kind of floating
point number; I don't think rationals make sense for
differential-equations.  I pushed a fix, at least for the Runge-Kutta
solvers of ODE.jl: https://github.com/JuliaLang/ODE.jl/pull/96

On Mon, 2016-06-20 at 07:09, Gabriel Gellner <[email protected]> wrote:
> Fair enough. I guess if the urge is to support strangely generic code then
> the inputs should never be expected to be promoted. But I just don't see
> what you are describing as being a "standard" in Julia. ODE.jl and your
> project maybe try to attain this level of genericity, but most of Base
> seems to do this kind of promotion, and doesn't always return the types, or
> give an inexact error, when you provide certain inputs (like returning
> Rational if you input Rational). Optim.jl, Roots.jl, Disributions.jl
> doesn't do this, quadgk doesn't give back rationals, etc. The standard
> libraries I use the most often I guess.
>
> A user that is told that type in type out is the standard in Julia, and
> that strange error messages like the OP had are not bugs, would have great
> reason to be skeptical that this is actually a contract that is commonly
> followed. Maybe this is the way Julia is going. I hope that doing the
> common case will never get too annoying (like throwing a type error so I
> can have the unlikely case that I an use Rational inputs for an ode solver
> ;), and that all my code would be expected to be filled with eltypes and
> inexact errors. We shall see.
>
> On Sunday, June 19, 2016 at 7:32:55 PM UTC-7, Chris Rackauckas wrote:
>>
>> But I gave an example where the output type can change depending on the
>> chosen timespan (eltype(y0)==Rational{Int}), so "eltype(f(y0))" can really
>> only be what the time integration algorithm actually produces, which means
>> you have to just run it and see what happens. It becomes a type-stability
>> issue because the internals of the functions are using similar(y0) to make
>> all the arrays (well, with some promotions before doing so), and so each
>> time you go through the loop you're banking on getting the same type. The
>> other way to handle this would be to make the arrays something like a Float
>> which just always kind of work, so this "bug" was likely introduced when
>> the integrator were upgraded to allow for output to be any type (That's
>> what introduced this issue in DifferentialEquations.jl, so I assume that's
>> what happened in ODE.jl as well).
>>
>> The examples you gave are cases where the output is set (Int/Int returns
>> on Float no matter what), or where the type promotion isn't too difficult
>> (quadgtk is a linear combination of values from a to b, so just check the
>> element type of the intermediate values that you're using and promote
>> everything to that). But if you don't want to do the first, and you're
>> dealing with a case where type inference is essentially undecidable, you
>> will have this issue.
>>
>> That said, using the heuristic of "eltype(f(y0))" will do better than it
>> currently does (it would catch the case where all inputs are an Int but one
>> application makes things floats, which is probably the most common problem).
>>
>> On Monday, June 20, 2016 at 3:13:44 AM UTC+1, Gabriel Gellner wrote:
>>>
>>> I will admit my understanding of type stability in a jit compiler is
>>> shakey, but I don't see 0.5//2 as a type instability, rather it is a method
>>> error (the issues is a float does not convert to an int, but having a int
>>> become a float is a fair promotion, so I can't see why requiring y0 to be a
>>> float is at all similar -- it is very Julian to promote it). I understand
>>> type instability to mean that the output of function is not uniquely
>>> determined by its inputs. In this sense there is no type instability. The
>>> issue as I understand it is that we do eltype(y0) for the output type, when
>>> maybe it makes more sense to do eltype(f(y0)) which would then be type
>>> stable, since f is. This would even work if you did y0 = 3f0, etc.
>>>
>>> Again I could be missing something simple, but requiring the inputs
>>> to agree with the output of the input function feels like something far
>>> beyond any kind of Julia difference from other languages, and more a
>>> feature of it being a dynamic language and not purely static. Suggesting
>>> users, especially new users, to be worry about these situations doesn't
>>> jive with my understanding of Julia. It feels like premature optimization
>>> to me.
>>>
>>>
>>> On Sunday, June 19, 2016 at 6:38:37 PM UTC-7, Chris Rackauckas wrote:
>>>
>>>> I mean, it's the same type instability that you get if you try things
>>>> like .5//2. Many Julia function work with ints that give a float, but not
>>>> all do. If any function doesn't work (like convert will always fail if you
>>>> somehow got a float but initialized an array to be similar(arrInt)), then
>>>> you get this error.
>>>>
>>>> This can be probably be masked a little by pre-processing. I know that
>>>> ODE.jl makes the types compatible to start, but that doesn't mean they will
>>>> be after one step. For example, run an Euler step with try-catch and then
>>>> have it up the types to whatever is compatible, then solve the ODE. And
>>>> this has almost no performance penalty in most cases (and would be easy to
>>>> switch off). But I don't know if this goes into a low level "this uses this
>>>> method to solve the ODE" that ODE.jl implements. But even if you do this,
>>>> you won't catch all of the type errors. For example, if you want to use
>>>> Rational{Int}, it can take quite a few steps to overflow the numerator or
>>>> denominator, but once it does, you get an InexactError (and the solution is
>>>> to use Rational{BigInt}).
>>>>
>>>> You can use some try-catch phrases in the main solver, or put the solver
>>>> in a try-catch and have it fix types and re-run, but these are all things
>>>> that would be non-intuitive behavior and would have to be off by default.
>>>> But at that point, the user would probably know to just fix the type
>>>> problem.
>>>>
>>>> So honestly I don't think that there's a good way to make this "silent".
>>>> But this is the fundamental trade off in Julia that makes it fast, and it's
>>>> not something that is just encountered here, so users will need to learn
>>>> about it pretty quick or else they will see lots of other
>>>> functions/packages break.
>>>>
>>>> On Monday, June 20, 2016 at 2:07:30 AM UTC+1, Gabriel Gellner wrote:
>>>>>
>>>>> Is this truly a type instability?
>>>>>
>>>>> The function f has no type stability issues from my understanding of
>>>>> the concept. No matter the input types you always get a Float output so
>>>>> there is no type instability. Many of Julia's functions work this way,
>>>>> including division 1/2 -> float even though the inputs are ints.
>>>>>
>>>>> The real issue is that ode23 infers the type of the output from y0
>>>>> which in this case is an int, but I don't see how this is the correct
>>>>> inference. Maybe it is desired, but I hardly see this as normal Julia
>>>>> behavior. I can happily mix input types to arguments in many Julia
>>>>> constructs, without forcing me to have to use the same input vs output
>>>>> type. matrix mult, sin, sqrt, etc etc. Isn't this exactly what convert
>>>>> functions are for?
>>>>>
>>>>> hell the developer docs say that literals in expressions should be ints
>>>>> so that conversions can be better. that is they say I should right 2*x not
>>>>> 2.0*x so that type promotions can work correctly. The issue in this case 
>>>>> is
>>>>> that an implementation detail is being exposed to the user, that 
>>>>> eltype(y0)
>>>>> is determining the output of the function. I don't see that this is
>>>>> standard Julian practice, though it might be desired in this case. For
>>>>> example I can use quadgk(f, 1, 2) and not have an error because of the
>>>>> integer a, b. And that is a very similar style function Base method.
>>>>>
>>>>> Maybe I am missing something simple, but I worry being to harsh about
>>>>> types when it feels unessary.
>>>>>
>>>>>
>>>>> On Sunday, June 19, 2016 at 5:28:39 PM UTC-7, Chris Rackauckas wrote:
>>>>>
>>>>>> I wouldn't call this a bug, it's a standard Julia thing for a reason.
>>>>>> You get an InexactError() because you start with an Int and you do an
>>>>>> operation which turns the Int into a Float so the program gets mad at the
>>>>>> type instability. You can just change everything to floats, but then 
>>>>>> you're
>>>>>> getting rid of the user choice. For example, if you change everything to
>>>>>> floats, you can't solve it all using rationals of BigInts or whatever 
>>>>>> crazy
>>>>>> numbers the user wants. However, if you let the number operations do as
>>>>>> they normally do, the user can get an answer in the same way that they
>>>>>> provide it. And it's not like this is a weird thing inside some
>>>>>> mathematical packages, this is normal Julia behavior.
>>>>>>
>>>>>> But this kind of thing will cause issues for first-timers in Julia. It
>>>>>> should be front and center in the Noteworthy Differences from Other
>>>>>> Languages that if you really want a float, start with a float.
>>>>>>
>>>>>> On Sunday, June 19, 2016 at 10:06:42 PM UTC+1, Gabriel Gellner wrote:
>>>>>>>
>>>>>>> You are passing in the initial condition `start` as an integer, but
>>>>>>> ode23 needs this to be a float. Change it to `const start = 3.0` and you
>>>>>>> are golden. This does feel like a bug you should file an issue at the
>>>>>>> github page.
>>>>>>>
>>>>>>> On Sunday, June 19, 2016 at 11:49:55 AM UTC-7, Joungmin Lee wrote:
>>>>>>>>
>>>>>>>> Hi,
>>>>>>>>
>>>>>>>> I am making simple examples of the ODE package in Julia, but I
>>>>>>>> cannot make a code without error for 1st order ODE.
>>>>>>>>
>>>>>>>> Here is my code:
>>>>>>>>
>>>>>>>> using ODE;
>>>>>>>>>
>>>>>>>>> function f(t, y)
>>>>>>>>>     x = y
>>>>>>>>>
>>>>>>>>>     dx_dt = (2-x)/5
>>>>>>>>>
>>>>>>>>>     dx_dt
>>>>>>>>> end
>>>>>>>>>
>>>>>>>>> const start = 3;
>>>>>>>>> time = 0:0.1:30;
>>>>>>>>>
>>>>>>>>> t, y = ode23(f, start, time);
>>>>>>>>>
>>>>>>>>
>>>>>>>> It finally gives:
>>>>>>>> LoadError: InexactError()
>>>>>>>> while loading In[14], in expression starting on line 1
>>>>>>>>
>>>>>>>> in copy! at abstractarray.jl:310
>>>>>>>> in setindex! at array.jl:313
>>>>>>>> in oderk_adapt at
>>>>>>>> C:\Users\user\.julia\v0.4\ODE\src\runge_kutta.jl:279
>>>>>>>> in oderk_adapt at
>>>>>>>> C:\Users\user\.julia\v0.4\ODE\src\runge_kutta.jl:220
>>>>>>>> in ode23 at C:\Users\user\.julia\v0.4\ODE\src\runge_kutta.jl:210
>>>>>>>>
>>>>>>>> The example of 2nd order ODE at the GitHub works fine.
>>>>>>>>
>>>>>>>> How should I edit the code?
>>>>>>>>
>>>>>>>

Reply via email to