jstac/quant-econ — pull request #41 by spencerlyon2 (2014-08-04 21:42:26+00:00)
Title: ENH: moved the lucas_tree tuple to a new LucasTree class

Updated examples and solutions to match change

We had a `lucas_tree`named tuple and a function `compute_lt_price` in the file originally. This pull request moved to a `LucasTree` class with a `compute_lt_price` method. There are a few reasons for this:

* Inside the original `compute_lt_price` function, we were defining two nested functions. When trying to write tests for this module I was unable to access those functions to test them. Having `integrate` and `lucas_operator` be methods of the class instead of nested functions defined within `compute_lt_price` allows me to test them.
* The current version uses our `compute_fixed_point` function like all of the other function iteration algorithms in the QuantEcon library do. This makes this code mesh much better with the rest of QuantEcon.
* Another point here is that the value function iteration we were doing was pretty much a copy paste from `compute_fixed_point`. Eventually we will want to speed up that algorithm with numba or cython and only having to do it in one place makes that change easier.
* It felt a bit awkward to use a named tuple here, when we needed to define various nested functions using attributes of that tuple. It made more sense to have them be methods/class attributes instead.

---

I also made a couple minor changes to `compute_fixed_point`:

1. i added `*args` and `**kwargs` to `compute_fixed_point` that I pass directly on to the `T` argument of that function. This enables the user to pass arbitrary positional and keyword arguments on to their `T` mapping
2. I changed the line `v = new_v` at the end of the iteration to read `v[:] = new_v`. This change is subtle, but coupled with the ability to pass arbitrary arguments on to the `T` function allows us to run this whole algorithm without allocating any memory. This results in more efficient code. (without the `[:]` python interprets that line as make v point to the same memory as `new_v`. If we pass a kwarg that specifies the output of the `T` operator (to avoid allocating in within `T`), then after the first iteration `v` and `new_v` will point to the same memory address and effectively be the exact same variable. This means when we check the error, it will be `0.0` on the second iteration. With the `[:]` python interprets the line as 'fill the memory held by `v` with the values from `new_v` -- so we avoid the problem just described)

As a follow up to point 2 I have opened #40 so that we can update our other fixed point algorithms to use the allocation-free method. Some of those routines are quite slow and this could be a very easy potential speedup.