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? >>>>>>>> >>>>>>>
