[Python-ideas] Reduce/fold and scan with generator expressions and comprehensions

Danilo J. S. Bellini danilo.bellini at gmail.com
Sun Nov 6 17:01:50 EST 2016


2016-11-06 18:00 GMT-02:00 Stephen J. Turnbull <
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/3584de2a/attachment.html>


More information about the Python-ideas mailing list