1

My question is the same one from the google answers back in 2002 [1].

Here is the question quoted from the google answers.

"I am trying to compute the maximum possible sum of values from a matrix or 2d array or table or any suitable structure. The restriction is that once you select a particular row,column value to add to your sum, no other values from that row or column may be used in calculating the sum."

The only way I have been able to solve this is by going through every possible combination and store the potential result in a set of all possible potential results. I then select the maximum. This seems to chew up a lot of memory in my program which generates errors. The program is written in Java.

I have provided an example below for further clarification

e.g. 3 X 3 matrix with the following values

0.5 0.1 0.4
0.3 0.8 0.7
0.2 0.4 0.6

All possible combinations

0.5 + 0.8 + 0.6 = 1.9
0.5 + 0.7 + 0.4 = 1.6
0.1 + 0.3 + 0.6 = 1.0
0.1 + 0.7 + 0.2 = 1.0
0.4 + 0.3 + 0.4 = 1.1
0.4 + 0.8 + 0.2 = 1.4

So the maximum possible sum is 1.9.

If there is no other way to get the exact maximum, is there something I can do to get an approximate value?

Duplicates can appear in the matrix and the matrix is not necessarily square.

martineau
  • 119,623
  • 25
  • 170
  • 301
Barrelo
  • 11
  • 2
  • Seems like you could sum _all_ the values once, and then subtract the sum of all the values in it that are in a particular row and column (for every possible row and column combination). These subtotals would only need to be calculated once. – martineau Apr 18 '18 at 17:15
  • Perhaps the https://en.wikipedia.org/wiki/Hungarian_algorithm could help? – Peter de Rivaz Apr 18 '18 at 18:16
  • Try researching dynamic programming and memoization. – Rohi Apr 19 '18 at 12:05
  • @PeterdeRivaz Thank you for your help. It really helped – Barrelo Jan 23 '19 at 02:38

4 Answers4

2

Using itertools, you can loop over all combinations in a memory efficient way and keep the set of elements with the highest sum.

from itertools import permutations, product

def get_max_sum(table):
    height, width = len(table), len(table[0])

    sum_, *pos = max((sum(table[x][y] for x, y in zip(*pairs)), *zip(*pairs))
               for pairs in product(
                permutations(range(height)),
               ([*range(i, width), *range(i)] for i in range(width))))

    return (sum_, *sorted(pos))

Here is an example.

sum_, *pos = get_max_sum(
    [[1, 2, 3, 6],
     [2, 3, 5, 8],
     [4, 9, 16, 1]]
)
# Output: (26, (0, 1), (1, 3), (2, 2))

The output provides the sum followed by the coordinates of the chosen elements.

Olivier Melançon
  • 21,584
  • 4
  • 41
  • 73
  • First of all, sorry about such a late reply and appreciate your idea. I had tried the same idea but unfortunately in my case, all the possible combinations are too many to try brute-force. – Barrelo May 31 '18 at 08:56
  • @Barrelo I'll try to see if I have time to update my answer, but long story short, you would want to adapt the [Hungarian algorithm](https://en.wikipedia.org/wiki/Hungarian_algorithm#Matrix_interpretation) for an unbalanced matrix. It is an interesting problem, I'll notify you if I update my answer accordingly – Olivier Melançon May 31 '18 at 13:07
1

In Python, you can use the linear sum assignment from Scipy. An example is given below, which shows the maximum possible sum.

import numpy as np
from scipy.optimize import linear_sum_assignment

cost_matrix = np.array([[29,10,1,17,6,2],
                       [36,31,26,32,28,27],
                       [35,24,18,25,21,19],
                       [30,11,3,20,8,4],
                       [34,16,13,23,15,14],
                       [33,12,5,22,9,7]])
row_ind, col_ind = linear_sum_assignment(cost_matrix, maximize=True)
opt_ass = [[row_ind],[col_ind]]
values = cost_matrix[row_ind, col_ind]
tc = cost_matrix[row_ind, col_ind].sum()
print(opt_ass)
print(values)
print(tc)
Lateef26
  • 21
  • 3
0

In python it is very easy to realize. Suppose that the 2-D array is A with shape n,m. Now search for the index with largest value and remove the row and column. Repeat for the smallest n,m considering that you may not reuse the row and column of the maximum again.

import numpy as np
A = np.random.randint(0,100,30).reshape((5,6))
S = 0
for i in range(0,min(A.shape)) :
   I = np.unravel_index(np.argmax(A, axis=None), A.shape)
   S+= A[I]
   A=np.delete(A,I[0],0)
   A=np.delete(A,I[1],1)
print('Sum = ' + str(S))
Johan van Breda
  • 583
  • 8
  • 13
0

Here's an idea, I'm not sure if it works in all cases.

For each row and column, find the maximum and minimum values and compute the difference. Then choose the row or column that has the maximal difference. Add the maximum of that row or column to the solution, and recur on the matrix that results from removing the row and column of the item just added to the solution.

Consider the sample matrix. The differences between maximum and minimum are 0.4, 0.5 and 0.4 for the first, second and third rows, and 0.3, 0.7 and 0.3 for the first, second and third columns. The biggest difference is 0.7 for the second column, and the maximum item in the second column is 0.8, so add 0.8 to the solution and reduce the matrix to 0.5 0.4 | 0.2 0.6. The biggest difference in the reduced matrix is the second row, from 0.2 to 0.6, so add 0.6 to the solution and reduce the matrix to a single column and single row containing 0.5. Finally, add 0.5 to the solution. Thus, the solution is 0.8 + 0.6 + 0.5 = 1.9, which agrees to your solution.

user448810
  • 17,381
  • 4
  • 34
  • 59