[Python-ideas] Reduce/fold and scan with generator expressions and comprehensions
Wes Turner
wes.turner at gmail.com
Sun Nov 6 20:27:35 EST 2016
- So, IIUC, for recursive list comprehensions
- "prev" = x_(n-1)
- there is a need to define an initial value
- chain([1000], [...])
- sometimes, we actually need window function
- __[0] = x_(n-1)
- __[1] = x_(n-2) # this
- __[-1] = x_(n-2) # or this
- this can be accomplished with dequeue
- __= dequeue([1000], maxlen)
- for recursive list comprehensions, we'd want to bind e.g. __ to a
dequeue
[f(__[0], x) for x in y with __ = dequeue((1000,), 1)]
But the proposed syntax differs from this interpretation:
- "from bal = 1000" # ~= with prev = dequeue((1000,), 1)[-1]
(Recursive) fibonacci would then require a dequeue (..., 2)
Other than brevity, is there any advantage to list comprehensions over a
for loop?
- IIRC, reduce() and fold() can avoid unnecessary variable binding, but
require lower-level debugging.
A recursive list comprehension syntax would be cool. Is there a better
variable name than '__'?
On Sunday, November 6, 2016, Danilo J. S. Bellini <danilo.bellini at gmail.com>
wrote:
> 2016-11-06 18:00 GMT-02:00 Stephen J. Turnbull <turnbull.stephen.fw at u.
> tsukuba.ac.jp
> <javascript:_e(%7B%7D,'cvml','turnbull.stephen.fw at u.tsukuba.ac.jp');>>:
>
>> Danilo J. S. Bellini writes:
>>
>> > About the effort, do you really find the examples below with the new
>> > proposed syntax difficult to understand?
>>
>> No. I just don't see how they would become tools I would use. My main
>> interest here was in your claim to have economic applications, but the
>> examples you give don't seem to offer big wins for the kind of
>> calculations I, my students, or my colleagues do. Perhaps you will
>> have better luck interesting/persuading others.
>>
>
> If you want something simple, the itertools.accumulate examples from
> docs.python.org include a simple "loan amortization" example:
>
> >>> # Amortize a 5% loan of 1000 with 4 annual payments of 90
> >>> cashflows = [1000, -90, -90, -90, -90]
> >>> list(accumulate(cashflows, lambda bal, pmt: bal*1.05 + pmt))
> [1000, 960.0, 918.0, 873.9000000000001, 827.5950000000001]
>
> >>> # With the proposed syntax
> >>> payments = [90, 90, 90, 90]
> >>> [bal * 1.05 - pmt for pmt in payments from bal = 1000]
> [1000, 960.0, 918.0, 873.9000000000001, 827.5950000000001]
>
>
> From the Wilson J. Rugh "Linear Systems Theory" book, chapter 20 "Discrete
> Time State Equations", p. 384-385 (the very first example on the topic):
>
> """
> A simple, classical model in economics for national income y(k) in year k
> describes y(k) in terms of consumer expenditure c(k), private investment
> i(k), and government expenditure g(k) according to:
>
> y(k) = c(k) + i(k) + g(k)
>
> These quantities are interrelated by the following assumptions. First,
> consumer expenditure in year k+1 is proportional to the national income in
> year k,
>
> c(k+1) = α·y(k)
>
> where the constant α is called, impressively enough, the marginal
> propensity to consume. Second, the private investment in year k+1 is
> proportional to the increase in consumer expenditure from year k to year
> k+1,
>
> i(k+1) = β·[c(k+1) - c(k)]
>
> where the constant β is a growth coefficient. Typically 0 < α < 1 and β >
> 0.
>
> From these assumptions we can write the two scalar difference equations
>
> c(k+1) = α·c(k) + α·i(k) + α·g(k)
> i(k+1) = (β·α-β)·c(k) + β·α·i(k) + β·α·g(k)
>
> Defining state variables as x₁(k) = c(k) and x₂(k) = i(k), the output as
> y(k), and the input as g(k), we obtain the linear state equation
>
> # ⎡ α α ⎤ ⎡ α ⎤
> # x(k+1) = ⎢ ⎥·x(k) + ⎢ ⎥·g(k)
> # ⎣β·(α-1) β·α⎦ ⎣β·α⎦
> #
> # y(k) = [1 1]·x(k) + g(k)
>
> Numbering the years by k = 0, 1, ..., the initial state is provided by
> c(0) and i(0).
> """
>
> You can use my "ltiss" or "ltvss" (if alpha/beta are time varying)
> functions from the PyScanPrev state-space example to simulate that, or some
> dedicated function. The linear time varying version with the proposed
> syntax would be (assuming alpha, beta and g are sequences like
> lists/tuples):
>
> >>> from numpy import mat
> >>> def first_digital_linear_system_example_in_book(alpha, beta, c0, i0,
> g):
> ... A = (mat([[a, a ],
> ... [b*(a-1), b*a]]) for a, b in zip(alpha, beta))
> ... B = (mat([[a ],
> ... [b*a]]) for a, b in zip(alpha, beta))
> ... x0 = mat([[c0],
> ... [i0]])
> ... x = (Ak*xk + Bk*gk for Ak, Bk, gk in zip(A, B, g) from xk = x0)
> ... return [xk.sum() + gk for xk, gk in zip(x, g)]
>
> If A and B were constants, it's simpler, as the scan line would be:
>
> x = (A*xk + B*gk for gk in g from xk = x0)
>
> --
> Danilo J. S. Bellini
> ---------------
> "*It is not our business to set up prohibitions, but to arrive at
> conventions.*" (R. Carnap)
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20161106/2cd26bab/attachment-0001.html>
More information about the Python-ideas
mailing list