Symbolic derivation: - python

I have made a code for performing symbolic derivation in python as below:
import numpy as np
import sympy as sym
# coeffs = [2, 0, 1]
# p = np.poly1d(coeffs[::-1]) # [::-1] because I want to have poly1d reversed
# print(p)
x = sym.Symbol('x')
p = 2 + x ** 2
print(sym.diff(p))
And this one gives me the output 2x which is correct but I want it to give me the output as [0,2]. I would like to define the polynomial as p = [2,0,1] instead of p = 2 + x ** 2 and also have the output on the same formula, ie as a list [0,2] and not 2x. How can I fix this?
Thanks in advance!

Related

plug np.array into sympy expression

I need to subs a numpy.array into an indexed symbol of Sympy expression to numerically calculate the sum. (1+2+3+4+5=15).
My below code still produce symbolic expression. Please help~
from sympy import *
import numpy as np
i = Symbol("i")
y = Symbol("y")
y_ = np.array([1,2,3,4,5])
h = Sum(Indexed("y","i"),(i,0,4))
h.subs([(y,y_)])
smichr answer is solid, however considering that the numerical values of h_ are going to be converted by SymPy to symbolic numbers, the easiest and fastest way is to do this:
new_h = h.subs(y, Array(y_))
# out: Sum([1, 2, 3, 4, 5][i], (i, 0, 4))
# alternatively:
# new_h = h.subs(y, sympify(y_))
new_h.doit()
# out: 15
Another alternative is to convert your symbolic expression to a numerical function with lambdify. However, this approach works as long as the there is not infinity on the bounds of the summation:
f = lambdify([y], h)
f(y_)
# out: 15
Perhaps something like this will work?
>>> y = IndexedBase("y")
>>> h = Sum(y[i],(i,0,4));h.doit()
y[0] + y[1] + y[2] + y[3] + y[4]
>>> _.subs(dict(zip([y[i] for i in range(len(y_))],y_)))
15

How to Insert an Array of Values to a Symbolic Function in Python

I want to study symbolic functions in python. I want to create y(x) = x^2 + 2x + 3 and plot it in the range [1, 255]. I want to use the subs() function to calculate the values by using the for loop. However, when I run that I get this error:
IndexError('list index out of range')
Can you help me please?
import numpy as np
import matplotlib.pyplot as plot
from sympy import *
a = [1,2,3]
x = Symbol('x')
fx = a[0]*x**2 + a[1]*x + a[2]
t = list(range(1,256))
y = np.zeros(256)
for i in t:
y[i] = fx.subs({x:t[i]})
plot.plot(t,y)
plot.show()
Just replace with the following lines:
y = np.zeros(len(t))
for i in range(len(t)):
y[i] = fx.subs({x:t[i]})
The problem was that the length of t was only 255 but the len of y was 256 in your code because you define y = np.zeros(256), hence the Index Error because there is no t[256]. I am using y = np.zeros(len(t)) because you have as many y points as t (or x) points. By the way, you are most likely to get an error in your plot command the way it is right now because you have called import matplotlib.pyplot as plot. I would simply call it plt instead of plot
Output

ask for help for a sum (sigma) function

need help to calculate this:
so, the total number of y is equal to number of x, and each y is calculated with one x and several a.
My code list below, it gives the correct results for a0. what is a simple way to calculate this? maybe a different version can also verify the results.
Thanks a lot.
import numpy as np
import matplotlib.pyplot as plt
a = np.array([1,2,3,4],float) # here we can give several a
b = np.asarray(list(enumerate(a)))
x = np.linspace(0.0,1.0,10)
y1 = []
for r in x:
y1.append(np.exp(np.sum((1-r)**2*a*((2*b[:,0]+1)*r-1+r)*(r-1+r)**(b[:,0]-1))))
y1=np.asarray(y1)
You can write almost literally the same in numpy:
def f(x, a):
x, a = np.asanyarray(x), np.asanyarray(a)
x = x[:, None] # create new dimension to sum along
i = np.arange(len(a)) # create counter
return np.sum((1-x)**2 * a * ((2*i + 1) * x - (1-x)) * (x - (1-x))**(i-1), axis=-1)
As a side note: there are obvious algebraic simplifications you could take advantage of.

How does theano's scan function work?

