Equation solver in Python - python

Given a simple equation such as:
x = y + z
You can get the third variable if you bind the other two (ie: y = x - z and z = x - y). A straightforward way to put this in code:
def solve(args):
if 'x' not in args:
return args['y'] + args['z']
elif 'z' not in args:
return args['x'] - args['y']
elif 'y' not in args:
return args['x'] - args['z']
else:
raise SomeError
I obviously can take an equation, parse it and simplify it to achieve the same effect.
But I believe in doing so I would be re-inventing the wheel. So where's my ready-made wheel?

Consider using Sympy. It includes various tools to solve equations and a lot more.
The following is an excerpt from the docs:
>>> from sympy import I, solve
>>> from sympy.abc import x, y
>>> solve(x**4-1, x)
[1, -1, -I, I]

Related

Python sympy symbols

When I use "x" and "z" as symbols, I have no problem with this code:
from sympy import *
x, z = symbols('x z')
y = -6*x**2 + 2*x*z**0.5 + 50*x - z
solve((diff(y, x), diff(y, z)))
y.subs({x: 5, z: 25})
But when I use "q" and "a", solve does not give me any solution.
q, a = symbols('q a')
y = -6*q**2 + 2*q*a**0.5 + 50*q - a
solve((diff(y, q), diff(y, a)))
y.subs({q: 5, a: 25})
As you can see I use "subs" to check that there is no typo in the objective function.
UPDATE: I used "Symbol" to set each variable individually, but again using "q" and "a" does not work.
# This works
x = Symbol('x')
z = Symbol('z')
y = -6*x**2 + 2*x*z**0.5 + 50*x - z
solve((diff(y, x), diff(y, z)))
# This does not work
q = Symbol('q')
a = Symbol('a')
y = -6*q**2 + 2*q*a**0.5 + 50*q-a
solve((diff(y, q), diff(y, a)))
Thank you.
Got it!
It all depends on an alphabetic order of your variables.
If you substitute x for z and z for x in your first example it will also stop working.
Internally solve sends the expression to the function _solve in sympy.solvers which then tries to solve your equation and fails many times.
Finally as a last effort what it does is it tries to solve -sqrt(a) + q or x - sqrt(z) by picking symbols from it through an internal function _ok_syms, with an argument that sorts those alphabetically (even without this argument it still would, but if wrapped with reversed it magically makes your examples works in the exactly opposite way).
And so it does solve x - sqrt(z) as x: sqrt(z) and -sqrt(a) + q as a: q**2.
While in the first case it ends up with an easily solvable 50 - 10*sqrt(z), in the second case it is lost on -12*q + 2*sqrt(q**2) + 50 as it is not able to simplify sqrt(q**2).
source:
a lot of testing on:
https://github.com/sympy/sympy/blob/master/sympy/solvers/solvers.py

How to know whether a function is continuous with sympy?

I need to define a function that checks if the input function is continuous at a point with sympy.
I searched the sympy documents with the keyword "continuity" and there is no existing function for that.
I think maybe I should consider doing it with limits, but I'm not sure how.
def check_continuity(f, var, a):
try:
f = sympify(f)
except SympifyError:
return("Invaild input")
else:
x1 = Symbol(var, positive = True)
x2 = Symbol(var, negative = True)
//I don't know what to do after this
I would suggest you use the function continuous_domain. This is defined in the calculus.util module.
Example usage:
>>> from sympy import Symbol, S
>>> from sympy.calculus.util import continuous_domain
>>> x = Symbol("x")
>>> f = sin(x)/x
>>> continuous_domain(f, x, S.Reals)
Union(Interval.open(-oo, 0), Interval.open(0, oo))
This is documented in the SymPy docs here. You can also view the source code here.
Yes, you need to use the limits.
The formal definition of continuity at a point has three conditions that must be met.
A function f(x) is continuous at a point where x = c if
lim x —> c f(x) exists
f(c) exists (That is, c is in the domain of f.)
lim x —> c f(x) = f(c)
SymPy can compute symbolic limits with the limit function.
>>> limit(sin(x)/x, x, 0)
1
See: https://docs.sympy.org/latest/tutorial/calculus.html#limits
Here is a more simple way to check if a function is continues for a specific value:
import sympy as sp
x = sp.Symbol("x")
f = 1/x
value = 0
def checkifcontinus(func,x,symbol):
return (sp.limit(func, symbol, x).is_real)
print(checkifcontinus(f,value,x))
This code output will be - False

Writing a function for x * sin(3/x) in python

