Is there a standard way to implement sympy.solve
to solve a system of equations with respect to a specified subset of free symbols (i.e. sympy.core.symbol.Symbol
instances), such that it only finds solutions that are valid for any value attained by remaining free symbols in the equations that were not in the specified solve set? That is, I would like it not to return solutions that are only valid subject to additional constraints on the remaining variables.
For example, if the equations system eqns=[eqn1,eqn2]
involves two free variables var1
and var2
, is there a way to solve
w.r.t. var1
, such that any solution returned solves the full system for all var2
values? The intuitive
solve([eqn1,eqn2],[var1])
does not necessarily achieve this, because depending on [eqn1,eqn2]
it may return solutions in var1
that only solve the system subject to hidden/unreported constraints on var2
.
While I can think of ways to program an implementation that filters out such "conditionally valid" solutions (e.g., by taking an initially found solution and substituting back into the equation system and then checking if it becomes trivial), my work-arounds are rather tedious and computationally heavy. Presumably it could be done more efficiently if integrated into the existing solve algorithms, so I wonder if there is not a standard approach for this built into SymPy already.
Here are two concrete examples demonstrating that solve([eqn1,eqn2],[var1])
does not work for this task in general:
Example 1:
from sympy import solve, symbols
x,y=symbols('x y')
eqns = [x,y]
solve_variables = [x]
solve(eqns,solve_variables)
returns {x: 0}
, but {x: 0}
only solves the system (x=0, y=0) subject to the additional unreported constraint {y: 0}
. There are no solutions that work for all y
, so I am looking for a solve implementation that returns "no solution" in some format.
Example 2:
from sympy import solve, symbols
x,y=symbols('x y')
eqns = [x,x+y]
solve_variables = [x]
solve(eqns,solve_variables)
returns []
. This time the result is of a form I am wanting in general, i.e., no solution in x
because there is no solution working for all y
.
What the returns from these two examples represent mathematically in relation to their respective equation systems is different categorically, which makes it difficult to implement solve into some computational workflows programatically.
For reference, I am working with SymPy version 1.13.3.
From what you are saying it sounds like solutions "valid for all equations" must set all equations to 0. So what you would need to do (and cannot be assured of in general) is to see if the given solution satisfies all equations and only keep it if it does:
from sympy import solve, symbols
x,y=symbols('x y')
eqns = [x,y]
solve_variables = [x]
sols = solve(eqns,solve_variables, dict=True) # list of dict giving solutions
general = []
for s in sols:
if all(e.xreplace(s).equals(0) for e in eqns):
general.append(s)
>>> print(general)
[]
If you change your second equation to x*y
then the general solution will be [{x:0}]
.