Sympy linsolve with empty output for a system of overdetermined equations

Question:

I have a system of 6 linear equations with 4 variables (a4,a5,a6,a7). I tried to solve the system for these variables with sympy linsolve, however the output is empty. Here is my working example:

from sympy import symbols, linsolve, Eq, sqrt

b4, b5, b6, b7, b8, b9 = symbols('b4,b5,b6,b7,b8,b9')
a4,a5,a6,a7 = symbols('a4,a5,a6,a7',real=True)

eq4 = Eq(b4, a5 + a6/4 + a7/4)
eq5 = Eq(b5, a4 + a6/4 + a7/4)
eq6 = Eq(b6, a7 + a4/4 + a5/4)
eq7 = Eq(b7, a6 + a4/4 + a5/4)
eq8 = Eq(b8, 3*(a4 + a5 + a6 + a7)/4)
eq9 = Eq(b9, sqrt(3)/4*(a4 + a5 - a6 - a7))

display(eq4,eq5,eq6,eq7,eq8,eq9)

eqs = (eq4,eq5,eq6,eq7,eq8,eq9)
sol = linsolve(eqs, a4,a5,a6,a7)
display(sol)

The display output for sol is empty as I said. Is there any mistake in my code? Thanks in advance.

Asked By: Marcos

||

Answers:

This is the system of equations as a matrix equation in echelon form:

In [5]: A, b = linear_eq_to_matrix(eqs, [a4, a5, a6, a7])

In [6]: Matrix.hstack(A, b)
Out[6]: 
⎡ 0     -1   -1/4  -1/4  -b₄⎤
⎢                           ⎥
⎢ -1    0    -1/4  -1/4  -b₅⎥
⎢                           ⎥
⎢-1/4  -1/4   0     -1   -b₆⎥
⎢                           ⎥
⎢-1/4  -1/4   -1    0    -b₇⎥
⎢                           ⎥
⎢-3/4  -3/4  -3/4  -3/4  -b₈⎥
⎢                           ⎥
⎢-√3   -√3    √3    √3      ⎥
⎢────  ────   ──    ──   -b₉⎥
⎣ 4     4     4     4       ⎦

In [7]: Matrix.hstack(A, b).echelon_form()
Out[7]: 
⎡-1  0   -1/4  -1/4                 -b₅                ⎤
⎢                                                      ⎥
⎢0   -1  -1/4  -1/4                 -b₄                ⎥
⎢                                                      ⎥
⎢                               b₄   b₅                ⎥
⎢0   0   1/8   -7/8             ── + ── - b₆           ⎥
⎢                               4    4                 ⎥
⎢                                                      ⎥
⎢                           b₄   b₅   7⋅b₆   b₇        ⎥
⎢0   0    0    -3/4         ── + ── - ──── - ──        ⎥
⎢                           4    4     8     8         ⎥
⎢                                                      ⎥
⎢                      3⋅b₄   3⋅b₅   3⋅b₆   3⋅b₇   3⋅b₈⎥
⎢0   0    0     0    - ──── - ──── - ──── - ──── + ────⎥
⎢                       64     64     64     64     32 ⎥
⎢                                                      ⎥
⎣0   0    0     0                    0                 ⎦

The second to last row is all zeros and then nonzero which implies that the system of equations is inconsistent unless that combination of the b parameters happens to be equal to zero.

The solution returned by linsolve applies for "generic" values of the parameters i.e. for almost all possible values of b1, b2, etc. this expression will not be equal to zero:

In [10]: e = Matrix.hstack(A, b).echelon_form()[4,4]

In [11]: e
Out[11]: 
  3⋅b₄   3⋅b₅   3⋅b₆   3⋅b₇   3⋅b₈
- ──── - ──── - ──── - ──── + ────
   64     64     64     64     32 

In other words for almost all values of the symbolic parameters your system of equations is inconsistent so linsolve returns the empty set.

If you want to assume that the parameters takes values such that the system is consistent then you can use this echelon form with the last two rows discarded:

In [13]: Maug = Matrix.hstack(A, -b).echelon_form()[:4,:]

In [14]: Maug
Out[14]: 
⎡-1  0   -1/4  -1/4           b₅          ⎤
⎢                                         ⎥
⎢0   -1  -1/4  -1/4           b₄          ⎥
⎢                                         ⎥
⎢                         b₄   b₅         ⎥
⎢0   0   1/8   -7/8     - ── - ── + b₆    ⎥
⎢                         4    4          ⎥
⎢                                         ⎥
⎢                      b₄   b₅   7⋅b₆   b₇⎥
⎢0   0    0    -3/4  - ── - ── + ──── + ──⎥
⎣                      4    4     8     8 ⎦

In [15]: linsolve(Maug)
Out[15]: 
⎧⎛  b₄   7⋅b₅   b₆   b₇    7⋅b₄   b₅   b₆   b₇  b₄   b₅   b₆   7⋅b₇  b₄   b₅   7⋅b₆   b₇⎞⎫
⎨⎜- ── - ──── + ── + ──, - ──── - ── + ── + ──, ── + ── - ── - ────, ── + ── - ──── - ──⎟⎬
⎩⎝  6     6     3    3      6     6    3    3   3    3    6     6    3    3     6     6 ⎠⎭

Alternatively using the original equations you can simply allow some of the b symbols to be treated as unknowns rather than as parameters:

In [19]: linsolve(eqs, [a4, a5, a6, a7, b4, b7])
Out[19]: 
⎧⎛     b₈   √3⋅b₉        5⋅b₈   √3⋅b₉        5⋅b₈   √3⋅b₉       b₈   √3⋅b₉             √3⋅b₉             √3⋅b₉⎞⎫
⎨⎜b₅ - ── + ─────, -b₅ + ──── + ─────, -b₆ + ──── - ─────, b₆ - ── - ─────, -b₅ + b₈ + ─────, -b₆ + b₈ - ─────⎟⎬
⎩⎝     6      6           6       2           6       2         6      6                 3                 3  ⎠⎭

The extra degrees of freedom in choosing values for these parameters makes it possible to find a consistent solution to the equations. With this method parameters that you choose (i.e. b4 and b7 above) will be eliminated from the expression for the solution.

Answered By: Oscar Benjamin