Mathematica has a symbolic solver for quadratic (and maybe other) functions, e.g.:
Minimize[2 x^2 - y x + 5, {x}]
will yield the following solution:
{1/8 (40-y^2),{x->y/4}}
Is this feature supported in SymPy or a derivative library? Or I have to implement it myself?
Thanks a lot for your opinion!
I'm not sure about the generality of this approach, but the following code:
import sympy
from sympy.solvers import solve
x = sympy.var('x')
y = sympy.var('y')
f = 2*x**2 - y*x + 5
r = solve(f.diff(x), x)
f = f.subs(x, r[0])
print(f)
print(r)
Outputs:
-y**2/8 + 5
[y/4]
The first line of output (-y**2/8 + 5) is equivalent to Mathematica's 1/8 (40-y^2), just ordered differently.
The second line ([y/4]) is similar to Mathematica's {x->y/4} (solve returns a list of roots)
The idea is that we first take the partial derivative of f with respect to x, then substitute it into the original function.
Related
from sympy import Symbol
from sympy.solvers import solveset
x = Symbol('x')
equation = x**2 - 2*x + 1
result = solveset(equation, x)
Here, result evaluates to FiniteSet(1).
Since this is a quadratic equation, there must be 2 roots.
But also, since the two roots are the same (1 in this case), the result returns it only once.
For the purpose of solving linear recurrences, I need to know the repeated roots, and how many times did each one of them repeat.
How to do that?
You can convert it into a polynomial and then use the roots function, which will return a dictionary that has the roots as keys and the multiplicities as values, like so:
from sympy import roots
poly = equation.as_poly()
roots(poly)
# returns {1: 2}
Unlike nroots, this works with polynomials with symbolic coefficients as well:
from sympy.abc import a, b, c
poly = (a * x ** 2 - 2 * sqrt(a * c) * x + c).as_poly(x)
roots(poly, x)
# returns {sqrt(a*c)/a: 2}
I have a function that should compute an integral, taking in some function as input. I'd like the code to compute a definite integral of: <some function, in terms of x. e.g., 3*x or 3*x*(1-x), etc.> * np.sin(np.pi * x)). I'm using scipy for this:
import scipy.integrate as integrate
def calculate(a):
test = integrate.quad(a*np.sin(np.pi * x), 0, 1)
return test
a = lambda x: 3*x
calculate(a)
Now this implementation will fail because of the discrepancy between a and x. I tried defining x as x = lambda x: x, but that won't work because I get an error of multiplying a float by a function.
Any suggestions?
Since you are trying to combine two symbolic expressions before computing the definite integral numerically, I think this might be a good application for sympy's symbolic manipulation tools.
from sympy import symbols, Integral, sin, pi
def calculate(a_exp):
test = Integral(a_exp * sin(pi * x), (x, 0, 1)).evalf()
return test
x = symbols('x')
a_exp = 3*x
print(calculate(a_exp))
# 0.954929658551372
Note: I changed the name of a to a_exp to make it clear that this is an expression rather than a function.
If you decide to use sympy then note that you might also be able to compute the expression for the integral symbolically as well.
Update: Importing Sympy might be overkill for this
If computation speed is more important than precision, you can easily calculate the integral approximately using some simple discretized method.
For example, the functions below calculate the integral approximately with increasingly sophisticated methods. The accuracy of the first two will improve as n is increased and also depends on the nature of a_func etc.
import numpy as np
from scipy.integrate import trapz, quad
def calculate2(a_func, n=100):
dx = 1/n
x = np.linspace(0, 1-dx, n)
y = a_func(x) * np.sin(np.pi*x)
return np.sum(y) * dx
def calculate3(a_func, n=100):
x = np.linspace(0, 1, n+1)
y = a_func(x) * np.sin(np.pi*x)
return trapz(y, x)
def calculate4(a_func):
f = lambda x: a_func(x) * np.sin(np.pi*x)
return quad(f, 0, 1)
a_func = lambda x: 3*x
print(calculate2(a_func))
# 0.9548511174430737
print(calculate3(a_func))
# 0.9548511174430737
print(calculate4(a_func)[0])
# 0.954929658551372
I'm not an expert on numerical integration so there may be better ways to do this than these.
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 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))
it is commonly an easy task to build an n-th order polynomial
and find the roots with numpy:
import numpy
f = numpy.poly1d([1,2,3])
print numpy.roots(f)
array([-1.+1.41421356j, -1.-1.41421356j])
However, suppose you want a polynomial of type:
f(x) = a*(x-x0)**0 + b(x-x0)**1 + ... + n(x-x0)**n
Is there a simple way to construct a numpy.poly1d type function
and find the roots ? I've tried scipy.fsolve but it is very unstable as it depends highly on the choice of the starting values
in my particular case.
Thanks in advance
Best Regards
rrrak
EDIT: Changed "polygon"(wrong) to "polynomial"(correct)
First of all, surely you mean polynomial, not polygon?
In terms of providing an answer, are you using the same value of "x0" in all the terms? If so, let y = x - x0, solve for y and get x using x = y + x0.
You could even wrap it in a lambda function if you want. Say, you want to represent
f(x) = 1 + 3(x-1) + (x-1)**2
Then,
>>> g = numpy.poly1d([1,3,1])
>>> f = lambda x:g(x-1)
>>> f(0.0)
-1.0
The roots of f are given by:
f.roots = numpy.roots(g) + 1
In case x0 are different by power, such as:
f(x) = 3*(x-0)**0 + 2*(x-2)**1 + 3*(x-1)**2 + 2*(x-2)**3
You can use polynomial operation to calculate the finally expanded polynomial:
import numpy as np
import operator
ks = [3,2,3,2]
offsets = [0,2,1,2]
p = reduce(operator.add, [np.poly1d([1, -x0])**i * c for i, (c, x0) in enumerate(zip(ks, offsets))])
print p
The result is:
3 2
2 x - 9 x + 20 x - 14