Plotting a sympy function. Strange xlim behavior - sympy

I try to plot a sympy function from 0 to 120 by using this code :
def symbolicCalc():
A0, k1, k2, t = sp.symbols("A0 k1 k2 t",real=True)
fSymb=A0*(1-(k1+k2*A0)/(k2*A0+k1*sp.exp((k1+k2*A0)*t)))
sp.plotting.plot(fSymb.subs([(A0,70),(k1,8e-4),(k2,1.5e-3)]),xlim=[0,120],ylim=[0,100])
symbolicCalc()
And I obtain the following figure :
How can I have a plot from 0 to 120 ?
Thanks for answer

Ok, I solved my problem by adding (t,0,120)
def symbolicCalc():
A0, k1, k2, t = sp.symbols("A0 k1 k2 t",real=True)
fSymb=A0*(1-(k1+k2*A0)/(k2*A0+k1*sp.exp((k1+k2*A0)*t)))
sp.plotting.plot(fSymb.subs([(A0,70),(k1,8e-4),(k2,1.5e-3)]),(t,0,120),xlim=[0,120],ylim=[0,100])
symbolicCalc()

Related

Find numerical roots in poly rational elements with Sympy function set

I am not pratice in Sympy manipulation.
I need to find roots on particular poly:
-4x**(11/2)-24x**(9/2)-16x**(7/2)+2x**(5/2)+16x**(5)+23x**(4)+5x**(3)-x**(2)
I verified that I have 2 real solution and I find one of them with Sympy function
nsolve(mypoly,x,1).
Why the previous step doesn't look the other?
How can I proceed to find ALL roots?
Thank you to all for assistance
A.
To my knowledge, nsolve looks in the proximity of the provided initial guess to find one root for each equations.
I would plot the expression to find suitable initial guesses:
from sympy import *
from sympy.plotting import PlotGrid
expr = -4*x**(S(11)/2)-24*x**(S(9)/2)-16*x**(S(7)/2)+2*x**(S(5)/2)+16*x**(5)+23*x**(4)+5*x**(3)-x**(2)
p1 = plot(expr, (x, 0, 0.5), adaptive=False, n=1000, ylim=(-0.01, 0.05), show=False)
p2 = plot(expr, (x, 0, 5), adaptive=False, n=1000, ylim=(-200, 200), show=False)
PlotGrid(1, 2, p1, p2)
Now, we can do:
nsolve(expr, x, 0.2)
# out: 0.169003536680445
nsolve(expr, x, 4)
# out: 4.28968831654177
EDIT: to find all roots (even the complex one), we can:
compute the derivative of the expression.
convert both the expression and the derivative to numerical functions with sympy's lambdify.
visually inspect the expression in the complex plane to determine good initial values for the root finding algorithm. I'm going to use this plotting module, SymPy Plotting Backend which exposes a very handy function, plot_complex, to generate domain coloring plots. In particular, I will plot alternating black and white stripes corresponding to modulus.
use scipy's newton method to compute the actual roots. EDIT: I just discovered that nsolve works too :)
# step 1 and 2
f = lambdify(x, expr)
f_der = lambdify(x, expr.diff(x))
# step 3
from spb import plot_complex
r = (x, -1-0.8j, 4.5+0.8j)
w = r[1].real - r[2].real
h = r[1].imag - r[2].imag
# number of discretization points, watch out memory usage
n1 = 1500
n2 = int(h / w * n1)
plot_complex(expr, r, {"interpolation": "spline36"}, grid=False, coloring="e", n1=n1, n2=n2, size=(10, 5))
In the above picture we see circular stripes getting bigger and deforming. The center of these circular stripes represent a pole or a zero. But this is an easy case: there are no poles. So, from the above pictures we count 7 zeros. We already know 3, the two computed above and the value 0. Let's find the others:
from scipy.optimize import newton
r1 = newton(f, x0=-0.9+0.1j, fprime=f_der)
r2 = newton(f, x0=-0.9-0.1j, fprime=f_der)
r3 = newton(f, x0=0.6+0.6j, fprime=f_der)
r4 = newton(f, x0=0.6-0.6j, fprime=f_der)
for r in (r1, r2, r3, r4):
print(r, ": is it a zero?", expr.subs(x, r).evalf())
# out:
# (-0.9202719950522663+0.09010409402273806j) : is it a zero? -8.21787666002984e-15 + 2.06697764417957e-15*I
# (-0.9202719950522663-0.09010409402273806j) : is it a zero? -8.21787666002984e-15 - 2.06697764417957e-15*I
# (0.6323265751497729+0.6785871500619469j) : is it a zero? -2.2103533615688e-15 - 2.77549897301442e-15*I
# (0.6323265751497729-0.6785871500619469j) : is it a zero? -2.2103533615688e-15 + 2.77549897301442e-15*I
As you can see, inserting those values into the original expression get values very very close to zero. It is perfectly normal to see these kind of errors.
I just discovered that you can use also use nsolve instead of newton to compute complex roots. This makes step 1 and 2 unnecessary.
nsolve(expr, x, -0.9+0.1j)
# out: −0.920271995052266+0.0901040940227375𝑖

