jprockbelly jprockbelly - 1 month ago 12
Python Question

Solve set of simple equations given only a few variables

I have a set of a few hundred simple sum equations. For example here are 3:

w1 - u1 - u2 = 0
w1 + w2 - w3 - u3 = 0
w1 - w2 - w4 = 0


I am trying to find a way to solve as many as possible given only a few of the values. For example, in the above equation set if I have
u1
and
u2
I can calculate
w1
, but nothing else.
Given
u1
,
u2
and
w2
I can calculate
w1
and
w4
. And so forth...

Currently I'm approaching this in a fairly straight forward way (psudo code):

while there are new results:
for each equation:
try to solve equation:
if solved update result set


This works but feels clunky and inefficient.

Is there a better way? (using Python if that is relevant)

EDIT: I know this could be solved as series of linear equations, IF i know enough of the values. I'm looking for a method to use when I don't know enough to solve as a system of linear equations (or possibly there a fancy way to reduce the problem somehow)

EDIT 2: erroneous, deleted

EDIT 3: For anyone interested in my solution using sympy:

from sympy import linsolve, symbols, linear_eq_to_matrix


def my_solver(known_vals):
w1, w2, w3, w4, u1, u2, u3 = symbols("w1, w2, w3, w4, u1, u2, u3", integer=True)
variables = [w1, w2, w3, w4, u1, u2, u3]


eqns = [w1 - u1 - u2,
w1 + w2 - w3 - u3,
w1 - w2 - w4]

A, b = linear_eq_to_matrix(eqns, variables)
solution = linsolve((A, B), variables)

e= next(iter(answer))
for idx, x in enumerate(e):
print(variables[idx], x.subs(known_vals)) #this has a bug see comment below


my_solver({w1:2, u2:-2})


I noticed a bug in the approach, if I pass
{w1:2, u1: -10, u2:-2}
I get a solution no probs, even though these values violate the first equation! This doesn't matter for my use case (it might even be useful, since I am dealing with imprecise measured values), but mentioning it in case anyone else uses this approach.

Answer

Just get SymPy and stuff the whole system of linear equations into sympy.solvers.solveset.linsolve. It'll give you the whole solution space, including the values of variables with determined values, in a form dependent on whether the system has 0, 1, or infinite solutions.

There's probably also a NumPy/SciPy way to get the solution set of an underdetermined system, but whatever that way is, I don't know it. Google suggests a singular value decomposition would be useful, but I haven't figured out how you'd get a basis for the solution set out of that.