Sum of squares using lambda functions - python

I am thinking of different ways to take the sum of squares in python. I have found that the following works using list comprehensions:
def sum_of_squares(n):
return sum(x ** 2 for x in range(1, n))
But, when using lambda functions, the following does not compute:
def sum_of_squares_lambda(n):
return reduce(lambda x, y: x**2 + y**2, range(1, n))
Why is this?

Think about what reduce does. It takes the output of one call and uses it as the first argument when calling the same function again. So imagine n is 4. Suppose you call your lambda f. Then you are doing f(f(1, 2), 3). That is equivalent to:
(1**2 + 2**2)**2 + 3**2
Because the first argument to your lambda is squared, your first sum of squares will be squared again on the next call, and then that sum will be squared again on the next, and so on.

You're only supposed to square each successive element. x**2 + y**2 squares the running total (x) as well as each successive element (y). Change that to x + y**2 and you'll get the correct result. Note that, as mentioned in comments, this requires a proper initial value as well, so you should pass 0 as the optional third argument.
>>> sum(x ** 2 for x in range(5,15))
985
>>> reduce(lambda x, y: x + y**2, range(5,15))
965
>>> reduce(lambda x, y: x + y**2, range(5,15), 0)
985

Suppose you plug in 4:
1^2 + 2^2 = 5 (you then take this result and put it back in the lambda)
5^2 + 3^2 = 34 (for reference the correct answer is 14)
It squares the "previous" sum as well in the lambda.
(You also have an off by one issue, it should be n+1 in your range calls.)

(for python 3 users)
from functools import reduce
To be able to use reduce.
Second, your function sum_of_squares_lambda won't work the way you expect it to because reduce will take twice (instead of once) every argument except the first and the last one.

Related

Python recursive function definition storage issue

I am trying to get a list of functions defined recursively by storing each step of a math serie:
x^0+x^1+x^2+x^3+... → f0(x)=1, f1(x)=1+x, f2(x)=1+x+x², f3(x)=1+x+x²+x³, ...
I coded this in python:
n = 3
devs = [lambda x: 1]
for k in range(n):
devs.append(lambda x, f=devs[k]: f(x) + x**(k+1))
print(devs[-1](4)) # x=4
I learned in this answer that you need to pass the previous function as default argument in order to solve the maximum recursion depth error, but this outputs 193.
I think it has to do with the k in the default parameter. It seems to calculate: 1+4^3+4^3+4^3=193, or more accurately 1+n*x^n instead of x^0+x^1+...+x^n
Can you please tell me what am I doing wrong here?
I think the same question you linked has the answer to your problem. Because the k inside the function is evaluated only outside the loop, it will have the last value from the loop. You can check the documention for how it works in depth.
The correct code is
n = 4
devs = [lambda x: 1]
for k in range(n):
devs.append(lambda x, f=devs[k], j=k: f(x) + x**(j+1))
One liner just for fun!
n=10
devs = (lambda f:[f] + [f := (lambda x, a=k, g=f: g(x) + x**(a+1)) for k in range(n)])(lambda x:1)

Sum with index as derivative order

I want to define a sum that contains derivatives of a function, where the summation index is the derivative order.
Simple example:
x, i = symbols("x i")
f = Function("f")(x)
Sum(diff(f,x,i), [i,1,3])
However, this only returns a sum of zeros. I assume this is because it tries to differentiate f wrt x first, and then wrt i. Since f is not a function of i, it evaluates to zero before it is processed by the Sum function. What I want to happen is
diff(f,x,1)
diff(f,x,2)
diff(f,x,3)
etc.
Is there a way to make this work?
sympy.diff(f,x,i) is equivalent to i'th order derivative of f only if i is an integer. In your case it is a symbol.
Use instead the builtin sum() along with a generator expression:
>>> sum(diff(f,x,j) for j in range(1,4))
Derivative(f(x), x) + Derivative(f(x), x, x) + Derivative(f(x), x, x, x)

apply a filter to x[n] in python

What's the most clever way to apply a FIR filter in Python to x[n] (for all n <= N)
y[n] = a[0]*x[n] + a[1]*x[n-1] + a[2]*x[n-2] + ... + a[K]*x[n-K]
I know how to do this with a double for loop, but I imagine there are more "beautiful" ways to write it in Python?
You can do:
y[n] = sum(a[k]*x[n-K] for k in xrange(K + 1))
This uses the built-in sum() and xrange functions and a generator expression to compute the final result.
This avoids the use of an index:
y[n] = sum(aa * xx for aa, xx in zip(a, x[n::-1]))
A cool thing about zip is that the length of its output will be the length of the shorter of the two inputs.
To do this for all n, it's probably easiest to use an index for the outer loop:
y = [sum(aa * xx for aa, xx in zip(a, x[n::-1])) for n in xrange(0, len(x))]
You could replace xrange(0, len(x)) with something like xrange(len(a), len(x)) if you want to include only the "valid" terms (terms that use a sum across all coefficients in a).
If this is something you're going to be doing a lot, or doing with large inputs, I would suggest checking out Numpy, specifically its convolve function. That implementation will be much faster than the one I've described here.
For signal processing, you should really make use of NumPy. In particular, filtering a signal will just be convolution, making this a one-liner.