Solving 1 equation based on input variable

For example, Volume of a rectangular box can be calculated as V = L * W * H
Suppose we know V, L, W, then we can solve for H.
Suppose we know V, H, W, then we can solve for V.
Suppose we know L, W, H, then we can solve for V.
And e.t.c
Is there a way to solve in python (I am trying Sympy currently) to solve it based on the input given?
Sure I can use cases of ifs, but I will need to write 4 equations to solve and that is for a short equation.
Any suggestion is appreciated.
Kind regards,
Iwan
This answer to a similar question may help you. Basically you can define the general equation, get values for all but one variable, substitution them into the general equation then pass that expression to solve (or else just pass all equations to solve, which I show below):
from sympy import Eq, solve, Tuple, S
from sympy.abc import v,l,w,h
eq = Eq(v, l*w*h)
variables = eq.free_symbols
got = []
vs = ', '.join(([str(i) for i in variables]))
print('enter 3 known values of {%s} as equality, e.g. h=2' % vs)
for i in range(3):
if 0: # change to 1 to get real input
e = input()
else:
e = ['v=20','w=5','h=1'][i]
got.append(Eq(*[S(j) for j in e.split('=')]))
x = ({v,l,w,h} - Tuple(*got).free_symbols).pop()
ans = solve([eq]+got)
print('consistent values: %s' % ans)
print('%s = %s' % (x.name, ans[0][x])
gives
enter 3 known values of {v, h, w, l} as equality, e.g. h=2
consistent values: [{v: 20, h: 1, w: 5, l: 4}]
l = 4

Solving a matrix equation containing MatrixSymbols of symbolic size in Sympy?

As an introduction i want to point out that if one has a matrix A consisting of 4 submatrices in a 2x2 pattern, where the diagonal matrices are square, then if we denote its inverse as X, the submatrix X22 = (A22-A21(A11^-1)A12)^-1, which is quite easy to show by hand.
I was trying to do the same for a matrix of 4x4 submatrices, but its quite tedious by hand. So I thought Sympy would be of some help. But I cannot figure out how (I have started by just trying to reproduce the 2x2 result).
I've tried:
import sympy as s
def blockmatrix(name, sizes, names=None):
if names is None:
names = sizes
ll = []
for i, (s1, n1) in enumerate(zip(sizes, names)):
l = []
for j, (s2, n2) in enumerate(zip(sizes, names)):
l.append(s.MatrixSymbol(name+str(n1)+str(n2), s1, s2))
ll.append(l)
return ll
def eyes(*sizes):
ll = []
for i, s1 in enumerate(sizes):
l = []
for j, s2 in enumerate(sizes):
if i==j:
l.append(s.Identity(s1))
continue
l.append(s.ZeroMatrix(s1, s2))
ll.append(l)
return ll
n1, n2 = s.symbols("n1, n2", integer=True, positive=True, nonzero=True)
M = s.Matrix(blockmatrix("m", (n1, n2)))
X = s.Matrix(blockmatrix("x", (n1, n2)))
I = s.Matrix(eyes(n1, n2))
s.solve(M*X[:, 1:]-I[:, 1:], X[:, 1:])
but it just returns an empty list instead of the result.
I have also tried:
Using M*X==I but that just returns False (boolean, not an Expression)
Entering a list of equations
Using 'ordinary' symbols with commutative=False instead of MatrixSymbols -- this gives an exception with GeneratorsError: non-commutative generators: (x12, x22)
but all without luck.
Can you show how to derive a result with Sympy similar to the one I gave as an example for X22?
The most similar other questions on solving with MatrixSymbols seem to have been solved by working around doing exactly that, by using an array of the inner symbols or some such instead. But since I am dealing with symbolically sized MatrixSymbols, that is not an option for me.
Is this what you mean by a matrix of 2x2 matrices?
>>> a = [MatrixSymbol(i,2,2) for i in symbols('a1:5')]
>>> A = Matrix(2,2,a)
>>> X = A.inv()
>>> print(X[1,1]) # [1,1] instead of [2,2] because indexing starts at 0
a1*(a1*a3 - a3*a1)**(-1)
[You indicated not and pointed out that the above is not correct -- that appears to be an issue that should be resolved.]
I am not sure why this isn't implemented, but we can do the solving manually as follows:
>>> n = 2
>>> v = symbols('b:%s'%n**2,commutative=False)
>>> A = Matrix(n,n,symbols('a:%s'%n**2,commutative=False))
>>> B = Matrix(n,n,v)
>>> eqs = list(A*B - eye(n))
>>> for i in range(n**2):
... s = solve(eqs[i],v[i])[0]
... eqs[i+1:] = [e.subs(v[i],s) for e in eqs[i+1:]]
...
>>> s # solution for v[3] which is B22
(-a2*a0**(-1)*a1 + a3)**(-1)
You can change n to 3 and see a modestly complicated expression. Change it to 4 and check the result by hand to give a new definition to the word "tedious" ;-)
The special structure of the equations to be solved can allow for a faster solution, too: the variable of interest is the last factor in each term containing it:
>>> for i in range(n**2):
... c,d = eqs[i].expand().as_independent(v[i])
... assert all(j.args[-1]==v[i] for j in Add.make_args(d))
... s = 1/d.subs(v[i], 1)*-c
... eqs[i+1:] = [e.subs(v[i], s) for e in eqs[i+1:]]

