I am working on a script to try and solve a quadratic form, where it is highly suspected that the values of the variables can only be 1 or -1. I can easily get this restriction with SymPy, but for many cases either 1 or -1 work in at least one solution set. I want to know if any of the variables' value is fixed or only has 1 solution.
For Example, we have the equation list and the valid solutions for (ep0c1, ep0c2, ep1c2)
returned by solve:
[ep0c1**2 - 1, ep0c2**2 - 1, ep1c2**2 - 1, 25*ep1c2 + 25]
[(-1, -1, -1), (-1, 1, -1), (1, -1, -1), (1, 1, -1)]
Here, in all valid solutions, ep1c2 = -1
. I want to know which variables satisfy this property, where there is only one valid value.
Sadly, solving for singular variables is not working properly with the other free variables. Going through the answers manually is working but it can lead to an exponential running time on the number of variables. Anyone know how to check easily if a single variable has a fixed value in SymPy?
If a variable x
is "fixed" in an expression (i.e. has a rational value it sounds like from your description) it will appear as a factor x-n
where n
is some numerical expression. Try to factor your expression
from sympy.abc import *
from sympy import *
>>> factor(-a*x + a + x**2 - x)
(-a + x)*(x - 1)
But in your case, you have a system of equations and you are looking for evidence that a single variable has a single value. Consider the Groebner basis of the equations:
>>> eqs=S('(ep0c1**2 - 1, ep0c2**2 - 1, ep1c2**2 - 1, 25*ep1c2 + 25)')
>>> g = groebner(eqs); g
GroebnerBasis([ep0c1**2 - 1, ep0c2**2 - 1, ep1c2 + 1], ep0c1, ep0c2, ep1c2, domain='ZZ', order='lex')
>>> [Poly(i).is_linear for i in g.exprs]
[False, False, True]
>>> g.exprs[-1]
ep1c2 + 1
>>> solve(_, dict=1)
[{ep1c2: -1}]
You can see from the reduced form of the equations that ep1c2
is a linear equation (hence, has only one solution).
Putting this into a function which accepts a list of equations looks like
def fixed_values(eqs):
"""return a dictionary of fixed values for the equations else
an empty dict (if there are no such values) for the system of
polynomial equations."""
from sympy import groebner, Poly
lin = [i for i in groebner(eqs).exprs if Poly(i).is_linear]
rv = {}
for i in lin[::-1]: # do last, first
rv.update(solve(i.subs(rv), dict=True)[0])
return rv
>>> fixed_values(eqs)
{ep1c2: -1}