How can I create functions that handle polynomials?

I have these problems about polynomials and I've spent about 4 hours on this, but I just can't get it. I'm new to Python and programming and I've tried working it out on paper, but I just don't know.
Write and test a Python function negate(p) that negates the polynomial represented by the list of its coeffeicients p and returns a new polynomial (represented as a list). In other words, write a function that makes the list of numbers negative.
Write a Python function eval_polynomial(p, x) that returns the value of P(x), where P is the polynomial represented by the list of its coefficients p. For example, eval_polynomial([1, 0, 3], 2) should return 1*2^2 + 0*2 + 3 = 7. Use a single while loop.
Write and test a function multiply_by_one_term(p, a, k) that multiplies a given polynomial p, represented by a list of coefficients, by ax^k and returns the product as a new list.
I would really appreciate it if someone could help me.
I'd recommend using numpy.poly1d and numpy.polymul, where the coefficients are a0*x2 + a1*x + a2.
For example, to represent 3*x**2 + 2*x + 1:
p1 = numpy.poly1d([3,2,1])
And with the resulting poly1d object you can operate using *, / and so on...:
print(p1*p1)
# 4 3 2
#9 x + 12 x + 10 x + 4 x + 1
If you want to build your own functions, assuming that p contains the coefficients in order: a0 + a1*x + a2*x**2 + ...:
def eval_polynomial(p,x):
return sum((a*x**i for i,a in enumerate(p)))
def multiply_by_one_term(p, a, k):
return [0]*k + [a*i for i in p]
Note
My evaluate function uses exponentials, which can be avoided with Horner's rule, as posted in another answer, which is available in Numpy's polyval function
Please use Horner's Method instead!
For polynomials, you should consider Horner's Method. Its main feature is that computing a polynomial of order N requires only N multiplies and N additions -- no exponentials:
def eval_polynomial(P, x):
'''
Compute polynomial P(x) where P is a vector of coefficients, highest
order coefficient at P[0]. Uses Horner's Method.
'''
result = 0
for coeff in P:
result = x * result + coeff
return result
>>> eval_poly([1, 0, 3], 2)
7
You can work through it by hand, or follow the link to see how it works.

Python lambda function

What is happening here?
reduce(lambda x,y: x+y, [x for x in range(1,1000) if x % 3 == 0 or x % 5 == 0])
I understand how x is iterating through all of the numbers from 1 to 999 and taking out those that are divisible by 3 or 5, but the 'lambda x,y: x+y' part is stumping me.
This is bad Python for
sum(x for x in range(1,1000) if x % 3 == 0 or x % 5 == 0)
It simply sums all numbers in the range 1..999 divisible by 3 or 5.
reduce() applies the given function to the first two items of the iterable, then to the result and the next item of the iterable, and so on. In this example, the function
lambda x, y: x + y
simply adds its operands.
saying
f = lambda x, y : x + y
is almost the same as saying
def f(x, y):
return x + y
in other words lambda returns a function that given the parameters to the left of the : sign will return the value of the expression on the right of it.
In respect to a function is however quite limited, for example allows only one expression and no statements are allowed. This is not a serious problem however because in Python you can define a full function even in the middle of another function and pass that instead.
The usage you shown is however quite bad bacause a lambda there is pointless... Python would allow to compute that sum directly instead of using reduce.
Also, by the way, for the result of that computation there is an easy closed-form solution that doesn't require any iteration at all... (hint: the sum of all numbers from 1 to n is n*(n+1)/2 and the sum of all multiples of 5 from 5 to n is 5*(sum of all numbers from 1 to n/5) ... therefore ...)
A lambda designates an anonymous function. The syntax lambda x,y: x+y can be stated in English as "declare a nameless function taking two parameters named x and y. Perform the operation x+y. The return value of this nameless function will by the result of this operation"
reduce applies some function sequentially to the first two elements of a supplied list, then to the result of that function and the third element, and so on. Therefore, the lambda in the supplied code is used by reduce to add together the elements of the supplied list, which will contain all of the multiples of 3 and 5 less than 1000.

Categories