fzero(f, j, guess) works for me when f and j are functions. f(Af, guess) 
works for me now when Af is an @anon function. 

On Tuesday, July 7, 2015 at 7:34:39 PM UTC-4, j verzani wrote:
>
> 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.
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>

Reply via email to