Ah ok, thanks.

As far as I can tell @anon is doing what it's supposed to do, and there's 
nothing to fix. My approach just has me specifying the contents of the 
built type explicitly, while @anon tries to automatically figure that out 
for you. I think this is more convenient for my purposes. Also, I'm using 
an immutable and @anon makes a mutable type. 

On Tuesday, July 21, 2015 at 6:32:28 AM UTC-4, Tim Holy wrote:
>
> @anon builds a type for you, creates a field called w, and defines call() 
> for 
> that type. IF you're running julia 0.4, that is. 
>
> My point was simply, as a busy person I haven't read this long email chain 
> through and might forget about it. If there's something you want fixed, 
> best to 
> file an issue with the appropriate package, with a test case that 
> illustrates 
> the problem you're having. 
>
> Best, 
> --Tim 
>
> On Monday, July 20, 2015 09:57:24 PM Andrew wrote: 
> > I'm not quite sure what you mean. It looks like I could sort of 
> replicate 
> > my approach using @anon by just defining an @anon function right below 
> my 
> > initial function definition. Then I can use the @anon version elsewhere. 
> > For example, 
> > function FOC(x,w) 
> >  return x*w 
> > end 
> > p_FOC = @anon x -> FOC(x,w) # maybe I should say const p_FOC for 
> > performance of global variables? 
> > 
> > 
> > But this doesn't work because I haven't defined w anywhere. It would 
> work 
> > if I set a dummy value for w, like w = 5., but that looks sort of odd. 
> It 
> > would basically come down to what I'm doing above anyway. 
> > 
> > Is that what you meant? 
> > 
> > On Monday, July 20, 2015 at 10:01:12 PM UTC-4, Tim Holy wrote: 
> > > @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