I'm new to python but I been working on a code which can solve an integral equation which range is also changing according the unknown parameter. I tried to use Sympy solve function but it does not return any result. I solved the problem with a for loop, but its really slow, inefficient. I'm sure there must be a better solution, a solver. Maybe there is an other approach? I'am messing up something? I attach also the code.
import sympy as sy
from sympy.solvers import solve
alphasum = 1.707
Lky = 3.078
g = 8
Ep = 195
sigp1 = 1401.927
sigp0 = 1476
e = 2.718282
u = 0.05
k = 0.007
lsl = sy.Symbol('lsl')
def lefthand(g, Ep):
return g * Ep
def rigthhand(sigp1, sigp0, e, u, alphasum, Lky, k, lsl):
return (sigp1 - (-sigp1 + 2 * sigp0 - 2 * sigp0 * (1 - e ** (-u * (((alphasum / Lky) * lsl) + k * lsl)))))
equr = (sy.integrate(rigthhand(sigp1, sigp0, e, u, alphasum, Lky, k, lsl), (lsl, 0, lsl)))
equl = lefthand(g, Ep)
print(equr)
print (equl)
print (equr-equl)
result = solve(equr-equl, lsl,warn =True,check=False,minimal=True,quick=True,simplify=True,quartics=True)
print(result)
You can use nsolve to find numerical solutions:
In [11]: sympy.nsolve(equr-equl, lsl, 8)
Out[11]: 8.60275245116315
In [12]: sympy.nsolve(equr-equl, lsl, -4)
Out[12]: -4.53215114758428
When u is 0 your equation is linear and you can solve if for lsl; let this be an initial guess for the value of lsl at a larger value of u. Increase your value of u to the target value. Let's use capital U for the parameter we will control, replacing it with values closer and closer to u:
>>> U = Symbol('U')
>>> equr = (sy.integrate(rigthhand(sigp1, sigp0, e, U, alphasum, Lky, k, lsl), (lsl, 0, lsl)))
>>> equl = lefthand(g, Ep)
>>> z = equr-equl
>>> u0 = solve(z.subs(U,0),lsl)[0]
>>> for i in range(1,10): # get to u in 9 steps
... u0 = nsolve(z.subs(U,i*u/10.), u0)
>>> print(u0)
-4.71178322070344
Now define a larger value of u
>>> u = 0.3
>>> for i in range(1,10): # get to u in 9 steps
... u0 = nsolve(z.subs(U,i*u/10.), u0)
...
>>> u0
-2.21489271112540
Our intitial guess will (usually) be pretty good since it is exact when u is 0; if it fails then you might need to take more than 9 steps to reach the target value.
Related
I am still having a problem, a different one than my previous post.
Basically I have [5x5][5x1]=[0] and would like to have the symbolic expression of the solution.
Here is my code.
from sympy import symbols, solve
gm1, gm2, gm4 = symbols(['gm1', 'gm2', 'gm4'])
gds1, gds2, gds3, gds4, gds5 = symbols(['gds1', 'gds2', 'gds3', 'gds4', 'gds5'])
s = symbols('s')
Cd, CF , Cin, Ct = symbols(['Cd', 'CF', 'Cin', 'Ct'])
K = symbols('K')
vb, vc, ve, vout, iin = symbols(['vb', 'vc', 've', 'vout', 'iin'])
sol = solve([-(gds1+gds3+(s*Cd))*vb + (gm1+gds1)*ve + -gm1*vout, \
-gm4*vb + (gds4-gds2-(s*Cin)-(s*CF))*vc + (gds2+gm2)*ve + s*CF*vout + iin, \
gds1*vb + gds2*vc + (-(s*Ct)-gds5-gds1-gm1-gm2-gds2)*ve + gm1*vout, \
K*vc + vout, 0], [vout])
print(sol)
I am expecting
vout/iin = f(gm1, gm2, gm4, gds1, gds2, gds3, gds4, gds5, s, Cd, CF , Cin, Ct, K)
In other words, vb, vc, ve are eliminated.
Is there any specific command to do that?
The problem is that you have 4 equations and you've only specified one unknown (vout). The system is generically unsolvable for most values of vb, vc, ve so asking to solve only for vout leads to no solution (in the generic case).
Ask to solve for vout, vb, vc, ve as 4 unknowns for the 4 equations and you can get a solution for all 4:
linsolve(eqs, [vout, vb, vc, ve])
(The output is long so I have omitted it)
I'm using linsolve since the equations are linear although solve will also work.
It's not entirely clear what you want but some variation of the above should do it. You said you wanted vout and vin in terms of the other symbols but with vb, vc and ve eliminated. That would require 5 independent equations but since your 5th equation is just 0 you don't have that.
If you suspect that you should be able to solve for the ratio, go ahead and solve for one of the dividends and the others that you don't want in the solution for it:
>>> sol = solve(eqs, iin, vb, vc, ve, check=False, simplify=False)
You suspect that you should be able to form the ratio of vout/iin which means that the solution for iin should be linear in vout:
>>> sol[iin].diff(vout,2)
0
It is. The constant should also be 0:
>>> sol[iin].subs(vout,0)
0
It is. So iin = vout*sol[iin].diff(vout) or
>>> r = 1/sol[iin].diff(vout) # vout/iin
This is an expression that is in the form K*{quadratic in s}/{cubic in s}. All other solutions for vb,vc,ve are also directly proportional to vout so they can all be expressed as a ratio vout/vi in a similar fashion.
The problems you are having basically boil down to this: your equations are not written in terms of ratios but you are interested in solving for ratios. In your case, the variables of interest should all be normalized by vout. You can get your system into that form and then it will work, too:
>>> V = iin, vb, vc, ve # variables you have
>>> r = symbols('r:4') # variables for the ratios
>>> reps = dict([(v, r[i]*vout) for i,v in enumerate(V)])
>>> req = Tuple(*eqs).xreplace(reps) # e.g. replace iin with r0*vout
>>> rsol = solve(req, r, check=False, simplify=False, dict=True)[0]
>>> explicit_ratio_solutions = Dict(rsol).xreplace({ri: v/vout for ri,v in zip(r, V)}) # restore keys to be iin/vout, vb/vout, etc...
You can confirm that the solutions are free of vout
>>> vout in Dict(rsol).free_symbol
False
When is this going to work? When the additive term independent of the symbols of interest is itself proportional to the normalizing factor and the normalizing factor does not appear in the terms containing the symbol of interest. I'm going to use simpler symbols for your system so it is easy to see explicitly that this is the case:
>>> neq = Tuple(*eqs)
>>> syms = neq.free_symbols - {iin,vout,vb,vc,ve}
>>> neq = neq.xreplace({o:n for o,n in zip(ordered(syms), var('a:z'))})
>>> x = symbols('x:4')
>>> neq = neq.xreplace({i:j for i,j in zip((iin,vb,vc,ve), x)})
>>> neq = neq.xreplace({vout:y})
>>> for i in neq:
... t = ind, dep = i.as_independent(*x, as_Add=True)
... t + (dep.has(y),)
(-k*y, x1*(-b*n - f - h) + x3*(f + k), False)
(a*n*y, -m*x1 + x0 + x2*(-a*n - c*n - g + i) + x3*(g + l), False)
(k*y, f*x1 + g*x2 + x3*(-d*n - f - g - j - k - l), False)
(y, e*x2, False)
Notice that y (for vout) appears as a factor in all the xi-independent terms and that it does not appear in the xi-dependent terms. That means you can do a change of variables from xi to xi/y.
How do I calculate the cube roots of a complex number in python? Currently, the only way I've found to do it is according to this answer, but I'm trying to remove any and all import statements from my code.
Current method, reproduced here:
import math
def cuberoot( z ):
z = complex(z)
x = z.real
y = z.imag
mag = abs(z)
arg = math.atan2(y,x)
resMag = mag**(1./3)
resArg = [ (arg+2*math.pi*n)/3. for n in range(1,4) ]
return [ resMag*(math.cos(a) + math.sin(a)*1j) for a in resArg ]
Compute one and multiply with the cube roots of 1?
cuberoots_of_1 = 1, complex(-.5, .75**.5), complex(-.5, -.75**.5)
def cuberoot(z):
cuberoot = complex(z)**(1/3)
return [cuberoot * cr1 for cr1 in cuberoots_of_1]
Test:
>>> cuberoot(-2 + 3j)
[(1.1532283040274223+1.0106429470939737j),
(-1.4518566183526649+0.49340353410400484j),
(0.2986283143252425-1.5040464811979786j)]
>>> for z in cuberoot(-2 + 3j):
print(z**3, abs(z**3 - (-2 + 3j)))
(-1.999999999999999+3j) 1.1102230246251565e-15
(-1.999999999999999+3j) 1.1102230246251565e-15
(-1.9999999999999982+2.9999999999999996j) 1.831026719408895e-15
Doing the same with yours is less accurate:
(-1.999999999999996+3.000000000000002j) 4.572178254219406e-15
(-1.9999999999999933+3.000000000000004j) 7.768388458966724e-15
(-1.9999999999999956+3.0000000000000013j) 4.636427468134552e-15
Here is an approach using rotation by a factor of i^(2/3).
f = 1j**(2/3)
def cube_roots(z):
r = z**(1/3)
return [r, -r*f, r*f**2]
Python's built-in complex can handle finding one root out of the box:
def cube_root(v):
if not isinstance(v, complex):
v = complex(v, 0)
return v ** (1.0 / 3.0)
Examples:
cube_root(-3)
(0.7211247851537043+1.2490247664834064j)
cube_root(complex(1, -2))
(1.2196165079717578-0.47171126778938893j)
The function you reproduced above is one way to get all three roots.
I use Sympy solve() function to solve a large number of equations. All variables in the equations are defined as symbols. Variables can start with the letter P or F. I use solve() to express one specific P variable (the one that I observe) with only F variables, so I use solve() to substitute all other P variables with F variables. The sum of the coefficients before the F variables is ideally 1 or almost 1 (e.g.: 0.99).
This produces good results till a certain point where the number of equations becomes pretty big and also their length. There the Sympy solve() function starts to give me wrong results. The sum of the coefficients becomes negative (e.g. -7,...). It looks like that the solve() function gets problems with substituting any carrying over all variables and their coefficients.
Is there a way to correct this problem?
Dictionary of equations under link: https://drive.google.com/open?id=1VBQucrDU-o1diCd6i4rR3MlRh95qycmK
import json
from sympy import Symbol, Add, Eq, solve
# Get data
# data from link above
with open("C:\\\\Test\\dict.json") as f:
equations = json.load(f)
comp =[]
expressions = []
for p, equation_components in equations.items():
p = Symbol(p)
comp.append(p)
expression = []
for name, multiplier in equation_components.items():
if type(multiplier) == float or type(multiplier) == int:
expression.append(Symbol(name) * multiplier)
else:
expression.append(Symbol(name) * Symbol(multiplier))
expressions.append(Eq(p, Add(*expression)))
# Solution for variable P137807
print("Solving...")
# Works for slice :364 !!!!!
solutions = solve(expressions[:364], comp[:364], simplify=False, rational=False)
# Gives wrong results for slice :366 and above !!!!!
# solutions = solve(expressions[:366], comp[:366], simplify=False, rational=False)
vm_symbol = Symbol("P137807")
solution_1 = solutions[vm_symbol]
print("\n")
print("Solution_1:")
print(solution_1)
print("\n")
#Sum of coefficients
list_sum = []
for i in solution_1.args:
if str(i.args[1]) != "ANaN":
list_sum.append(i.args[0])
coeff_sum = sum(list_sum)
print("Sum:")
print(coeff_sum)
...
I just wanted to mark the problem as solved and provide reference to the solution. Please look at numerical instability when solving n=385 linear equations with Float coefficients #17136.
The solution that worked for me was to use the following solver and not the Sympy solve() function:
def ssolve(eqs, syms):
"""return the solution of linear system of equations
with symbolic coefficients and a unique solution.
Examples
========
>>> eqs=[x-1,x+2*y-z-2,x+z+w-6,2*y+z+x-2]
>>> v=[x,y,z,w]
>>> ssolve(eqs, v)
{x: 1, z: 0, w: 5, y: 1/2}
"""
from sympy.solvers.solveset import linear_coeffs
v = list(syms)
N = len(v)
# convert equations to coefficient dictionaries
print('checking linearity')
d = []
v0 = v + [0]
for e in [i.rewrite(Add) for i in eqs]:
co = linear_coeffs(e, *v)
di = dict([(i, c) for i, c in zip(v0, co) if c or not i])
d.append(di)
print('forward solving')
sol = {}
impl = {}
done = False
while not done:
# check for those that are done
more = set([i for i, di in enumerate(d) if len(di) == 2])
did = 0
while more:
di = d[more.pop()]
c = di.pop(0)
x = list(di)[0]
a = di.pop(x)
K = sol[x] = -c/a
v.remove(x)
changed = True
did += 1
# update everyone else
for j, dj in enumerate(d):
if x not in dj:
continue
dj[0] += dj.pop(x)*K
if len(dj) == 2:
more.add(j)
if did: print('found',did,'definitions')
# solve implicitly for the next variable
dcan = [i for i in d if len(i) > 2]
if not dcan:
done = True
else:
# take shortest first
di = next(ordered(dcan, lambda i: len(i)))
done = False
x = next(ordered(i for i in di if i))
c = di.pop(x)
for k in di:
di[k] /= -c
impl[x] = di.copy()
di.clear()
v.remove(x)
# update everyone else
for j, dj in enumerate(d):
if x not in dj:
continue
done = False
c = dj.pop(x)
for k in impl[x]:
dj[k] = dj.get(k, 0) + impl[x][k]*c
have = set(sol)
sol[0] = 1
while N - len(have):
print(N - len(have), 'to backsub')
for k in impl:
if impl[k] and not set(impl[k]) - have - {0}:
sol[k] = sum(impl[k][vi]*sol[vi] for vi in impl[k])
impl[k].clear()
have.add(k)
sol.pop(0)
return sol
I am using sympy to solve some equations and I am running into a problem. I have this issue with many equations but I will illustrate with an example. I have an equation with multiple variables and I want to solve this equation in terms of all variables but one is excluded. For instance the equation 0 = 2^n*(2-a) - b + 1. Here there are three variables a, b and n. I want to get the values for a and b not in terms of n so the a and b may not contain n.
2^n*(2-a) - b + 1 = 0
# Since we don't want to solve in terms of n we know that (2 - a)
# has to be zero and -b + 1 has to be zero.
2 - a = 0
a = 2
-b + 1 = 0
b = 1
I want sympy to do this. Maybe I'm just not looking at the right documentation but I have found no way to do this. When I use solve and instruct it to solve for symbols a and b sympy returns to me a single solution where a is defined in terms of n and b. I assume this means I am free to choose b and n, However I don't want to fix n to a specific value I want n to still be a variable.
Code:
import sympy
n = sympy.var("n", integer = True)
a = sympy.var("a")
b = sympy.var("b")
f = 2**n*(2-a) - b + 1
solutions = sympy.solve(f, [a,b], dict = True)
# this will return: "[{a: 2**(-n)*(2**(n + 1) - b + 1)}]".
# A single solution where b and n are free variables.
# However this means I have to choose an n I don't want
# to that I want it to hold for any n.
I really hope someone can help me. I have been searching google for hours now...
Ok, here's what I came up with. This seems to solve the type of equations you're looking for. I've provided some tests as well. Of course, this code is rough and can be easily caused to fail, so i'd take it more as a starting point than a complete solution
import sympy
n = sympy.Symbol('n')
a = sympy.Symbol('a')
b = sympy.Symbol('b')
c = sympy.Symbol('c')
d = sympy.Symbol('d')
e = sympy.Symbol('e')
f = sympy.sympify(2**n*(2-a) - b + 1)
g = sympy.sympify(2**n*(2-a) -2**(n-1)*(c+5) - b + 1)
h = sympy.sympify(2**n*(2-a) -2**(n-1)*(e-1) +(c-3)*9**n - b + 1)
i = sympy.sympify(2**n*(2-a) -2**(n-1)*(e+4) +(c-3)*9**n - b + 1 + (d+2)*9**(n+2))
def rewrite(expr):
if expr.is_Add:
return sympy.Add(*[rewrite(f) for f in expr.args])
if expr.is_Mul:
return sympy.Mul(*[rewrite(f) for f in expr.args])
if expr.is_Pow:
if expr.args[0].is_Number:
if expr.args[1].is_Symbol:
return expr
elif expr.args[1].is_Add:
base = expr.args[0]
power = sympy.solve(expr.args[1])
sym = expr.args[1].free_symbols.pop()
return sympy.Mul(sympy.Pow(base,-power[0]), sympy.Pow(base,sym))
else:
return expr
else:
return expr
else:
return expr
def my_solve(expr):
if not expr.is_Add:
return None
consts_list = []
equations_list = []
for arg in expr.args:
if not sympy.Symbol('n') in arg.free_symbols:
consts_list.append(arg)
elif arg.is_Mul:
coeff_list = []
for nested_arg in arg.args:
if not sympy.Symbol('n') in nested_arg.free_symbols:
coeff_list.append(nested_arg)
equations_list.append(sympy.Mul(*coeff_list))
equations_list.append(sympy.Add(*consts_list))
results = {}
for eq in equations_list:
var_name = eq.free_symbols.pop()
val = sympy.solve(eq)[0]
results[var_name] = val
return results
print(my_solve(rewrite(f)))
print(my_solve(rewrite(g)))
print(my_solve(rewrite(h)))
print(my_solve(rewrite(i)))
How do i implement this kind of equation in python dC/dt = r + kI - dC where the left hand side are constants and the right hand side are varibles?
i am relatively new to python and as such can't really do much.
from sympy.solvers import ode
r=float(input("enter r:"))
k=float(input("enter k:"))
I=float(input("enter I:"))
d=float(input("enter d:"))
C=float(input("enter C:"))
dC/dt=x
x=r + kI-dC
print(x)
what it just does equate the values of x and not any differential, would like help getting this to work.
if possible i would like to get answer specifying the using of sympy,
but all answers are truly appreciated.
You asigned values to all the variables that are on the rhs of x so when you show x you see the value that it took on with the variables that you defined. Rather than input values, why not try solve the ode symbolically if possible?
>>> from sympy import *
>>> var('r k I d C t')
(r, k, I, d, C, t)
>>> eq = Eq(C(t).diff(t), r + k*I + d*C(t)) # note d*C(t) not d*C
>>> ans = dsolve(eq); ans
C(t) == (-I*k - r + exp(d*(C1 + t)))/d
Now you can substitute in values for the variables to see the result:
>>> ans.subs({k: 0})
C(t) == (-r + exp(d*(C1 + t)))/d