Use index of summation as the order of derivation - python

Given some function f, I want to compute the following sum using sympy:
In general I want to use the index of summation as the order of differentiation of the function but I could not find out how to do it with sympy.

Given n is an int you know in advance, you can construct a function:
from sympy import diff
def sum_diff_order(f,x,n):
g = 0
for i in range(n+1):
g += diff(f,x,i)
return g
So if you take f to be x**10 and n=5, we get:
>>> x = symbols('x')
>>> f = x**10
>>> sum_diff_order(f,x,5)
x**10 + 10*x**9 + 90*x**8 + 720*x**7 + 5040*x**6 + 30240*x**5

import sympy as sp
x = sp.symbols('x')
f = sp.Function('f')
n = 2
sum([f(x).diff(x,i) for i in range(n+1)])
f(x) + Derivative(f(x), x) + Derivative(f(x), x, x)

If n is an known integer, you can use something like Add(*[diff(f(x), x, i) for i in range(n+1)]). For symbolic n or infinity, it isn't possible yet, as there is no way yet to represent derivatives of symbolic order.

Related

Weighted sum using multiple pandas series?

I have 3 pandas series which I want to make a weighted sum.
Basically i want to sum all of the elements in p,r,y and do the following operation
(1/n) * ((r * y) / p) where n is the number of elements
p = pd.Series(np.random.random(5))
r = pd.Series([1,0,0,1,0])
y = pd.Series([1,0,0,0,1])
How can I do this in a clean way?
I did it like so?
(1/len(r))((r.sum() * y.sum()) / p.sum())
I can only think of lambda for sum to make the code cleaner:
s = lambda x: x.sum()
(s(r)*s(y)/s(p))/len(r)
N = 5
p = pd.Series(np.random.random(N))
r = pd.Series([1,0,0,1,0])
y = pd.Series([1,0,0,0,1])
(s(r)*s(y)/s(p)) /N

Why doesn't SymPy simplify the expression?

I am just looking at the Python module SymPy and try, as a simple (useless) example the fit of a function f(x) by a function set g_i(x) in a given interval.
import sympy as sym
def functionFit(f, funcset, interval):
N = len(funcset) - 1
A = sym.zeros(N+1, N+1)
b = sym.zeros(N+1, 1)
x = sym.Symbol('x')
for i in range(N+1):
for j in range(i, N+1):
A[i,j] = sym.integrate(funcset[i]*funcset[j],
(x, interval[0], interval[1]))
A[j,i] = A[i,j]
b[i,0] = sym.integrate(funcset[i]*f, (x, interval[0], interval[1]))
c = A.LUsolve(b)
u = 0
for i in range(len(funcset)):
u += c[i,0]*funcset[i]
return u, c
x = sym.Symbol('x')
f = 10*sym.cos(x)+3*sym.sin(x)
fooset=(sym.sin(x), sym.cos(x))
interval = (1,2)
print("function to approximate:", f)
print("Basic functions:")
for foo in fooset:
print(" - ", foo)
u,c = functionFit(f, fooset, interval)
print()
print("simplified u:")
print(sym.simplify(u))
print()
print("simplified c:")
print(sym.simplify(c))
The result is the fit function u(x), to be returned, together with the coefficients by functionFit.
In my case
f(x) = 10 * sym.cos(x) + 3 * sym.sin(x)
and I want to fit it according to a linear combination of sin(x), cos(x).
So the coefficients should be 3 and 10.
The result is OK, but for u(x) I get
u(x) = (12*sin(2)**2*sin(4)*sin(x) + 3*sin(8)*sin(x) + 12*sin(2)*sin(x) + 40*sin(2)**2*sin(4)*cos(x) + 10*sin(8)*cos(x) + 40*sin(2)*cos(x))/(2*(sin(4) + 2*sin(2))) :
Function to approximate: 3*sin(x) + 10*cos(x)
Basic functions:
- sin(x)
- cos(x)
Simplified u: (12*sin(2)**2*sin(4)*sin(x) + 3*sin(8)*sin(x) + 12*sin(2)*sin(x) + 40*sin(2)**2*sin(4)*cos(x) + 10*sin(8)*cos(x) + 40*sin(2)*cos(x))/(2*(sin(4) + 2*sin(2)))
Simplified c: Matrix([[3], [10]])
which is indeed the same as 10 * cos(x) + 3 * sin(x).
However I wonder why it is not simplified to that expression. I tried several simplifying function available, but none of it gives the expected result.
Is there something wrong in my code or are my expectations to high?
Don't know if this is a solution for you, but I'd simply use the .evalf method of every Sympy expression
In [26]: u.simplify()
Out[26]: (12*sin(2)**2*sin(4)*sin(x) + 3*sin(8)*sin(x) + 12*sin(2)*sin(x) + 40*sin(2)**2*sin(4)*cos(x) + 10*sin(8)*cos(x) + 40*sin(2)*cos(x))/(2*(sin(4) + 2*sin(2)))
In [27]: u.evalf()
Out[27]: 3.0*sin(x) + 10.0*cos(x)
In [28]:

