Substituing equation on Sympy - python

I'm trying to make an substitution of an equation to another, to reduce the variables.
Ex:
Import sympy
r, h = sympy.symbols('r h')
volume = sympy.Eq(sympy.pi*r**2*h , 355)
areaSup = 2*sympy.pi*r*h + 2*sympy.pi*r**2
areaSup = areaSup.subs(h, volume)
Give me an error:
TypeError: Relational can not be used in Mul
But if I rewrite the equation on subs, this pass.
I don't know how to solve this kind of problem, rewrite formulas every time is key to error.

h should be replaced by the value of h you get when solving the area-equation for h:
>>> areaSup.subs(h, solve(volume,h)[0])
2*pi*r**2 + 710/r

Related

I want solve this Equations in python

I'm work with Python
it's simple (1.1*x)+(b+(b*0.1))=a this equation is what I want to solve.
I'm so newbie in this world so I having a problem with it
"a" and "b" is come with
int(input('factor a : '))
int(input('factor b : '))
How can I script this to make an calculator
I don't know what values ​​you would set the X to but you would just add the part of the equation and assemble it already in this code.
import math
a = int(input('factor a : '))
b = int(input('factor b : '))
print((b+(b*0.1))/a)
Depending on the kind of project that you have in mind you can use symbolic mathematics program to gather flexibility.
Here an example with sympy and a live shell to test it without installations.
from sympy import symbols, Eq, solve
# declare the symbols
x, a, b = symbols('x a b')
# set up the equation
eq = Eq((1.1*x)+(b+(b*0.1)), a)
# solve it (for hard ones there are several types of solvers)
sol = solve(eq, x)
# fix the free variables
extra_pars = {a.name: input('a:'), b.name: input('b')}
# replace into the expression
new_sol = sol[0].subs(extra_pars)
print(new_sol)

SymPy with advanced rewrite and simplification

