@anon is supposed to work this way for you under the hood; it's a bit of a 
puzzle if it doesn't. Can you file an issue, with test case, with 
FastAnonymous?

--Tim

On Monday, July 20, 2015 06:14:24 PM Andrew wrote:
> Update: I've found a significantly cleaner way to do this which avoids
> FastAnonymous entirely and runs faster for me. Now in 0.4 arbitrary objects
> can be overloaded to use the f() syntax using Base.call. I create an
> accessory type for each function that I want to pass to a non-linear solver
> or optimization routine. This accessory type encapsulates the parameters of
> the function, Then I define a new method for Base.call which acts like a
> single-variable function, and simply redirects the parameters stored in my
> type into the function. It looks like this
> 
> function
> hoursFOC(UF::UtilityFunction,hours,state::State{IdioState1,AggState1},
> aprime)
>   w = state.as.w
>   consump = budget_consump_givenhours(state, aprime, hours)
>   w*uc(UF,consump,hours) - ul(UF,consump,hours) # Is w*uc = ul
> end
> 
> immutable pars_hoursFOC{TUF <: UtilityFunction, TIS<:IdioState,
> TAS<:AggState}
>   UF::TUF
>   state::State{TIS,TAS}
>   aprime::Float64
> end
> Base.call(f::pars_hoursFOC, h) = hoursFOC(f.UF, h, f.state, f.aprime)
> 
> When I need the nonlinear equation solver, I do
> 
> f = pars_hoursFOC(UF,state,aprime)
> j = pars_JACOBhoursFOC(UF, state, aprime) # jacobian, same idea
> hours = myNewton(f, j, hoursguess)
> 
> f and j are treated like functions, so this works as expected.
> 
> This is much cleaner than my previous method where I was using @anon to
> store an anonymous function, then passing that function around everywhere.
> Also it's faster for some reason. My new code runs in 14s, the version
> using @anon was about 20s, and a version with nested functions(or regular
> anonymous functions) would be >30s.
> 
> I see mentioned in #8712 <https://github.com/JuliaLang/julia/pull/8712> that
> there may be a Callable type. That would be useful, since currently these
> callable types don't work with the Optim functions or anything else that
> asks for a ::Function argument.
> 
> On Thursday, July 16, 2015 at 9:20:51 PM UTC-4, Andrew wrote:
> > 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