Look at this code:
import theano
import numpy
import theano.tensor as T
import numpy as np
x = T.dvector('x')
y = T.dvector('y')
def fun(x,a):
return x+a
results, updates = theano.scan(fn=fun,sequences=dict(input=x), outputs_info=dict(initial=y, taps=[-3]))
h = [10.,20,30,40,50,60,70]
f = theano.function([x, y], results)
g = theano.function([y], y)
print(f([1],h))
I have changed outputs_info'taps to -2,-3,and so on, but the the result of code is the same [11.0], I can't understand. Somebody can explain it?
Another question.
import theano
import numpy
import theano.tensor as T
import numpy as np
x = T.dvector('x')
y = T.dvector('y')
def fun(x,a,b):
return x+a+b
results, updates = theano.scan(fn=fun,sequences=dict(input=x), outputs_info=dict(initial=y, taps=[-5,-3]))
h = [10.,20,30,40,50,60,70]
f = theano.function([x, y], results)
g = theano.function([y], y)
print(f([1,2,3,4],h))
The output is [41,62,83,85], how does 85 come?
Consider this variation on your code:
x = T.dvector('x')
y = T.dvector('y')
def fun(x,a,b):
return x+b
results, updates = theano.scan(
fn=fun,
sequences=dict(input=x),
outputs_info=dict(initial=y, taps=[-5,-3])
)
h = [10.,20,30,40,50,60,70]
f = theano.function([x, y], results)
g = theano.function([y], y)
print(f([1],h))
Your result will be 31.
Change taps to [-5, -2] and your result changes to 41.
Change taps to [-4, -3] and your result changes to 21.
This demonstrates how things are working:
The largest negative number in taps is treated as h[0]
All other taps are offset from that
So when taps is [-5,-2] fun inputs a and b = 10 and 40 respectively.
Update for new question
taps actually indicates that the the function at time t depends on the output of the function at time t - taps.
For instance, the Fibonacci sequence is defined by the function
Here's how you'd implement the Fibonacci sequence with theano.scan:
x = T.ivector('x')
y = T.ivector('y')
def fibonacci(x,a,b):
return a+b
results, _ = theano.scan(
fn=fibonacci,
sequences=dict(input=x),
outputs_info=dict(initial=y, taps=[-2,-1])
)
h = [1,1]
f = theano.function([x, y], results)
print(np.append(h, f(range(10),h)))
However, theano.scan has a problem. If the function depends on prior output, what do you use as the prior output for the first iteration?
The answer is the initial input, h in your case. But in your case h is longer than you need it to be, you only need it to be 5 elements long (because the largest taps is -5 in your case). After using the required 5 elements of h, your function switches over to the actual output from your function.
Here's a simplified trace of what's happening in your code:
output[0] = x[0] + h[0] + h[2] = 41
output[1] = x[1] + h[1] + h[3] = 62
output[2] = x[2] + h[2] + h[4] = 83
output[3] = x[3] + h[3] + output[0] = 85
You'll see, at time = 4, we have an output from the function for time 4-3, and that output is 41. And since we have that output, we need to use it, because the function is defined as using prior outputs. So we just ignore the rest of h.

numpy.poly1d , root-finding optimization, shifting polynom on x-axis

it is commonly an easy task to build an n-th order polynomial
and find the roots with numpy:
import numpy
f = numpy.poly1d([1,2,3])
print numpy.roots(f)
array([-1.+1.41421356j, -1.-1.41421356j])
However, suppose you want a polynomial of type:
f(x) = a*(x-x0)**0 + b(x-x0)**1 + ... + n(x-x0)**n
Is there a simple way to construct a numpy.poly1d type function
and find the roots ? I've tried scipy.fsolve but it is very unstable as it depends highly on the choice of the starting values
in my particular case.
Thanks in advance
Best Regards
rrrak
EDIT: Changed "polygon"(wrong) to "polynomial"(correct)
First of all, surely you mean polynomial, not polygon?
In terms of providing an answer, are you using the same value of "x0" in all the terms? If so, let y = x - x0, solve for y and get x using x = y + x0.
You could even wrap it in a lambda function if you want. Say, you want to represent
f(x) = 1 + 3(x-1) + (x-1)**2
Then,
>>> g = numpy.poly1d([1,3,1])
>>> f = lambda x:g(x-1)
>>> f(0.0)
-1.0
The roots of f are given by:
f.roots = numpy.roots(g) + 1
In case x0 are different by power, such as:
f(x) = 3*(x-0)**0 + 2*(x-2)**1 + 3*(x-1)**2 + 2*(x-2)**3
You can use polynomial operation to calculate the finally expanded polynomial:
import numpy as np
import operator
ks = [3,2,3,2]
offsets = [0,2,1,2]
p = reduce(operator.add, [np.poly1d([1, -x0])**i * c for i, (c, x0) in enumerate(zip(ks, offsets))])
print p
The result is:
3 2
2 x - 9 x + 20 x - 14

Categories

Resources