For instance, I want to expand the following simultaneous equations in first order difference with respect to x, y and z1:
$$x^\alpha y^(1-\alpha) = z_1$$
$$x^\beta y^(1-\beta) = z_2$$
It is obviously that
$$\alpha \hat{x} + (1-\alpha) \hat{y} = \hat{z_1}$$
$$\beta \hat{x} + (1-\beta) \hat{y} = 0$$
where $\hat{variable}$ means the elasticity of the variable, namely, $\frac{d varibale}{variable}$.
We have:
$$\hat{x} = \frac{1-\beta}{\alpha - \beta} \hat{z_1}$$
$$\hat{y} = -\frac{\beta}{\alpha - \beta} \hat{z_1}$$
The corresponding code for python using SymPy will be:
import sympy as sp
x,y,z1,z2,alpha,beta = sp.symbols('x,y,z_1,z_2,alpha,beta',positive=True)
eq1 = x**alpha*y**(1-alpha) - z1
eq2 = x**beta*y**(1-beta) - z2
hat_x,hat_y,hat_z1 = sp.symbols('\hat{x},\hat{y},\hat{z_1})
diff_eq1 = eq1.diff(x)*hat_x*x + eq1.diff(y)*hat_y*y + eq1.diff(z1)*hat_z1*z1
diff_eq2 = eq2.diff(x)*hat_x*x + eq2.diff(y)*hat_y*y + eq2.diff(z1)*hat_z1*z1
root = sp.solve([diff_eq1,diff_eq2],[hat_x,hat_y])
which gives the result
As you can see, the expression is right, but without further simplification. The reason is that it does not take the advantage of eq1 = 0 and eq2 = 0. My question is, how to make further simplifications using the information given by the original equations? Thanks!!
BTW, how can I declare variables with ranges? For instance, I want to declare $\alpha \in (0,1)$ and the $1-\alpha$ will also be positive and facilitate the following manipulation.
My question is, how to make further simplifications using the information given by the original equations?
In general, the solution to a simultaneous equation will not have one side of the equation in the solution. So I can only answer your question in this specific case. root is a dictionary and we will loop through all the values and substitute the RHS of the equations with the LHS.
import sympy as sp
x,y,z1,z2,alpha,beta = sp.symbols('x,y,z_1,z_2,alpha,beta',positive=True)
eq1 = x**alpha*y**(1-alpha) - z1
eq2 = x**beta*y**(1-beta) - z2
hat_x,hat_y,hat_z1 = sp.symbols('\hat{x},\hat{y},\hat{z_1}')
diff_eq1 = eq1.diff(x)*hat_x*x + eq1.diff(y)*hat_y*y + eq1.diff(z1)*hat_z1*z1
diff_eq2 = eq2.diff(x)*hat_x*x + eq2.diff(y)*hat_y*y + eq2.diff(z1)*hat_z1*z1
root = sp.solve([diff_eq1,diff_eq2],[hat_x,hat_y])
for key, value in root.items():
root[key] = value.subs({z1: x**alpha*y**(1-alpha), z2: x**beta*y**(1-beta)}).simplify()
BTW, how can I declare variables with ranges? For instance, I want to declare $\alpha \in (0,1)$ and the $1-\alpha$ will also be positive and facilitate the following manipulation.
There is no explicit way to do so in SymPy. There are a few work-arounds. See this Stack Overflow question.

How can I use the elements of a FiniteSet for my following calculations?

I'm trying to dissolve an equation using solveset(equation, variable), which will get me the value of the variable as result. As result I get an FiniteSet {value}. Is this FiniteSet accessible so that I can use the value (which is hopefully of the type float) for the next calculations?
The problem is the following:
I define three SymPy Symbols (drift1, drift2, drift3 = symbols('drift1 drift2 drift3')), which should be kind of placeholders for the following calculations. They have no values. They are part of two equations (equation1 and equation2, both are functions of drift1, drift2 and drift3).
My aim is to program an iteration loop to optimize all three symbols drift1, drift2 and drift3 by solving both equations and use the results for the next iteration step. For this, I define three Python variables x, y and z, the initial values of a and y are 0.0188 and 0.0099. z is a function of x and y and will be calculated new with every iteration step.
In the first step z is calculated with x and y (and other variables I defined in the code) and I substitute drift2 and drift3 by y and z in equation1 (equation is now a function of drift1). By activating equation1=0towards drift1, I'm using solveset(equation1.subs(drift2, y).subs(drift3, z), drift1) and I get a FiniteSet, which contains the result. I will use this result for solving the second equation by doing solveset(equation2.subs(drift1, result from FiniteSet).subs(drift3, z), drift2). This does not work because the result is not a float variable but sympy.sets.sets.FiniteSet-type.
Can anyone tell me how I can use the value of the FiniteSet ('inside' the FiniteSet; {value}) for the next calculations? I use Pyhton 3 and SymPy.
import numpy as np
from sympy import *
import scipy as sp
drift1, drift2, drift3 = symbols('drift1 drift2 drift3')
init_printin(use_unicode=True)
equation1 = 0.005*(drift1*(-23.88*drift2*(15.16*drift3 + 1.15)-20.31*drift3
+00.47*drift2*(15.16*drift3+1.15)+1.03*drift3+0.05))/drift1
equation2 = 0.005*(drift1*(35.73*drift2*(-13.79*drift3 + 0.86)+7.91*drift3+2.09)
+1.65*drift2*(-13.79*drift3+0.86)+0.75*drift3+0.07)/drift1
x, y = 0.0188, 0.0099
gesamtlaenge = 1.676
laenge1 = 0.04
laenge2 = 0.02
# the loop for the iteration is not included in this code
# the only thin I wanna know is how to substitute drift1 by the solution of
# the first calculation sol1
z = gesamtlaenge-laenge1-laenge2-x-y
expr1 = equation1.subs(drift2, y).subs(drift3, z)
sol1 = solveset(equation, drift1)
# up to this point, the code is running, but now, I get a FiniteSet {0.047} as
# result for sol1 and I wanna use this value to substitute drift1 in the next calculation
expr2 = equation2.subs(drift1, sol1).subs(drift3, z)
sol2 = solveset(equation, drift2)
print(drift1, drift2, drift3)
When I execute expr2 = equation2.subs(drift1, sol1).subs(drift3, z), I get equation2 as a function of drift1 and drift2, because it cannot use the value in FiniteSet {0,047} (0.047 is the value I need). I understand why this is the case but I have no solution.
I'm thankful for any help! Cheers
You can access the element(s) of a FiniteSet by converting to a list. In this case, where there is one solution, list(sol1).pop() will work:
>>> sol1 = FiniteSet(1)
>>> x.subs(x, list(sol1).pop())
1

Fenics help: Writing a list of data into Expression for nonlinear part in fenics?

I'm trying to solve a nonlinear problem in fenics. Instead of knowing the nonlinear function as an expression, I only know the values in the form of data.
In other words, if i am solving nabla(k(u).nabla(u)) = C, I do not know k(u) or cannot write it in terms of x[0] etc, I only know corresponding values of k for all values of u.
At the moment i have written some interpolating function and called it into 'k' which can project it to a function space, but it does not seem to work when i put it into the variational form and solve.
Below is some code to clarify the problem: I was using method of manufactured solutions where u=x^2 with k=1+u^2 as a test, where k_data = list of data for u=[0,(1+xmax^2)].
I've been told i can look into subclasses in Expression but i have no idea how to do this without knowing it in terms of x[0]. please help!
u = Function(V)
v = TestFunction(V)
u.interpolate(Expression("x[0]"))
k = interpolate_table(u,kappa_data)
plot(project(k,V))
C = Expression("-2.0-10.0*x[0]*x[0]*x[0]*x[0]")
diff_part = k*inner(grad(u),grad(v))*dx
source_part = C*v*dx
Res = diff_part - source_part
J = derivative(Res,u)
problem = NonlinearVariationalProblem(Res, u, bcs, J)
solver = NonlinearVariationalSolver(problem)
solver.solve()
prm = solver.parameters['newton_solver']
prm['relative_tolerance'] = 1E-6
prm['absolute_tolerance'] = 1E-6
prm['maximum_iterations'] = 100

lambdify a sympy expression that contains a Derivative of UndefinedFunction

I have several expressions of an undefined function some of which contain the corresponding (undefined) derivatives of that function. Both the function and its derivatives exist only as numerical data. I want to make functions out of my expressions and then call that function with the corresponding numerical data to numerically compute the expression. Unfortunately I have run into a problem with lambdify.
Consider the following simplified example:
import sympy
import numpy
# define a parameter and an unknown function on said parameter
t = sympy.Symbol('t')
s = sympy.Function('s')(t)
# a "normal" expression
a = t*s**2
print(a)
#OUT: t*s(t)**2
# an expression which contains a derivative
b = a.diff(t)
print(b)
#OUT: 2*t*s(t)*Derivative(s(t), t) + s(t)**2
# generate an arbitrary numerical input
# for demo purposes lets assume that s(t):=sin(t)
t0 = 0
s0 = numpy.sin(t0)
sd0 = numpy.cos(t0)
# labdify a
fa = sympy.lambdify([t, s], a)
va = fa(t0, s0)
print (va)
#OUT: 0
# try to lambdify b
fb = sympy.lambdify([t, s, s.diff(t)], b) # this fails with syntax error
vb = fb(t0, s0, sd0)
print (vb)
Error message:
File "<string>", line 1
lambda _Dummy_142,_Dummy_143,Derivative(s(t), t): (2*_Dummy_142*_Dummy_143*Derivative(_Dummy_143, _Dummy_142) + _Dummy_143**2)
^
SyntaxError: invalid syntax
Apparently the Derivative object is not resolved correctly, how can I work around that?
As an alternative to lambdify I'm also open to using theano or cython based solutions, but I have encountered similar problems with the corresponding printers.
Any help is appreciated.
As far as I can tell, the problem originates from an incorrect/unfortunate dummification process within the lambdify function. I have written my own dummification function that I apply to the parameters as well as the expression before passing them to lambdifying.
def dummify_undefined_functions(expr):
mapping = {}
# replace all Derivative terms
for der in expr.atoms(sympy.Derivative):
f_name = der.expr.func.__name__
var_names = [var.name for var in der.variables]
name = "d%s_d%s" % (f_name, 'd'.join(var_names))
mapping[der] = sympy.Symbol(name)
# replace undefined functions
from sympy.core.function import AppliedUndef
for f in expr.atoms(AppliedUndef):
f_name = f.func.__name__
mapping[f] = sympy.Symbol(f_name)
return expr.subs(mapping)
Use like this:
params = [dummify_undefined_functions(x) for x in [t, s, s.diff(t)]]
expr = dummify_undefined_functions(b)
fb = sympy.lambdify(params, expr)
Obviously this is somewhat brittle:
no guard against name-collisions
perhaps not the best possible name-scheme: df_dxdy for Derivative(f(x,y), x, y)
it is assumed that all derivatives are of the form:
Derivative(s(t), t, ...) with s(t) being an UndefinedFunction and t a Symbol. I have no idea what will happen if any argument to Derivative is a more complex expression. I kind of think/hope that the (automatic) simplification process will reduce any more complex derivative into an expression consisting of 'basic' derivatives. But I certainly do not guard against it.
largely untested (except for my specific use-cases)
Other than that it works quite well.
First off, rather than an UndefinedFunction, you could go ahead and use the implemented_function function to tie your numerical implementation of s(t) to a symbolic function.
Then, if you are constrained to discrete numerical data defining the function whose derivative occurs in the troublesome expression, much of the time, the numerical evaluation of the derivative may come from finite differences. As an alternative, sympy can automatically replace derivative terms with finite differences, and let the resulting expression be converted to a lambda. For example:
import sympy
import numpy
from sympy.utilities.lambdify import lambdify, implemented_function
from sympy import Function
# define a parameter and an unknown function on said parameter
t = sympy.Symbol('t')
s = implemented_function(Function('s'), numpy.cos)
print('A plain ol\' expression')
a = t*s(t)**2
print(a)
print('Derivative of above:')
b = a.diff(t)
print(b)
# try to lambdify b by first replacing with finite differences
dx = 0.1
bapprox = b.replace(lambda arg: arg.is_Derivative,
lambda arg: arg.as_finite_difference(points=dx))
print('Approximation of derivatives:')
print(bapprox)
fb = sympy.lambdify([t], bapprox)
t0 = 0.0
vb = fb(t0)
print(vb)
The similar question was discussed at here
You just need to define your own function and define its derivative as another function:
def f_impl(x):
return x**2
def df_impl(x):
return 2*x
class df(sy.Function):
nargs = 1
is_real = True
_imp_ = staticmethod(df_impl)
class f(sy.Function):
nargs = 1
is_real = True
_imp_ = staticmethod(f_impl)
def fdiff(self, argindex=1):
return df(self.args[0])
t = sy.Symbol('t')
print f(t).diff().subs({t:0.1})
expr = f(t) + f(t).diff()
expr_real = sy.lambdify(t, expr)
print expr_real(0.1)

Categories