I have to write a function, s(x) = x * sin(3/x) in python that is capable of taking single values or vectors/arrays, but I'm having a little trouble handling the cases when x is zero (or has an element that's zero). This is what I have so far:
def s(x):
result = zeros(size(x))
for a in range(0,size(x)):
if (x[a] == 0):
result[a] = 0
else:
result[a] = float(x[a] * sin(3.0/x[a]))
return result
Which...doesn't work for x = 0. And it's kinda messy. Even worse, I'm unable to use sympy's integrate function on it, or use it in my own simpson/trapezoidal rule code. Any ideas?
When I use integrate() on this function, I get the following error message: "Symbol" object does not support indexing.
This takes about 30 seconds per integrate call:
import sympy as sp
x = sp.Symbol('x')
int2 = sp.integrate(x*sp.sin(3./x),(x,0.000001,2)).evalf(8)
print int2
int1 = sp.integrate(x*sp.sin(3./x),(x,0,2)).evalf(8)
print int1
The results are:
1.0996940
-4.5*Si(zoo) + 8.1682775
Clearly you want to start the integration from a small positive number to avoid the problem at x = 0.
You can also assign x*sin(3./x) to a variable, e.g.:
s = x*sin(3./x)
int1 = sp.integrate(s, (x, 0.00001, 2))
My original answer using scipy to compute the integral:
import scipy.integrate
import math
def s(x):
if abs(x) < 0.00001:
return 0
else:
return x*math.sin(3.0/x)
s_exact = scipy.integrate.quad(s, 0, 2)
print s_exact
See the scipy docs for more integration options.
If you want to use SymPy's integrate, you need a symbolic function. A wrong value at a point doesn't really matter for integration (at least mathematically), so you shouldn't worry about it.
It seems there is a bug in SymPy that gives an answer in terms of zoo at 0, because it isn't using limit correctly. You'll need to compute the limits manually. For example, the integral from 0 to 1:
In [14]: res = integrate(x*sin(3/x), x)
In [15]: ans = limit(res, x, 1) - limit(res, x, 0)
In [16]: ans
Out[16]:
9⋅π 3⋅cos(3) sin(3) 9⋅Si(3)
- ─── + ──────── + ────── + ───────
4 2 2 2
In [17]: ans.evalf()
Out[17]: -0.164075835450162

Sympy: working with equalities manually

I'm currently doing a maths course where my aim is to understand the concepts and process rather than crunch through problem sets as fast as possible. When solving equations, I'd like to be able to poke at them myself rather than have them solved for me.
Let's say we have the very simple equation z + 1 = 4- if I were to solve this myself, I would obviously subtract 1 from both sides, but I can't figure out if sympy provides a simple way to do this. At the moment the best solution I can come up with is:
from sympy import *
z = symbols('z')
eq1 = Eq(z + 1, 4)
Eq(eq1.lhs - 1, eq1.rhs - 1)
# Output:
# z == 3
Where the more obvious expression eq1 - 1 only subtracts from the left-hand side. How can I use sympy to work through equalities step-by-step like this (i.e. without getting the solve() method to just given me the answer)? Any pointers to the manipulations that are actually possible with sympy equalities would be appreciated.
There is a "do" method and discussion at https://github.com/sympy/sympy/issues/5031#issuecomment-36996878 that would allow you to "do" operations to both sides of an Equality. It's not been accepted as an addition to SymPy but it is a simple add-on that you can use. It is pasted here for convenience:
def do(self, e, i=None, doit=False):
"""Return a new Eq using function given or a model
model expression in which a variable represents each
side of the expression.
Examples
========
>>> from sympy import Eq
>>> from sympy.abc import i, x, y, z
>>> eq = Eq(x, y)
When the argument passed is an expression with one
free symbol that symbol is used to indicate a "side"
in the Eq and an Eq will be returned with the sides
from self replaced in that expression. For example, to
add 2 to both sides:
>>> eq.do(i + 2)
Eq(x + 2, y + 2)
To add x to both sides:
>>> eq.do(i + x)
Eq(2*x, x + y)
In the preceding it was actually ambiguous whether x or i
was to be added but the rule is that any symbol that are
already in the expression are not to be interpreted as the
dummy variable. If we try to add z to each side, however, an
error is raised because now it is unclear whether i or z is being
added:
>>> eq.do(i + z)
Traceback (most recent call last):
...
ValueError: not sure what symbol is being used to represent a side
The ambiguity must be resolved by indicating with another parameter
which is the dummy variable representing a side:
>>> eq.do(i + z, i)
Eq(x + z, y + z)
Alternatively, if only one Dummy symbol appears in the expression then
it will be automatically used to represent a side of the Eq.
>>> eq.do(2*Dummy() + z)
Eq(2*x + z, 2*y + z)
Operations like differentiation must be passed as a
lambda:
>>> Eq(x, y).do(lambda i: i.diff(x))
Eq(1, 0)
Because doit=False by default, the result is not evaluated. to
evaluate it, either use the doit method or pass doit=True.
>>> _.doit == Eq(x, y).do(lambda i: i.diff(x), doit=True)
True
"""
if not isinstance(e, (FunctionClass, Lambda, type(lambda:1))):
e = S(e)
imaybe = e.free_symbols - self.free_symbols
if not imaybe:
raise ValueError('expecting a symbol')
if imaybe and i and i not in imaybe:
raise ValueError('indicated i not in given expression')
if len(imaybe) != 1 and not i:
d = [i for i in imaybe if isinstance(i, Dummy)]
if len(d) != 1:
raise ValueError(
'not sure what symbol is being used to represent a side')
i = set(d)
else:
i = imaybe
i = i.pop()
f = lambda side: e.subs(i, side)
else:
f = e
return self.func(*[f(side) for side in self.args], evaluate=doit)
from sympy.core.relational import Equality
Equality.do = do

Differentiating a product with an unknown function - sympy

I tried various searches but couldn't find a good google string to bring up the right results.
I have a product of the form
y = x*f(x)
where f is a function of x which is not known. I want sympy to differentiate y with respect to x. Does anyone know how I can do this?
How about:
>>> x = sympy.Symbol("x")
>>> f = sympy.Function("f")
>>> y = x * f(x)
>>> y
x*f(x)
>>> y.diff(x)
x*Derivative(f(x), x) + f(x)

Categories

Resources