I have an equation system like the following:
For this specific system, I know that a nontrivial solution(s) only exists if p1 == p2, which is
.
However, how can I determine this in the general case using Sympy?
For this example, my implementation is as follows:
from sympy import Matrix, symbols, pprint, lcm, latex
from sympy.solvers import solve_linear_system
top_matrix = Matrix.zeros(8,7)
p1 = symbols("p1")
p2 = symbols("p2")
top_matrix[0,0] = 1
top_matrix[0,1] = -1
top_matrix[1,1] = (1-p1)
top_matrix[1,2] = -1
top_matrix[2,2] = 1
top_matrix[2,4] = p2-1
top_matrix[3,1] = p1
top_matrix[3,3] = -1
top_matrix[4,3] = 1
top_matrix[4,4] = -p2
top_matrix[5,4] = 1
top_matrix[5,5] = -1
top_matrix[6,1] = -1
top_matrix[6,6] = 1
top_matrix[7,4] = -1
top_matrix[7,6] = 1
pprint(top_matrix)
vars = symbols("a1, a2, a3, a4, a5, a6, a7, a8")
print solve_linear_system(top_matrix, *vars)
The result is
None
If I set
p2 = p1
the result is
{a1: -1, a5: -1, a2: -1, a6: -1, a3: p1 - 1, a4: -p1}
Is there some way to discover this requirement automatically?
After the symbols and equations are defined, we can use SymPy's solve() function to compute the value of x and y. The first argument passed to the solve() function is a tuple of the two equations (eq1, eq2) . The second argument passed to the solve() function is a tuple of the variables we want to solve for (x, y) .
SymPy is a Python library that allows you to compute mathematical objects symbolically.
evalf() function and subs() function from sympy is used to evaluate algebraic expressions. Example 1: In this example, we import symbols from sympy package. An expression is created and evalf() function is used to evaluate the expression.
It appears that sympy treats p1
and p2
as non-equal, which means that
top_matrix.nullspace()
[]
that is, the homogeous system with matrix coefficients top_matrix
has no non-trivial solution.
You have two options, here. The first is to treat the homogeneous system as having unknown variables both the elements of vector b
and p2
, treating p1
as a fixed parameter.
b = sp.Matrix(sp.symbols('b1:8')) #import sympy as sp
sp.solve(top_matrix*b, (*b,p2))
[{b1: 0, b2: 0, b3: 0, b4: 0, b5: 0, b6: 0, b7: 0}, {b1: b7, b2: b7, b3: b7*(-p1 + 1), b4: b7*p1, b5: b7, b6: b7, p2: p1}]
Note that the system has two solutions. The trivial one (with arbitrary p2
), and a non-trivial one, where it holds p2==p1
(with arbitrary b7
).
The second option is to realize that the system A*b=0
has a non-trivial solution if the system A.T*A*b=0
has a non-trivial solution. The latter is possible if the determinant of A.T*A
is zero. The determinant of A.T*A
equals
(top_matrix.T * top_matrix).det().factor()
6*(p1 - p2)**2
immediately revealing that it must hold p1==p2
in order to have a non-trivial solution.
In your example code, solve_linear_system
expects an augmented system, i.e., if the right hand side is zero, the matrix should be declared as Matrix.zeros(8,8)
. With this modification, your code yields
{a3: 0, a1: 0, a5: 0, a7: 0, a6: 0, a2: 0, a4: 0}
which is indeed a solution, although not the interesting one...
To remedy this, one can explicitly request that one component of the solution should be normalized to, say, 1. So if you do something like the following:
from sympy import Matrix, symbols, pprint, lcm, latex, solve
top_matrix = Matrix.zeros(8,7)
p1,p2 = symbols("p1, p2")
top_matrix[0,0] = 1
top_matrix[0,1] = -1
top_matrix[1,1] = (1-p1)
top_matrix[1,2] = -1
top_matrix[2,2] = 1
top_matrix[2,4] = p2-1
top_matrix[3,1] = p1
top_matrix[3,3] = -1
top_matrix[4,3] = 1
top_matrix[4,4] = -p2
top_matrix[5,4] = 1
top_matrix[5,5] = -1
top_matrix[6,1] = -1
top_matrix[6,6] = -1
top_matrix[7,4] = 1
top_matrix[7,6] = 1
pprint(top_matrix)
a1,a2,a3,a4,a5,a6,a7 = list(symbols("a1, a2, a3, a4, a5, a6, a7"))
B = Matrix([[1],[a2],[a3],[a4],[a5],[a6],[a7]])
C = top_matrix * B
print(solve(C, (a2,a3,a4,a5,a6,a7,p1,p2)))
and solve for the remaining variables as well as the parameters p1,p2
, the result is:
[{a2: 1, a7: -1, a4: p2, a6: 1, a5: 1, p1: p2, a3: -p2 + 1}]
which is indeed the desired solution.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With