I want to convert all kinds of mathematical equations to any given variable within that quation using Python. I want this to work with equations with multiple variables and with all kinds of mathematical functions like quadratic function, trigonometric functions, exponentiell functions, logarithmic functions, fractures and so on.
If that makes a difference for your solution: I also want to solve to a variable that is in a trigonometric function, however I've got something for this, so thats NOT the focus on this question.
As example, lets use:
a<=((b-c)/2)*tan(d)
and solve it for b.
Alternatively solve it for d.
Another example would be:
a/b<=c
and solve it for b.
I tried using sympy to do this. This is my code:
import numpy as np
import math
import sympy as sy
from sympy import *
a = sy.symbols('a')
b = sy.symbols('b')
c = sy.symbols('c')
d = sy.symbols('d')
constraint_equation = 'a<=((b-c)/2)*tan(d)'
active_variable = 'b'
operations = ["==", "!=", "<=", ">=", "<", ">"]
for i in operations:
if constraint_equation.find(i) != -1:
operation = i
break
con = constraint_equation.replace(" ", "").split(operation)
if operation == '==':
eq = sy.Eq(eval(con[0]), eval(con[1]))
result = sy.solve(eq, active_variable)
result = str(result[0])
constraint_equation = active_variable + operation + result
elif operation == '!=':
eq = sy.Ne(eval(con[0]), eval(con[1]))
result = sy.solve(eq, active_variable)
constraint_equation = str(result)
if constraint_equation[0] == 'N' and constraint_equation[1] == 'e':
constraint_equation = constraint_equation[3:]
constraint_equation = constraint_equation[:-1]
constraint_equation = constraint_equation.replace(',', operation)
else:
if operation == '<=':
eq = sy.Le(eval(con[0]), eval(con[1]))
elif operation == '>=':
eq = sy.Ge(eval(con[0]), eval(con[1]))
elif operation == '<':
eq = sy.Lt(eval(con[0]), eval(con[1]))
elif operation == '>':
eq = sy.Gt(eval(con[0]), eval(con[1]))
result = sy.solve(eq, active_variable)
constraint_equation = str(result)
i = constraint_equation.find('&')
if constraint_equation.find('&') != -1 and constraint_equation[i-2] == 'o' and constraint_equation[i-3] == 'o' and constraint_equation[i-4] == '<' or constraint_equation.find('&') != -1 and constraint_equation[1] == '-' and constraint_equation[2] == 'o' and constraint_equation[3] == 'o' and constraint_equation[4] == '<':
constraint_equation = constraint_equation[i+2:-1]
if constraint_equation[-2] == 'o' and constraint_equation[-3] == 'o' and constraint_equation[-4] == '<':
constraint_equation = constraint_equation[1:i-1]
My problem is that sometimes the inequalities of '<, >, <=, >=' are not solved intirely. In this example the output is:
-b*tan(d)/2 >= -a - c*tan(d)/2
What I want to get is:
b >= (2*a+c*tan(d))/tan(d)
I think the problem is, that SymPy won't divide by a factor of an unknown sign when trying to solve an inequality.
Is there any way to make Sympy do it while assuming, that the factor would be positive (and for example if 'b' is positive, then dividing by '-b' would be dividing by something negative)?
Or is there a way to check if / how many times an equation is divided or multiplied by (-1)? So that I could solve every inequality as an equality and depending on if the equation was divided / multipied by (-1) I could change the sign to what it should be (by knowing what it was before)?
Or is there an entirely different way to achieve my goal?
I tried defining the variables as:
a = Symbol('a', positive=True)
b = Symbol('b', positive=True)
c = Symbol('c', positive=True)
d = Symbol('d', positive=True)
But when I try to convert the equation
a/b<=c
to b, I get an Error:
NotImplementedError:
inequality has more than one symbol of interest.