简体   繁体   中英

How to solve for unknowns in a 5x5 matrix in python

Here is a 5x5 matrix, with all cells unknown, it looks something like this:

A1+B1+C1+D1+E1| 1
A2+B2+C2+D2+E2| 0
A3+B3+C3+D3+E3| 1
A4+B4+C4+D4+E4| 3
A5+B5+C5+D5+E5| 2
_______________
2  1  2  1  1

So, the summation of rows can be seen on the right, and the summation of columns can be seen on the bottom. The solution can only be 0 or 1, and as an example here is the solution to the specific one I have typed out above:

0+0+1+0+0| 1
0+0+0+0+0| 0
1+0+0+0+0| 1
1+1+0+0+1| 3
0+0+1+1+0| 2
____________
2 1 2 1 1

As you can see, summing the rows and columns gives the results on the right and bottom. My question: How would you go about entering the original matrix with unknowns and having python iterate each cell with 0 or 1 until the puzzle is complete?

You don't really need a matrix -- just use vectors (tuples) of length 25. They can represent 5x5 matrices according to the following scheme:

0  1  2  3  4
5  6  7  8  9
10 11 12 13 14
15 16 17 18 19
20 21 22 23 24

These are the indices of such tuples. Note that the row and column of an index can be obtained from the function divmod .

You can use product from itertools to iterate over the 2**25 possible ways of filling in the matrix.

These ideas lead to the following code:

from itertools import product

#nxn matrices will be represented by tuples of length n**2,
#in row-major order
#the following function caluculates row and column sums:

def all_sums(array,n):
    row_sums = [0]*n
    col_sums = [0]*n
    for i,x in enumerate(array):
        q,r = divmod(i,n)
        row_sums[q] += x
        col_sums[r] += x
    return row_sums, col_sums

#in what follows, row_sums, col_sums are lists of target values

def solve_puzzle(row_sums, col_sums):
    n = len(row_sums)
    for p in product(range(2),repeat = n*n):
        if all_sums(p,n) == (row_sums, col_sums):
            return p
    return "no solution"

solution = solve_puzzle([1,0,1,3,2],[2,1,2,1,1])
for i in range(0,25,5):
    print(solution[i:i+5])

Output:

(0, 0, 0, 0, 1)
(0, 0, 0, 0, 0)
(0, 0, 0, 1, 0)
(1, 1, 1, 0, 0)
(1, 0, 1, 0, 0)

In this case brute-force was feasible. If you go much beyond 5x5 it would no longer be feasible, and more sophisticated algorithms would be required.

This is a special case of an integer linear programming problem. The special case of 0-1 integer linear programming is still unfortunately NP-complete, though there exist many algorithms including heuristic ones. You can use a built-in library to do this for you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM