I am looking for a method to solve a system of linear equations in Python. In particular, I am looking for the smallest integer vector that is larger than all zeros and solves the given equation. For example, I have the following equation:
In this case, the smallest integer vector that solves this equation is .
However, how can I determine this solution automatically?
If I use scipy.optimize.nnls
, like
A = np.array([[1,-1,0],[0,2,-1],[2,0,-1]])
b = np.array([0,0,0])
nnls(A,b)
the result is (array([ 0., 0., 0.]), 0.0)
.
Which is also correct, but not the desired solution...
Edit: I apologize for being imprecise in certain aspects. If anyone is interested in the details, the problem comes from the paper "Static Scheduling of Synchronous Data Flow Programs for Digital Signal Processing", Edward A. Lee and David G. Messerschmitt, IEEE Transactions on Computers, Vol. C-36, No. 1, pp. 24-35, January, 1987.
Theorem 2 says
For a connected SDF graph with s nodes and topology matrix A and with rank(A)=s-2, we can find a positive integer vector b != 0 such that Ab = 0 where 0 is the zero vector.
Directly after the proof of Theorem 2 they say
It may be desirable to solve for the smallest positive integer vector in the nullspace. To do this, reduce each rational entry in u' so that its numerator and denominator are relatively prime. Euclid's algorithm will work for this.
It's a wild idea perhaps but it sounds like you're looking to build a constraint solver.
minizinc is a general purpose constraint solver. Perhaps it is possible to express your constraint in such a way that minizinc can solve it?
Then it appears there is a Python library to interface with it: https://pypi.python.org/pypi/pymzn/
This question is quite informal as seen in the comments. Without knowing your definition of smallest (examples: l1-norm, l2-norm), it's hard to answer your specific problem.
The general problem is linked to solving a system of diophantine equations, but those are hard to solve (in the general case) and there is not much software.
A natural approach is to use Integer-programming, which is NP-hard, but commercial and some open-source solvers are very very powerful.
There is no built-in method in numpy/scipy which solves your problem without huge modifications (like: implementing some own algorithm based on numpy/scipy). Sadly, there is no IP-solver too within numpy/scipy.
Let's assume:
x is nonnegative
Here is some simple IP-based implementation using pulp and numpy. I don't like pulp much, but it's easy to install (
pip install pulp
) on all kind of popular systems.Code
Output
Actually, it's just basic linear algebra.
Let's calculate the eigenvalues and eigenvector for this matrix.
After rounding, we see that 0 is an eigenvalue of our matrix A. So, the eigenvector s for the 0-eigenvalue is a good candidate for your equation system.
Multiplying an eigenvector with the related matrix results in the eigenvector itself, scaled by the related eigenvalue. So, in the above case we see: As = 0s = 0
Since we are interested in an integer solution, we have to scale the solution vector.
Hope this answer solves your problem.
To find the exact solution that you want, numpy and scipy are probably not the best tools. Their algorithms generally work in floating point, and are not guaranteed to give the exact answer.
You can use
sympy
to get the exact answer to this problem. TheMatrix
class insympy
provides the methodnullspace()
that returns a list of basis vectors for the nullspace. Here's an example:Get the vector in the nullspace.
nullspace()
returns a list; this code assumes that the rank of A is 2, so the list has length one:Find the least common multiple of the denominators of the values in
v
so that we can scale the result to the smallest integers:x
holds the integer answer:To convert that result to a numpy array of integers, you can do something like:
There is a solver for this kind of equation at pypi. It apparently can compute the Hermite normal form of a matrix which in turn can be used to solve your problem.
The package is versioned 0.1.
Sage also appears to support the Hermite normal form.
The special case of a homogeneous system, i.e. b=0 is a bit easier, here is a solver for the simplest possible case of the matrix having rank n-1
Sample output: