Sympy - How to solve a system of equations in terms of x - python

I want to solve a system of equations with multiple variables.
The solution I'm looking for is in this form y = f(z).
The problem is: sympy won't solve completely my equations.
Here's a small example to illustrate my problem.
x = sympy.symbols("x", real=True)
y = sympy.symbols("y", real=True)
z = sympy.symbols("z", real=True)
eq0 = y - x**2
eq1 = x - z + 4
system = [eq0, eq1]
sympy.solve(system, y)[y]
This code produces y = x^2, which is mathematically correct, but not what I wanted.
What I want to see is my system solved like this y = f(z) therefore (y = (z - 4)^2).
Is there a way to define input and output in sympy's solvers?
Something like this:
sympy.solve(equations, input=z, ouptut=y)
Small note about substitution:
In this naive example, I could substitute the intermediate variable x with z+4 to solve the problem.
That said, I would prefer an alternative solution because, in my real problem, my system has 36 equations and substituting would be difficult.

You need to tell solve the variables to solve for.
eq0 = y - x**2
eq1 = x - z + 4
system = [eq0, eq1]
# solve your system of equation for x, y
solve(system, [x, y], dict=True)[0][y]
# out: (z - 4)^2

Related

how to solve non-linear inequalities with python like 12<x*y<14 and 2x + 3y>40?

I want to solve a system of nonlinear inequality equations, Simplify as follows:
12<xy<14 and 2x + 3*y>40, is there any way to find the minimum of x using python,
i konw how to solve linear inequality quations with scipy.optimize.linprog,but i can't find the way to solve non-linear inequality quations,thanks
Z3 is a SAT/SMT solver that could be interesting for this type of problems.
Here is an example looking for integer solutions. Note that the given equations are unbounded for floats.
from z3 import Optimize, Int, And
opt = Optimize()
x = Int('x')
y = Int('y')
opt.add(And(x * y > 12, x * y < 14))
opt.add(2 * x + 3 * y > 40)
opt.minimie(x)
print(opt.check()) # prints sat
print(opt.model()) # prints [y = 13, x = 1]

Program to find shortest distance from f(x) to origin

In Python (3.8) I try make a script that takes a function f(x) as input, e.g;
f(x) = 1/x
If we define the define y = f(x), as a line on the euclidean space, we can calculate the distance d() from the origin (0,0) for each point (x,f(x)) on the line as;
d(x,y) = sqrt(x^2+(f(x))^2)
My goal is to find the x such that the above distance is minimised. This can be done by solving
2x+2f(x)*f'(x) = 0
I will be grateful for help. Thanks.
Example in sympy (not expert on sympy);
from sympy import *
from sympy.solvers import solve
x, y, z = symbols('x y z')
g = 1/x
h = 2*x + (2*g) * (diff(g,x))
solve(h,x)
This will return [-1, 1, -I, I] so -1 and 1 should be real answers;
distance = x**2 + g**2
distance.subs(x,1)
distance.subs(x,-1)
I did not sqrt() in distance, but I hope you get an idea how this could be solved in sympy . This is 1 way, there are package to approximate the derivative, and find roots, which should also work.

How to create the equivalent of Excel Solver valueof function?

I have the following equation: x/0,2 * (0,2+1)+y/0,1*(0,1+1) = 26.34
The initial values of X and Y are set as 4.085 and 0.17 respectively.
I need to find the values of X and Y which satisfy the equation and have the lowest common deviation from initially set values. In other words, sum of |4.085 - x| and |0.17 - y| is minimized.
With Excel Solver Valueof Function this easy to find:
we insert x and y as variables to be changed to reach 26 in the formula result
Here is my python code (I am trying to use sympy for that)
x,y = symbols('x y')
eqn = solve([Eq(x/0.2*(0.2+1)+y/0.1*(0.1+1),26)],x,y)
print(eqn)
I am getting however strange result {x: 4.33333333333333 - 1.83333333333333*y}
Can anyone help me solve this equation?
The answer you are obtaining is not strange, it is just the answer to what you ask. You have an equation on two variables x and y, the solution to this problem is in general not unique (sometimes infinite). Now, you can either add an extra condition (inequality for example) or change the numeric Domain in which solutions are possible (like in Diophantine equations). You can do either of them in Sympy, in the following example I find the solution on x to your problem in the Real domain, using solveset:
from sympy import symbols, Eq, solveset
x,y = symbols('x y')
eqn = solveset(Eq(1.2 * x / 0.2 + 1.1 * y / 0.1, 26), x, Reals)
print(eqn)
Output:
Intersection(FiniteSet(4.33333333333333 - 1.83333333333333*y), Reals)
As you can see the solution on x is a finite set, that is the intersection between a straight line on y and the Reals. Any particular solution can be found by direct evaluation of y.
This is equivalent to say x = 4.33333333333333 - 1.83333333333333 * y if you evaluate this equation in the guess value y = 0.17, you obtain x = 4.0216 (close to your x = 4.085 guess value).
Edit:
After analyzing the new information added to your question, I think I have finally understood it: your problem is a constrained optimization. Now, I don't use Excel frequently, but it would be my bet that under the hood this optimization is carried out there using Lagrange multipliers. In your particular case, the target function represents the deviation of the solution (x, y) from the point (4.085, 0.17). For convenience, I have chosen this function to be the Euclidean distance between them (absolute values as you suggested can be problematic due to discontinuity of the derivatives). The constraint function is simply the equation you provided. To solve this problem with Sympy, one could use something like this:
import sympy as sp
# Define symbols and functions
x, y, lamb = sp.symbols('x, y, lamb', real=True)
func = sp.sqrt((x - 4.085) ** 2 + (y - 0.17) ** 2) # Target function
const = 1.2 * x / 0.2 + 1.1 * y / 0.1 - 26 # Constraint function
# Define Lagrangian
lagrang = func - lamb * const
# Compute gradient of Lagrangian
grad_lagrang = [sp.diff(lagrang, var) for var in [x, y, lamb]]
# Solve the resulting system of equations
spoints = sp.solve(grad_lagrang, [x, y, lamb], dict=True)
# Print stationary points
print(spoints)
Output:
[{x: 4.07047770700637, lamb: -0.0798086884467563, y: 0.143375796178345}]
Since in our case only one stationary point was found, this is the optimal solution (although this is only a necessary condition). The value of the lamb multiplier can be ditched, so x, y = 4.070, 0.1434. Hope this helps.

python : intersection geometrical objects in 3D space

Definition of the problem
I am trying to calculate the points of intersection of geometrical objects, such as two planes and a sphere, in python.
Let's consider for example these three objects:
This system gives two solutions:
I would like to know if there is a python library that can help develop a solver to calculate these intersections. I am looking for something working as Wolfram alpha, where we can input three equations and it returns all the possible solutions when there's finite number of solutions for simplicity.
What I tried
I tried with SymPy, but it returns []:
from sympy.solvers import solve
from sympy import Symbol
x = Symbol('x')
y = Symbol('y')
z = Symbol('z')
solve(z, x, x**2 + y**2 + z**2 -1)
I then tried with scipy:
from scipy.optimize import fsolve
def f(x):
y = np.zeros(3)
y[2] = x[2]
y[0] = x[0]
y[1] = x[0] ** 2 + x[1] ** 2+ x[2] ** 2 - 1
return y
x0 = np.array([10, 10, 10])
solution = fsolve(f, x0)
print(solution[0],solution[1],solution[2])
but it only returns one of the two solutions:
6.79746218330325e-28 1.0000000000000002 -2.3528179942097343e-35
I also tried with gekko, and stil it only returns one possible solution (which depends on the initial guess):
from gekko import GEKKO
m = GEKKO()
x = m.Var(value = 1)
y = m.Var(value = 1)
z = m.Var(value = 1)
m.Equation(x == 0)
m.Equation(z == 0)
m.Equation(x**2 + y**2+z**2 ==1)
m.solve()
fsolve from scipy, and all other functions that I personally know of that will accept any form of input function, will return one value.
One workaround if you have an idea where the other solution is would be to give an x0 value that is closer to the second solution with a second call to fsolve (see https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.fsolve.html).
If you alternatively know what range you want to try and find solutions in, the easiest way is to make an array that you then check to see where the value changes sign (this would be doing it from scratch)
I found the solution with sympy. Apparently it's one of the only (if not only) libraries that allow finding analytical solutions, and returns more than just one solution. Also, we don't need to pass guesses as initial variables. In my question, there was an error in the example I posted with sympy. This is how I solved the system:
from sympy.solvers import solve
import sympy as sp
x = Symbol('x')
y = Symbol('y')
z = Symbol('z')
sp.solve([z , x, (x**2 + y**2 + z**2) - 1], x,y,z)
Result: [0,-1,0], [0,1,0]

how to solve first-order linear differential equations analytically and numerically with sympy?

How can simple linear differential equations like this one be solved in sympy?
y' + p(t)y = q(t)
I'm looking to solve it in two ways: symbolically (analytically) if possible, if sympy can derive the integrating factor, etc., and also a way to do it numerically so that the two can be compared. how can this be done in sympy? is sympy.mpmath.odefun the right place to look?
Here and here are some examples.
As for your problem, you can write your equation like:
y' + p(t)y - q(t) = 0
and then use dsolve().
import sympy
t = sympy.Symbol('t')
y = sympy.Function('y')(t)
p = sympy.Function('p')(t)
q = sympy.Function('q')(t)
y_ = sympy.Derivative(y, t)
# y' + p(t)y - q(t)
sol = sympy.dsolve(y_ + p*y - q, y)
print(sol)
Solution as function
(Note : This is a quick solution i came up with by reading the documentation. I am not experienced with sympy. There might be much better ways to do the following.)
Suppose you want to solve y' = y.
from sympy import *
t = symbols('t')
y = Function('y')(t)
y_ = Derivative(y, t)
sol = dsolve(y_ - y, y)
We did the same as previously. Now, to use the second part of the sol, we use .args[1]. Then we create a function f(t_) and substitute the t value using subs().
def f(t_):
return sol.args[1].subs([(t, t_)])
print(sol)
print(f(0))

Categories

Resources