Okay, this just got fixed as much as I could with v"0.1.15" (there is no
fzero(f,j,guess) signature).
On Tuesday, July 7, 2015 at 4:38:41 PM UTC-4, Andrew wrote:
>
> Just checked. So, Roots.fzero(f, guess) does work. However,
> Roots.fzero(f, j, guess) doesn't work, and neither does Roots.newton(f, j,
> guess).
>
> I looked at the Roots.jl source and I see ::Function annotations on the
> methods with the jacobian, but not the regular one.
>
> On Tuesday, July 7, 2015 at 4:22:17 PM UTC-4, j verzani wrote:
>>
>> It isn't your first choice, but `Roots.fzero` can have `@anon` functions
>> passed to it, unless I forgot to tag a new version after making that change
>> on master not so long ago.
>>
>> On Tuesday, July 7, 2015 at 2:29:51 PM UTC-4, Andrew wrote:
>>>
>>> I'm writing this in case other people are trying to do the same thing
>>> I've done, and also to see if anyone has any suggestions.
>>>
>>> Recently I have been writing some code that requires solving lots(tens
>>> of thousands) of simple non-linear equations. The application is economics,
>>> I am solving an intratemporal first order condition for optimal labor
>>> supply given the state and a savings decision. This requires solving the
>>> same equation many times, but with different parameters.
>>>
>>> As far as I know, the standard ways to do this are to either define a
>>> nested function which by the lexical scoping rules inherits the parameters
>>> of the outer function, or use an anonymous function. Both these methods are
>>> slow right now because Julia can't inline those functions. However, the
>>> FastAnonymous package lets you define an anonymous "function", which
>>> behaves exactly like a function but isn't type ::Function, which is fast.
>>> Crucially for me, in Julia 0.4 you can modify the parameters of the
>>> function you get out of FastAnonymous. I rewrote some code I had which
>>> depended on solving a lot of non-linear equations, and it's now 3 times as
>>> fast, running in 2s instead of 6s.
>>>
>>> Here I'll describe a simplified version of my setup and point out a few
>>> issues.
>>>
>>> 1. I store the anonymous function in a type that I will pass along to
>>> the function which needs to solve the nonlinear equation. I use a
>>> parametric type here since the type of an anonymous function seems to vary
>>> with every instance. For example,
>>>
>>> typeof(UF.fhoursFOC)
>>> FastAnonymous.##Closure#11431{Ptr{Void}
>>> @0x00007f2c2eb26e30,0x10e636ff02d85766,(:h,)}
>>>
>>>
>>> To construct the type,
>>>
>>> immutable CRRA_labor{T1, T2} <: LaborChoice # <: means "subtype of"
>>> sigmac::Float64
>>> sigmal::Float64
>>> psi::Float64
>>> hoursmax::Float64
>>> state::State # Encodes info on how to solve itself
>>> fhoursFOC::T1
>>> fJACOBhoursFOC::T2
>>> end
>>>
>>> To set up the anonymous functions fhoursFOC and fJACOBhoursFOC (the
>>> jacobian), I define a constructor
>>>
>>> function CRRA_labor(sigmac,sigmal,psi,hoursmax,state)
>>> fhoursFOC = @anon h -> hoursFOC(CRRA_labor(sigmac,sigmal,psi,
>>> hoursmax,state,0., 0.) , h, state)
>>> fJACOBhoursFOC = @anon jh -> JACOBhoursFOC(CRRA_labor(sigmac,sigmal,
>>> psi,hoursmax,state,0., 0.) , jh, state)
>>> CRRA_labor(sigmac,sigmal,psi,hoursmax,state,fhoursFOC,
>>> fJACOBhoursFOC)
>>> end
>>>
>>> This looks a bit complicated because the nonlinear equation I need to
>>> solve, hoursFOC, relies on the type CRRA_labor, as well as some aggregate
>>> and idiosyncratic state info, to set up the problem. To encode this
>>> information, I define a dummy instance of CRRA_labor, where I supply 0's in
>>> place of the anonymous functions. I tried to make a self-referential type
>>> here as described in the documentation, but I couldn't get it to work, so I
>>> went with the dummy instance instead.
>>>
>>> @anon sets up the anonymous function. This means that code like
>>> fhoursFOC(0.5) will return a value.
>>>
>>> 2. Now that I have my anonymous function taking only 1 variable, I can
>>> use the nonlinear equation solver. Unfortunately, the existing nonlinear
>>> equation solvers like Roots.fzero and NLsolve ask the argument to be of
>>> type ::Function. Since anonymous functions work like functions but are
>>> actually some different type, they wouldn't accept my argument. Instead, I
>>> wrote my own Newton method, which is like 5 lines of code, where I don't
>>> restrict the argument type.
>>>
>>> I think it would be very straightforward to make this a multivariate
>>> Newton method.
>>>
>>> function myNewton(f, j, x)
>>> for n = 1:100
>>> fx , jx = f(x), j(x)
>>> abs(fx) < 1e-6 && return x
>>> d = fx/jx
>>> x = x - d
>>> end
>>> println("Too many iterations")
>>> return NaN
>>> end
>>>
>>> 3. The useful thing here in 0.4 is that you can edit the parameters of
>>> the anonymous function. The parameters are encoded in a custom type
>>> state::State, and I update the state. Then I call my nonlinear equation
>>> solver
>>>
>>> UF.fhoursFOC.state, UF.fJACOBhoursFOC.state = state, state
>>> f = UF.fhoursFOC
>>> j = UF.fJACOBhoursFOC
>>> hours = myNewton(f, j, hoursguess)
>>>
>>> This runs much faster than my old version which used NLsolve, which
>>> itself ran faster than a version using Roots.fzero.
>>>
>>> Issues:
>>>
>>> 1. Since the type of the anonymous function isn't ::Function, I had to
>>> write my own solver. I'm pretty sure a 1-line edit to Roots.fzero where I
>>> just remove the ::Function type annotation would let it work there, but I'm
>>> not aware of another workaround.
>>>
>>> 2. I would rather use NLsolve, which uses in-place updating of its
>>> arguments ( f!(input::Array, output::Array) ), but I've tried constructing
>>> an anonymous function that does that, and @anon didn't work. Perhaps there
>>> is a workaround.
>>>
>>> 3. Since I'm using an anonymous function, I have to explicitly pass it
>>> around. Encoding it into the type CRRA_labor wasn't really hard though.
>>>
>>>
>>>
>>>
>>>
>>>
>>>