Eliminate a variable to relate two functions in Python using SymPy

I have two equations that are parametrized by a variable "t". These look like:
X = p(t)
Y = q(t)
where p and q are polynomials in t. I want to use Python's SymPy library to eliminate the t variable and express Y = F(X) for some function X. I have tried using solve() in SymPy but this is not working too well. I know that Maple and Mathematica both have eliminate() functions that can accomplish this, but I wanted to know if Python might have a general function that does this.
Here is a lightly tested simple routine
def eliminate(eqs, z):
"""return eqs with parameter z eliminated from each equation; the first
element in the returned list will be the definition of z that was used
to eliminate z from the other equations.
Examples
========
>>> eqs = [Eq(2*x + 3*y + 4*z, 1),
... Eq(9*x + 8*y + 7*z, 2)]
>>> eliminate(eqs, z)
[Eq(z, -x/2 - 3*y/4 + 1/4), Eq(11*x/2 + 11*y/4 + 7/4, 2)]
>>> Eq(y,solve(_[1], y)[0])
Eq(y, -2*x + 1/11)
"""
from sympy.solvers.solveset import linsolve
Z = Dummy()
rv = []
for i, e in enumerate(eqs):
if z not in e.free_symbols:
continue
e = e.subs(z, Z)
if z in e.free_symbols:
break
try:
s = linsolve([e], Z)
if s:
zi = list(s)[0][0]
rv.append(Eq(z, zi))
rv.extend([eqs[j].subs(z, zi)
for j in range(len(eqs)) if j != i])
return rv
except ValueError:
continue
raise ValueError('only a linear parameter can be eliminated')
There is a more complex routine at this issue.
I refer to this example from the 'Scope' section of https://reference.wolfram.com/language/ref/Eliminate.html.
Eliminate[2 x + 3 y + 4 z == 1 && 9 x + 8 y + 7 z == 2, z]
>>> from sympy import *
>>> var('x y z')
(x, y, z)
>>> solve(2*x+3*y+4*z-1, z)
[-x/2 - 3*y/4 + 1/4]
>>> solve(9*x+8*y+7*z-2, z)
[-9*x/7 - 8*y/7 + 2/7]
>>> (-9*x/7 - 8*y/7 + Rational(2,7))-(-x/2 - 3*y/4 + Rational(1,4)).simplify()
-11*x/14 - 11*y/28 + 1/28
>>> 28*((-9*x/7 - 8*y/7 + Rational(2,7))-(-x/2 - 3*y/4 + Rational(1,4)).simplify())
-22*x - 11*y + 1
Solve each equation for z.
Subtract one expression for z from the other.
Note only that numeric fractions need to be coded — I've used Rational because I forget other methods — so that fractional arithmetic is used.
I multiply through to get rid of the denominators.
This approach will work only for the elimination of a single variable. I haven't considered the second and subsequent examples.
I hope this is useful.
Suppose you wanted to solve the equations for as a function of . This can be done by solving for both and :
solve(
[
Eq(z, sin(theta)),
Eq(z_o, cos(theta))
],
[z_o, theta],
dict=True
)
which yields
You can then throw away the result for and use the rest. This doesn't work for all situations - it requires that the intermediate variable be something that sympy could solve for directly.

