I get a NameError when using SymPy nonlinsolve. After reading a lot of posts I think can be related to type and/or syntax, but I cannot find the exact cause, I just installed sympy a few days ago and my python version is Python 3.5.3 (default, Jan 19 2017, 14:11:04)
[GCC 6.3.0 20170118] on linux
thanks in advance
Vilbjorg
# Python 3 script , using SymPy library, parametrizatrion of the 3-sphere and rotations using quaternion multiplication
# python3 three_sphere.py
from sympy import *
def qmul(x0, x1, x2, x3, y0, y1, y2, y3):
z0 = x0*y0 - x1*y1 - x2*y2 - x3*y3
z1 = x0*y1 + x1*y0 + x2*y3 - x3*y2
z2 = x0*y2 - x1*y3 + x2*y0 + x3*y1
z3 = x0*y3 + x1*y2 - x2*y1 + x3*y0
return z0, z1, z2, z3
r1, s1, t1, r2, s2, t2 = symbols('r1, s1, t1, r2, s2, t2')
a0 = 2*r1/(1 + r1*r1 + s1*s1 + t1*t1)
a1 = 2*s1/(1 + r1*r1 + s1*s1 + t1*t1)
a2 = 2*t1/(1 + r1*r1 + s1*s1 + t1*t1)
a3 = (1 - r1*r1 - s1*s1 - t1*t1)/(1 + r1*r1 + s1*s1 + t1*t1)
b0 = 2*r2/(1 + r2*r2 + s2*s2 + t2*t2)
b1 = 2*s2/(1 + r2*r2 + s2*s2 + t2*t2)
b2 = 2*t2/(1 + r2*r2 + s2*s2 + t2*t2)
b3 = (1 - r2*r2 - s2*s2 - t2*t2)/(1 + r2*r2 + s2*s2 + t2*t2)
c0, c1, c2, c3 = qmul(a0, a1, a2, a3, b0, b1, b2, b3)
c0 = simplify(c0)
c1 = simplify(c1)
c2 = simplify(c2)
c3 = simplify(c3)
print(c0)
print(" ")
print(c1)
print(" ")
print(c2)
print(" ")
print(c3)
print(" ")
print(" ")
r3, s3, t3 = symbols('r3, s3, t3')
q0 = 2*r3/(1 + r3*r3 + s3*s3 + t3*t3)
q1 = 2*s3/(1 + r3*r3 + s3*s3 + t3*t3)
q2 = 2*t3/(1 + r3*r3 + s3*s3 + t3*t3)
q3 = (1 - r3*r3 - s3*s3 - t3*t3)/(1 + r3*r3 + s3*s3 + t3*t3)
#possibly syntax error here which causes NameError ??
soln = nonlinsolve([q0-c0, q1-c1, q2-c2, q3-c3], (r3, s3, t3))
# the idea is to have 4 equations : q0=c0, q1=c1. q2=c2. q3=c3 ; and solve for r3, s3 and t3 in terms of r1, s1, t1, r2, s2, t2
print(soln)
# http://docs.sympy.org/dev/tutorial/solvers.html
You are using a version of SymPy which does not have nonlinsolve. One way to fix this is to update SymPy (versions starting with 1.1 have it). The other is to replace nonlinsolve with solve.
Unfortunately, neither will produce a solution of your system. This is because in general, a system of several algebraic equations has no explicit solution, unless you are really lucky. So neither nonlinsolve nor solve get anywhere with it, despite trying for a long time.
Related
I have this function for solve_ivp, which solves a series of differential equations.
For every time step, the variable position [Pos] should be updated depending on a probability of it jumping. However, solve_ivp is not remembering the previous variable.
def jump_fun(t, Y, P, flux = 670):
global Pos_list
k1, k2 , k3, k4, k5, k6 , k , kay, q , K1, c5_tot, c6_tot, phi, Nc, V, qs, Cx, Ks, F, Cs0, flux, Pos, Pos_list = P
c1, c2, c3, c4, c5 ,c6, c4ex1, c4ex2, Cs1, Cs2= Y.reshape([10,-1])
#print(c1, c2, c3, c4, c5 ,c6, c4ex, Cs, Pos)
print(f'Pos: {Pos}')
# function heterogeneous_environment
prob = heterogeneous_environment(Nc, flux, V, 10, 10)
print(f'prob: {prob}')
#These arrays keep track of where the cells are
R1 = np.where(Pos == 1, 1, 0 )
R2 = np.where(Pos == 2, 1, 0 )
# We need to know the external concentrations of each reactor
rs1 = (Cx*qs*Cs1/ (Ks+Cs1))
dCs1 = F/V + flux*Cs2/V - flux*Cs1/V - rs1 # Position of cell is reactor 1, C1 = Cs
rs2 = (Cx*qs*Cs2/ (Ks+Cs2))
dCs2 = flux*Cs1/V - flux*Cs2/V - rs2 # Position of cell is reactor 2, C2 = Cs
j0 = rs1*R1 + rs2*R2
jm1 = kay * (c4 - c4ex1)*R1
jm2 = kay * (c4 - c4ex2)*R2
dc1= j0 - (k1 * c1 * c6 * (1/( 1 + ((c6/K1 )**q))))
dc2 = 2* k1 * c1 * c6 * (1/( 1 + ((c6/K1 )**q))) - k2 * c2 * (c5_tot - c5) - k6 *c2 *c5
dc3 = k2 * c2 * (c5_tot - c5) - k3 * c3* (c6_tot - c6)
dc4 = k3 * c3* (c6_tot - c6) - k4 * c4 *c5 - (jm1*R1 + jm2*R2)
dc5= k2 * c2 * (c5_tot - c5) - k4 * c4 *c5 - k6 *c2 *c5
dc6 = -2 * k1 * c1 * c6 * (1/( 1 + ((c6/K1 )**q))) + 2 * k3 * c3* (c6_tot - c6) - k5 * c6
cell1 = np.count_nonzero(R1 == 1)
cell2 = np.count_nonzero(R2 == 1)
dc4ex1= - k * c4ex1 + (phi / cell1) * np.sum(jm1) - (flux*c4ex1)/V + (flux*c4ex2)/V
dc4ex2= - k * c4ex2 + (phi / cell2) * np.sum(jm2) + (flux*c4ex1)/V - (flux*c4ex2)/V
#print('1')
#print(Pos)
#print('2')
Pos = Pos + prob*R1
Pos = Pos - prob*R2
#print(Pos)
Pos_list.append(Pos)
#iterate through the Pos vector, if Pos =1 do the balances for reactor 1 and then if the probability says to change
#reactor, change the position of the cell. Same for POS=2
#UPDATE THE MASS BALANCE FOR EACH REACTOR
return dc1, dc2, dc3, dc4, dc5 , dc6, dc4ex1, dc4ex2, dCs1, dCs2
I tried passing Pos as a return of the function, but it also didn't seem to work. Please help.
I compared results of rotating a vector with scipy.spatial.transform.Rotation, pyquaternion.Quaternion and my own implementation.
My own and pyquaternion and pretty similar, but Rotation is quite different.
import numpy as np
from pyquaternion import Quaternion
from scipy.spatial.transform import Rotation
def ham(q1, q2):
a1, b1, c1, d1 = q1
a2, b2, c2, d2 = q2
return np.array(
[
a1 * a2 - b1 * b2 - c1 * c2 - d1 * d2,
a1 * b2 + b1 * a2 + c1 * d2 - d1 * c2,
a1 * c2 - b1 * d2 + c1 * a2 + d1 * b2,
a1 * d2 + b1 * c2 - c1 * b2 + d1 * a2,
]
)
vector = np.array([-9.86411084, 0.10916063, -0.68953008])
purequat = np.array([0, -9.86411084, 0.10916063, -0.68953008])
# order: w, i, j, k
quat = np.array([-0.54312134, 0.42388916, -0.45617676, 0.5632019])
conj = np.array([1, -1, -1, -1])
quatconj = quat * conj # hand conjugate
Q = Quaternion(quat)
R = Rotation.from_quat(quat)
print("manual:", ham(quat, ham(purequat, quatconj))[1:])
print("Quaternion:", Q.rotate(vector))
print("Rotation:", R.apply(vector))
print("Rotation inv:", R.inv().apply(vector))
manual: [-0.14691211 9.88691296 -0.08305227]
Quaternion: [-0.14691852 9.88734378 -0.08305589]
Rotation: [-2.87868815 9.45502779 -0.32195404]
Rotation inv: [-2.33238602 0.16116154 -9.60843655]
I think the result of scipy is wrong, but maybe I'm misunderstanding something. Am I misunderstanding something or should I open an issue on the scipy bugtracker?
The answer was of course, very obvious. Given a quaternion w + xi + yj + zk then pyquaternion treats an array of four numbers as [w,x,y,z] while scipy as [x,y,z,w].
I am trying to find the determinant of the matrix M which is constructed using 12 equations. But when I took determinat. It is coming as zero. The matrix is symbolic in nature. I have used sympy package to construct the matrix M. The possible out is an analytical expression which is a function of a,b,z1,z2,l,L,g
from sympy import *
from numpy.linalg import matrix_rank
b,g,l,a,L,z1,z2,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,d1,d2,d3,d4,x,y = var('b g l a L z1 z2
c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 d1 d2 d3 d4 x y')
#beam equation
W1= c1*cos(b*x) + c2*sin(b*x) + c3*cosh(b*x) + c4*sinh(b*x)
W2= c5*cos(b*(x - z1)) + c6*sin(b*(x - z1)) + c7*cosh(b*(x - z1)) + c8*sinh(b*(x - z1))
W3=c10*sin(b*(x - z2)) + c11*cosh(b*(x - z2)) + c12*sinh(b*(x - z2)) + c9*cos(b*(x - z2))
#Boundary conditions on beam
e1=W1.subs(x,0)
e2=diff(W1, x).subs(x,0)
e3=diff(W1, x,2).subs(x,1)
e4=diff(W1, x,3).subs(x,1)
#bar equation
U1=d1*cos(L*y) + d2*sin(L*y)
U2=d3*cos(L*y) + d4*sin(L*y)
print(U2)
# Boundary conditions on bar*)
e5 = U1 .subs( y, 0);
e6 = (U1 .subs( y, g)) - (W1 .subs( x, z1));
e7 = U2 .subs( y, 0);
e8 = (U2 .subs( y, g)) - (W2 .subs( x, z2));
eqns = [e5,e6, e7, e8]
ss=linsolve(eqns, [d1,d2, d3, d4])
ss=list(ss)[0]
dd1=ss[0]
dd2=ss[1]
dd3=ss[2]
dd4=ss[3]
U1=U1.subs([(d1,dd1),(d2,dd2)])
U2=U2.subs([(d3,dd3),(d4,dd4)])
#Compatability conditions
e9= (W1.subs( x, z1)) - (W2.subs(x, z1))
e10=(diff(W1, x).subs(x,z1))-(diff(W2, x).subs(x,z1))
e11=(W2.subs( x, z2)) - (W3.subs(x, z2))
e12=(diff(W2, x).subs(x,z2))-(diff(W3, x).subs(x,z2))
#equlibrium equation
e13=(diff(W1, x,3).subs(x,z1))+(a*(diff(U1, y).subs(y,g)))-(diff(W2, x,3).subs(x,z1))
e14=(diff(W1, x,2).subs(x,z1)) + (diff(W2, x,2).subs(x,z1))
e15 =(diff(W2, x,3).subs(x,z2))+(a*(diff(U2, y).subs(y,g)))-(diff(W3, x,3).subs(x,z2))
e16 =(diff(W2, x,2).subs(x,z2)) + (diff(W3, x,2).subs(x,z2))
eqnlist=[e1,e2,e3,e4,e9,e10,e11,e12,e13,e14,e15,e16]
varibles=[c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12]
M, B = linear_eq_to_matrix(eqnlist,varibles)
M.det()
I try to solve a system of 4 differential equations in sympy. I get a "NotImplementedError". Is there a workaround?
The set of ode's I am trying to solve is:
![ODE]: https://imgur.com/Xa5fwlt
I have tried substituting numerical values for the R12 to R45 symbols. I continue receiving the same error.
import sympy as sp
import numpy as np
import matplotlib.pyplot as plt
# Define symbols
m1, m2, m3, m4 = sp.symbols('m1 m2 m3 m4', real = True, positive=True)
c1, c2, c3, c4 = sp.symbols('c1 c2 c3 c4', real = True, positive=True)
R12, R25, R23, R34, R45 = sp.symbols('R12 R25 R23 R34 R45', real = True, positive=True) #0.2, 0.1, 2.7, 0.5, .6
T1, T2, T3, T4 = sp.symbols('T1 T2 T3 T4', cls=sp.Function)
qp, qel = sp.symbols('qp qel')
T5 = 25 # ambient temperature
# Define equations
eq1 = -sp.Eq(sp.Derivative(T1(t), t)) + - (T1(t)-T2(t)) / (R12 * m1 * c1)
eq2 = -sp.Eq(sp.Derivative(T2(t), t)) + 1 / (m2 * c2) * ((T1(t) - T2(t))/R12 + (T5-T2(t))/R25 - (T2(t)-T3(t))/R23)
eq3 = -sp.Eq(sp.Derivative(T3(t), t)) + 1 / (m3 * c3) * ((T2(t) - T3(t))/R23 + (T4(t)-T3(t))/R34 - qp)
eq4 = -sp.Eq(sp.Derivative(T4(t), t)) + 1 / (m4 * c4) * (qp - (T4(t) - T3(t))/R34 + (T4(t)-T5)/R45)
eq = (eq1, eq2, eq3, eq4)
funct = (T1(t), T2(t), T3(t), T4(t))
# Solve
sp.dsolve(eq, funct)
I expected to receive the symbolic solution for this set of differential equations.
The result is "NotImplementedError"
Your syntax for creating your equations is not correct. Eq needs to take two arguments, the left-hand side and the right-hand side.
eq1 = sp.Eq(sp.Derivative(T1(t), t), + - (T1(t)-T2(t)) / (R12 * m1 * c1))
eq2 = sp.Eq(sp.Derivative(T2(t), t), + 1 / (m2 * c2) * ((T1(t) - T2(t))/R12 + (T5-T2(t))/R25 - (T2(t)-T3(t))/R23))
eq3 = sp.Eq(sp.Derivative(T3(t), t), + 1 / (m3 * c3) * ((T2(t) - T3(t))/R23 + (T4(t)-T3(t))/R34 - qp))
eq4 = sp.Eq(sp.Derivative(T4(t), t), + 1 / (m4 * c4) * (qp - (T4(t) - T3(t))/R34 + (T4(t)-T5)/R45))
I did this and dsolve takes a while to compute the solution. It has to exponentiate a 4x4 symbolic matrix, which involves finding the symbolic eigenvalues, i.e., solving a quartic, which is very complicated in the general case.
SymPy could probably be improved here. Replacing symbolic parameters with numeric ones should make it go faster.
The equation of an ellipse is:
sqrt((x-a1)**2 + (y-b1)**2) + np.sqrt((x-a2)**2 + (y-b2)**2) = c
The focii are (a1, b1) and (a2, b2). c is also known. How do I draw this in python using matplotlib?
Thanks for your help.
You can represent the ellipse parametrically in some variable t. You could look into Wikipedia to see how this can be done, for instance.
In the following code, I've derived the parameters necessary for the parametric form from the parameters that you've supplied.
# Example focii and sum-distance
a1 = 1
b1 = 2
a2 = 5
b2 = 7
c = 9
# Compute ellipse parameters
a = c / 2 # Semimajor axis
x0 = (a1 + a2) / 2 # Center x-value
y0 = (b1 + b2) / 2 # Center y-value
f = np.sqrt((a1 - x0)**2 + (b1 - y0)**2) # Distance from center to focus
b = np.sqrt(a**2 - f**2) # Semiminor axis
phi = np.arctan2((b2 - b1), (a2 - a1)) # Angle betw major axis and x-axis
# Parametric plot in t
resolution = 1000
t = np.linspace(0, 2*np.pi, resolution)
x = x0 + a * np.cos(t) * np.cos(phi) - b * np.sin(t) * np.sin(phi)
y = y0 + a * np.cos(t) * np.sin(phi) + b * np.sin(t) * np.cos(phi)
# Plot ellipse
plt.plot(x, y)
# Show focii
plt.plot(a1, b1, 'bo')
plt.plot(a2, b2, 'bo')
plt.axis('equal')
plt.show()
This gives what you need:
you need 2 lists or arrays of X, Y such that the elements satisfy the ellipse equation
the usual ellipse plotting solutions parameterize the ellipse equation by central (or focal) angle to make the X,Y functions single valued for the angle in 0 to 2pi
I showed a solution in Drawing elliptical orbit in Python (using numpy, matplotlib)
Y as a function of X with a hack to "feel out" the xrange, then piece together the dual Y solutions for each x
just the minimum mods to that code to put in your equation, would fail for a1 = a2
the symbolic solution takes a minute or so runtime
import numpy as np
import matplotlib.pyplot as plt
from sympy import *
# sqrt((x-a1)**2 + (y-b1)**2) + np.sqrt((x-a2)**2 + (y-b2)**2) = c
coeffs = [1, 0, -1, 0, 4]
xs = [coeffs[0], coeffs[2]]
def ysolv(coeffs):
x,y,a1,b1,a2,b2,c = symbols('x y a1 b1 a2 b2 c', real = True)
ellipse = sqrt((x-a1)**2 + (y-b1)**2) + sqrt((x-a2)**2 + (y-b2)**2) - c
y_sols = solve(ellipse, y)
print(*y_sols, sep='\n')
num_coefs = [(a, f) for a, f in (zip([a1,b1,a2,b2,c], coeffs))]
y_solsf0 = y_sols[0].subs(num_coefs)
y_solsf1 = y_sols[1].subs(num_coefs)
print(y_solsf0, '\n', y_solsf1)
f0 = lambdify([x], y_solsf0)
f1 = lambdify([x], y_solsf1)
return f0, f1
f0, f1 = ysolv(coeffs)
y0 = [f0(x) for x in xs]
y1 = [f1(x) for x in xs]
def feeloutXrange(f, midx, endx):
fxs = []
x = midx
while True:
try: f(x)
except:
break
fxs.append(x)
x += (endx - midx)/200
return fxs
midx = (min(xs) + max(xs))/2
xpos = feeloutXrange(f0, midx, max(xs))
xnegs = feeloutXrange(f0, midx, min(xs))
xs_ellipse = xnegs[::-1] + xpos[1:]
y0s = [f0(x) for x in xs_ellipse]
y1s = [f1(x) for x in xs_ellipse]
ys_ellipse = y0s + y1s[::-1] + [y0s[0]] # add y start point to end to close drawing
xs_ellipse = xs_ellipse + xs_ellipse[::-1] + [xs_ellipse[0]] # added x start point
plt.plot(xs_ellipse, ys_ellipse)
plt.show()
(-c*sqrt((a1**2 - 2*a1*a2 + a2**2 + b1**2 - 2*b1*b2 + b2**2 - c**2)*(a1**2 + 2*a1*a2 - 4*a1*x + a2**2 - 4*a2*x + b1**2 - 2*b1*b2 + b2**2 - c**2 + 4*x**2))*(-b1 + b2 + c)*(b1 - b2 + c) + (b1**2 - 2*b1*b2 + b2**2 - c**2)*(-a1**2*b1 + a1**2*b2 + 2*a1*b1*x - 2*a1*b2*x + a2**2*b1 - a2**2*b2 - 2*a2*b1*x + 2*a2*b2*x - b1**3 + b1**2*b2 + b1*b2**2 + b1*c**2 - b2**3 + b2*c**2))/(2*(-b1 + b2 + c)*(b1 - b2 + c)*(b1**2 - 2*b1*b2 + b2**2 - c**2))
(c*sqrt((a1**2 - 2*a1*a2 + a2**2 + b1**2 - 2*b1*b2 + b2**2 - c**2)*(a1**2 + 2*a1*a2 - 4*a1*x + a2**2 - 4*a2*x + b1**2 - 2*b1*b2 + b2**2 - c**2 + 4*x**2))*(-b1 + b2 + c)*(b1 - b2 + c) + (b1**2 - 2*b1*b2 + b2**2 - c**2)*(-a1**2*b1 + a1**2*b2 + 2*a1*b1*x - 2*a1*b2*x + a2**2*b1 - a2**2*b2 - 2*a2*b1*x + 2*a2*b2*x - b1**3 + b1**2*b2 + b1*b2**2 + b1*c**2 - b2**3 + b2*c**2))/(2*(-b1 + b2 + c)*(b1 - b2 + c)*(b1**2 - 2*b1*b2 + b2**2 - c**2))
sqrt(-48*x**2 + 192)/8
-sqrt(-48*x**2 + 192)/8
the other answers used the parametric transform approach
I especially like showing sympy solving the equation for you rather than someone hand solving it
the symbolic expression only needs be found once for a particular Ellipse parameterization, then the symbolic expression can simply be hard coded:
"""
for Ellipse equation:
sqrt((x-a1)**2 + (y-b1)**2) + sqrt((x-a2)**2 + (y-b2)**2) = c
sympy solution to Ellipse equation, only have to run once to get y_sols
symbolic expression to paste into ysolv below
#def symEllipse():
# x,y,a1,b1,a2,b2,c = symbols('x y a1 b1 a2 b2 c', real = True)
# ellipse = sqrt((x-a1)**2 + (y-b1)**2) + sqrt((x-a2)**2 + (y-b2)**2) - c
# y_sols = solve(ellipse, y)
# print(*y_sols, sep='\n')
"""
coeffs = [1, 1, -1, -1, 3]
xs = [coeffs[0], coeffs[2]]
def ysolv(coeffs):
x,y,a1,b1,a2,b2,c = symbols('x y a1 b1 a2 b2 c', real = True)
y_sols = [
(-c*sqrt((a1**2 - 2*a1*a2 + a2**2 + b1**2 - 2*b1*b2 + b2**2 - c**2)*
(a1**2 + 2*a1*a2 - 4*a1*x + a2**2 - 4*a2*x + b1**2 - 2*b1*b2 + b2**2
- c**2 + 4*x**2))*(-b1 + b2 + c)*(b1 - b2 + c) + (b1**2 - 2*b1*b2 +
b2**2 - c**2)*(-a1**2*b1 + a1**2*b2 + 2*a1*b1*x - 2*a1*b2*x +
a2**2*b1 - a2**2*b2 - 2*a2*b1*x + 2*a2*b2*x - b1**3 + b1**2*b2 +
b1*b2**2 + b1*c**2 - b2**3 + b2*c**2))/(2*(-b1 + b2 + c)*
(b1 - b2 + c)*(b1**2 - 2*b1*b2 + b2**2 - c**2)),
(c*sqrt((a1**2 - 2*a1*a2 + a2**2 + b1**2 - 2*b1*b2 + b2**2 - c**2)*
(a1**2 + 2*a1*a2 - 4*a1*x + a2**2 - 4*a2*x + b1**2 - 2*b1*b2 + b2**2
- c**2 + 4*x**2))*(-b1 + b2 + c)*(b1 - b2 + c) + (b1**2 - 2*b1*b2 +
b2**2 - c**2)*(-a1**2*b1 + a1**2*b2 + 2*a1*b1*x - 2*a1*b2*x +
a2**2*b1 - a2**2*b2 - 2*a2*b1*x + 2*a2*b2*x - b1**3 + b1**2*b2 +
b1*b2**2 + b1*c**2 - b2**3 + b2*c**2))/(2*(-b1 + b2 + c)*
(b1 - b2 + c)*(b1**2 - 2*b1*b2 + b2**2 - c**2))
]
num_coefs = [(a, f) for a, f in (zip([a1,b1,a2,b2,c], coeffs))]
y_solsf0 = y_sols[0].subs(num_coefs)
y_solsf1 = y_sols[1].subs(num_coefs)
print(y_solsf0, '\n', y_solsf1)
f0 = lambdify([x], y_solsf0)
f1 = lambdify([x], y_solsf1)
return f0, f1