【问题标题】:Find a matrix which satisfies certain constraints找到满足某些约束的矩阵
【发布时间】:2017-06-27 13:02:37
【问题描述】:

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

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

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

  1. 所有条目都是介于 -10 和 10(含)之间的整数。
  2. 必须是对称矩阵,entry(x,y) = entry(y,x)。
  3. 对角线条目必须是正数,entry(x,x) > 0。
  4. 所有 16 个条目的总和必须为 0。

函数必须只对矩阵的值求和,没什么花哨的。

我的问题:

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

例如:

/* 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 矩阵的数量,如果数量足够小,则可以通过蛮力解决问题。

有没有更通用的方法? 这个问题的解决方案是否可以推广,使其可以很容易地适应给定矩阵上的任意函数和矩阵的任意约束?

【问题讨论】:

  • 相对于上述条件,要最大化的值究竟是多少?或者这是问题的一部分?
  • @Codor 函数的返回值被最大化。换句话说:该函数选择要对哪些条目求和,目标是得出一个矩阵,该矩阵的总和最大。
  • 请注意,由于对称性,矩阵实际上比任意矩阵“小”;没有 16 个可能不同的条目,但只有 10 个。
  • 总结某些值是什么意思?该函数只能选择肯定条目?
  • 然后取最大值乘以Integer.MAX_VALUE,问题描述有地方不对。

标签: java algorithm matrix


【解决方案1】:

您可以尝试使用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,使用给定的矩阵。

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

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

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

【讨论】:

  • 在最后一句中,您的意思是“线性”而不是“整数”吗?
  • 我这样做是出于乐趣和练习,解决方案应该在 java 中,我不想使用任何 3rd 方库。
【解决方案2】:

对矩阵中的元素进行降序排序,存储到数组中。逐个遍历数组中的元素 并将其添加到变量中。在将元素添加到变量时停止迭代,减小其值。存储在变量中的值给出最大值。

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;
}

【讨论】:

    【解决方案3】:

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

    所有 16 项的总和为 0 - 或者换句话说,sum(diagnoal)+sum(rest-of-matrix)=0。

    既然您知道 sum(diagonal) 是正数,这意味着 sum(rest-of-matrix) 必须是负数且相等 - 基本上是 sum(diagonal)*(-1)。

    我们还知道矩阵的其余部分是对称的 - 因此可以保证 sum(rest-of-matrix) 是偶数。这意味着对角线也必须是偶数,并且矩阵上半部分的和正好是对角线的一半*(-1)。

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

    其他类别的函数有一个简单的答案:

    1) 一个来自对角线,整个矩阵的一半在对角线上方/下方 - 最大值为 3。对角线单元格为 10,其余为 1、1、2(达到偶数的最小值number) 和半矩阵的总和为 -7。

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

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

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

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

    那么唯一的步骤就是把你的新选择函数放在正确的类别中,你就知道最大值了。

    【讨论】:

    • “如果它们仅来自矩阵的其余部分,请达到 -4(负最小对角线)。”为什么?如果我有一个仅对 cell(1,0) 求和的函数,则存在一个总和为 10 的矩阵(取示例 2 中的矩阵)。
    • 这是一个公平的观点。明天我会修改我的答案以包含更清晰的算法。
    • 我得出了一些类似的结论,您的矩阵到最大值映射有反例,因为该函数可能会汇总超过 16 个条目(它会多次汇总其中一些条目)。请参阅stackoverflow.com/questions/44787848/… 以获得更清晰的问题描述。
    • 我假设每个单元格只能在总和中出现一次。如果不是这种情况,那么您将无法使用我的大部分解决方案。
    • 参见示例 2,一些单元格在 sum 中多次出现。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-03
    • 1970-01-01
    • 2012-10-21
    • 1970-01-01
    相关资源
    最近更新 更多