找到满足某些约束的矩阵

时间:2017-06-27 13:02:38

标签: java algorithm matrix

问题的另一种描述:Compute a matrix which satisfies certain constraints

给定一个函数,其唯一参数是4x4矩阵(int[4][4] matrix),确定该函数的最大可能输出(返回值)。

4x4矩阵必须满足以下约束条件:

  1. 所有条目都是-10到10之间的整数(包括)。
  2. 必须是对称的,条目(x,y)=条目(y,x)。
  3. 对角线条目必须为正,条目(x,x)> 0
  4. 所有16个条目的总和必须为0.
  5. 该函数必须只总结矩阵的值,没什么特别的。

    我的问题:

    鉴于这样一个函数可以求和矩阵的某些值(矩阵满足上述约束),我如何找到该函数的最大可能输出/返回值?

    例如:

    /* The function sums up certain values of the matrix, 
       a value can be summed up multiple or 0 times. */
    
    // for this example I arbitrarily chose values at (0,0), (1,2), (0,3), (1,1).
    int exampleFunction(int[][] matrix) {
        int a = matrix[0][0];
        int b = matrix[1][2];
        int c = matrix[0][3];
        int d = matrix[1][1];
    
        return a+b+c+d;
    }
    
    /* The result (max output of the above function) is 40, 
       it can be achieved by the following matrix: */
        0.   1.   2.   3.
    0.  10  -10  -10   10
    1. -10   10   10  -10
    2. -10   10    1   -1
    3.  10  -10   -1    1
    
    
    // Another example:
    
    // for this example I arbitrarily chose values at (0,3), (0,1), (0,1), (0,4), ...
    int exampleFunction2(int[][] matrix) {
        int a = matrix[0][3] + matrix[0][1] + matrix[0][1];
        int b = matrix[0][3] + matrix[0][3] + matrix[0][2];
        int c = matrix[1][2] + matrix[2][1] + matrix[3][1];
        int d = matrix[1][3] + matrix[2][3] + matrix[3][2];
    
        return a+b+c+d;
    }
    
    /* The result (max output of the above function) is -4, it can be achieved by 
       the following matrix:  */
        0.   1.   2.   3.
    0.   1   10   10  -10
    1.  10    1   -1  -10
    2.  10   -1    1   -1
    3. -10  -10   -1    1
    

    我不知道从哪里开始。目前我试图估计满足约束条件的4x4矩阵的数量,如果数量足够小,问题可以通过暴力解决。

    有更通用的方法吗? 可以对这个问题的解决方案进行推广,以便它可以很容易地适应给定矩阵上的任意函数和矩阵的任意约束吗?

3 个答案:

答案 0 :(得分:3)

您可以尝试使用linear programming techniques解决此问题。

这个想法是将问题表达为一些不等式,一些等式和线性目标函数,然后调用库来优化结果。

Python代码:

import scipy.optimize as opt
c = [0]*16
def use(y,x):
    c[y*4+x] -= 1

if 0:
    use(0,0)
    use(1,2)
    use(0,3)
    use(1,1)
else:
    use(0,3)
    use(0,1)
    use(0,1)
    use(0,3)
    use(0,3)
    use(0,2)
    use(1,2)
    use(2,1)
    use(3,1)
    use(1,3)
    use(2,3)
    use(3,2)
bounds=[ [-10,10] for i in range(4*4) ]
for i in range(4):
    bounds[i*4+i] = [1,10]
A_eq = [[1] * 16]
b_eq = [0]
for x in range(4):
    for y in range(x+1,4):
        D = [0]*16
        D[x*4+y] = 1
        D[y*4+x] = -1
        A_eq.append(D)
        b_eq.append(0)

r = opt.linprog(c,A_eq=A_eq,b_eq=b_eq,bounds=bounds)
for y in range(4):
    print r.x[4*y:4*y+4]
print -r.fun

打印:

[  1.  10. -10.  10.]
[ 10.   1.   8. -10.]
[-10.   8.   1. -10.]
[ 10. -10. -10.   1.]
16.0

说第二种情况的最佳值是16,使用给定的矩阵。

严格来说,您需要整数解决方案。当输入可以是任何实数值时,线性编程解决了这类问题,而当输入必须是整数时,整数编程解决了这种类型。

在您的情况下,您可能会发现线性编程方法已经提供了整数解决方案(它适用于两个给定的示例)。当发生这种情况时,可以肯定这是最佳答案。

但是,如果变量不是整数,则可能需要找到整数编程库。

答案 1 :(得分:1)

您需要首先考虑哪些矩阵符合规则。对角线上的4个数字必须为正数,对角线的最小和为4(4个1值),最大值为40(4个10个值)。

所有16个项目的总和为0 - 或换句话说,总和(诊断)+总和(矩阵的剩余)= 0。

因为你知道和(对角线)是正的,这意味着总和(矩阵的剩余部分)必须是负的并且相等 - 基本上是和(对角线)*( - 1)。

我们也知道矩阵的其余部分是对称的 - 所以你保证总和(矩阵的其余部分)是偶数。这意味着对角线也必须是偶数,并且矩阵的上半部分的总和恰好是对角线*( - 1)的一半。

对于任何给定的函数,你需要一些单元格并求它们。现在,您可以将函数视为适合类别。对于仅从对角线获取所有4个单元格的函数,最大值为40.如果函数采用不是对角线的所有12个单元格,则最大值为-4(负最小对角线)。

其他类别的功能,答案很简单:

1)从对角线开始的一个和对角线上方/下方的矩阵的整半 - 最大值为3.对角线单元格为10,其余为1,1,2(最小值为均匀值数字)和半矩阵将总和为-7。

2)对角线和半个矩阵的两个单元 - 最大值为9.两个对角线单元最大化为二十,剩余单元格为1,1 - 所以半矩阵求和为-11。

3)来自对角线和半个矩阵的三个单元格 - 最大值为14。

4)整个对角线和矩阵的一半 - 最大值为20。

您可以继续选择功能的类别(使用一些来自对角线,一些来自其余部分),并轻松计算每个选择功能类别的最大值。我相信他们都可以被映射。

然后,唯一的步骤是将新的选择功能放在正确的类别中,并且您知道最大值。

答案 2 :(得分:1)

按矩阵降序排列矩阵中的元素并存储在数组中。逐个遍历数组中的元素 并将其添加到变量。在向变量添加元素时迭代,减少其值。存储在变量中的值给出最大值。

maxfunction(matrix[][])
{
array(n)=sortDescending(matrix[][]);
max=n[0];
i=1;
    for i to n do
     temp=max;
     max=max+n[i];
     if(max<temp)
       break;

return max;
}