Simplifying equations in Sympy using inequalities

I am trying in Sympy to use a standard engineering method of simplifying an equation, where you know one variable is much larger or smaller than another. For instance, given the equation
C1*R2*s+C1*R2+R1+R2
and knowing that
R1 >> R2
the equation can be simplified to
C1*R2*s+C1*R2+R1.
What you'd normally do by hand is divide by R1, giving
C1*R2*s/R1+C1*R2/R1+1+R2/R1
then anyplace you see R2/R1 by itself you can set it to zero and then multiply by R1. I've not been able to figure how this would be done in Sympy. Obviously it's easy to do the division step, but I haven't been able to figure out how to do the search and replace step- just using subs gives you
R1
which isn't the right answer. factor, expand, collect, don't seem to get me anywhere.
Using replace instead of subs works here.
C1, C2, R1, R2 = sp.symbols('C1, C2, R1, R2', real = True)
s = sp.symbols('s')
expr = C1*R2*s+C1*R2+R1+R2
print('original expression:', expr)
expr_approx = (R1 * ((expr/R1).expand().replace(R2/R1,0))).simplify()
print('approximate expression:', expr_approx)
original expression: C1*R2*s + C1*R2 + R1 + R2
approximate expression: C1*R2*s + C1*R2 + R1

Do loop with 2 variables changing in each step of loop

I'm working on Fortran 90. I need to calculate a recursion like xn = 6*(xn-1) + 7*(xn-2) where (xn-1) is the n-1 step and (xn-2) is the n-2 step. So if we set x1 = 2 and x0 = 1 we get x2 = 6*x1 + 7*x0 and so on for each n.
So I wrote
x0 = 1.
x1 = 2.
do i = 1,20
xn = 6.*x1 + 7.*x0
x1 = xn
x0 = x1
end do
but this code is replacing x0 and x1 for xn and I need to replace x1 for xn and x0 for x1 in each step. I'd tryed many things but I failed. Any idea how to do that?
Though the answer has already been added to this question, let me answer a more general question which is encountered more frequently. Consider the problem where the very next value in the iteration depends on n previous values. In the present case n = 2. The general strategy to solve this problem is to construct another 1-d array of size n and save all the initial values x(1),x(2),..,x(n) in this array. Then in each iteration we use these values to calculate the next value x(n+1) and update the array with x(1) by x(2), x(2) by x(3),...,x(n) by x(n+1) and again use these values to calculate the next value of x and so on. A particular example where such strategy must necessarily be used is the integration of time-delayed systems.
#parthian-shot has given the correct answer in the comment. But that leaves the question marked as unanswered, so I am repeating it here:
You are assigning the value of xn to x1, and then the value of x1 (which is now the same as xn) to x0. You just need to flip it around:
do i = 1,20
xn = 6.*x1 + 7.*x0
x0 = x1
x1 = xn
end do