Map linsolve solutions to indexed symbols in Sympy

I am trying to solve a set of linear simultaneous equations using linsolve in Sympy over a range of values. For simplicity I am showing below what I have been trying to do using simple equations.
from sympy import symbols, linsolve, IndexedBase
m = 2
n = symbols('n', integer=True)
x, y = symbols('x, y', cls=IndexedBase)
for n in range (0, m+1):
E1 = 2*x[n] + 5*y[n] - 33 + 2*n
E2 = x[n] + 3*y[n] - 19 + 4*n
sol = linsolve([E1, E2], [x[n], y[n]])
(x[n], y[n]) = tuple(*sol)
This returns an error "'IndexedBase' object does not support item assignment". How can I map the solution values to the indexed symbols so that I will be able to use them later in the code (e.g., take the sum of all x values (x[0] + x[1] + x[2])? I am looking for a robust solution as for the real equations the value of m can be around 500.
SymPy objects are immutable; one cannot attach numeric data to them. "x" is always just that, a symbol "x"; and "x[2]" is an indexed symbol "x[2]". They do not get associated with any numeric values. To store solutions, use a list of tuples or a dictionary (or list of dictionaries), whichever is more convenient.
solutions = {}
for n in range(0, m+1):
E1 = 2*x[n] + 5*y[n] - 33 + 2*n
E2 = x[n] + 3*y[n] - 19 + 4*n
sol = linsolve([E1, E2], [x[n], y[n]])
solutions.update(dict(zip([x[n], y[n]], *sol)))
print(solutions)
This prints {x[0]: 4, y[0]: 5, x[1]: 18, y[1]: -1, x[2]: 32, y[2]: -7}. You can then use this dictionary in subs:
expr = x[0] + 3*y[2]
print(expr.subs(solutions)) # -17

How to do numerical integration in python?

I can't install anything new I need to use the default python library and I have to integrate a function. I can get the value for any f(x) and I need to integrate from 0 to 6 for my function f(x).
In discrete form, integration is just summation, i.e.
where n is the number of samples. If we let b-a/n be dx (the 'width' of our sample) then we can write this in python as such:
def integrate(f, a, b, dx=0.1):
i = a
s = 0
while i <= b:
s += f(i)*dx
i += dx
return s
Note that we make use of higher-order functions here. Specifically, f is a function that is passed to integrate. a, b are our bounds and dx is 1/10 by default. This allows us to apply our new integration function to any function we wish, like so:
# the linear function, y = x
def linear(x):
return x
integrate(linear, 1, 6) // output: 17.85
# or using lamdba function we can write it directly in the argument
# here is the quadratic function, y=x^2
integrate(lambda x: x**2, 0, 10) // output: 338.35
You can use quadpy (out of my zoo of packages):
import numpy
import quadpy
def f(x):
return numpy.sin(x) - x
val, err = quadpy.quad(f, 0.0, 6.0)
print(val)
-17.96017028290743
def func():
print "F(x) = 2x + 3"
x = int(raw_input('Enter an integer value for x: '))
Fx = 2 * x + 3
return Fx
print func()
using the input function in python, you can randomly enter any number you want and get the function or if hard coding this this necessary you can use a for loop and append the numbers to a list for example
def func2():
print "F(x) = 2x + 3"
x = []
for numbers in range(1,7):
x.append(numbers)
upd = 0
for i in x:
Fx = 2 * x[upd] + 3
upd +=1
print Fx
print func2()
EDIT: if you would like the numbers to start counting from 0 set the first value in range to 0 instead of 1

Categories