在matlab中获得满足线性方程的一个答案的最佳方法

时间:2014-07-16 15:40:27

标签: matlab linear-programming linear-equation

我有一个线性方程式:

vt = v1*x1 + v2*x2 + v3*x3

vt,v1,v2,v3是值为0到1的标量。生成满足上述等式的x1,x2和x3的一个集合(任何集合都可以)的最佳方法是什么。并且还满足

x1>0
x2>0
x3>0

我有几千套vt,v1,v2和v3,因此我需要能够以编程方式生成x1,x2和x3。

1 个答案:

答案 0 :(得分:3)

有两种方法可以解决这个问题:

  1. 根据您在帖子中设计的方法。随机生成x1x2并确保vt < v1*x1 + v2*x2,然后继续解决x3
  2. 将其配制为线性程序。线性程序基本上是求解受不等式或等式约束的方程组。换句话说:
  3. blah

    因此,我们可以将您的问题转化为线性编程问题。 “最大化”语句就是所谓的目标函数 - 您要完成的目标。在线性规划问题中,我们试图最小化或最大化此目标。要做到这一点,我们必须满足条件中所见的不等式。通常,此程序以规范形式表示,因此每个变量的约束应为正。

    最大化条件可以是任意的,因为您不关心目标。你只关心任何解决方案。整个范例可以通过MATLAB中的linprog来实现。你应该注意的是如何指定linprog。事实上,目标是最小化而不是最大化。但是,除了确保所有变量都是正数之外,条件是相同的。我们必须自己编写代码。

    就任意目标而言,我们可以简单地x1 + x2 + x3。因此,c = [1 1 1]。我们的平等约束是:v1*x1 + v2*x2 + v3*x3 = vt。我们还必须确保x是积极的。为了对此进行编码,我们可以做的是选择一个小常量,以便x的所有值都大于此值。现在,linprog不支持严格的不等式(即x > 0),因此我们必须通过这个技巧来规避这一点。另外,为了确保值为正,linprog假定为Ax <= b。因此,使用的一个常见技巧是否定x >= 0的不等式,因此这相当于-x <= 0。为确保值不为零,我们实际上会执行:-x <= -eps,其中eps是一个小常量。然而,当我进行实验时,通过这种方式,两个变量最终成为相同的解决方案。因此,我建议我们做的是生成每次都是随机的好解决方案,让我们如同你所说的那样从均匀的随机分布中得出b。每当我们想要解决这个问题时,这将给我们一个起点。

    因此,我们的不平等是:

     -x1 <= -rand1
     -x2 <= -rand2
     -x3 <= -rand3
    

    rand1, rand2, rand3是三个随机生成的数字,介于01之间。在矩阵形式中,这是:

     [-1 0 0][x1]      [-rand1]
     [0 -1 0][x2]  <=  [-rand2]
     [0 0 -1][x3]      [-rand3]
    

    最后,我们之前的平等约束是:

    [v1 v2 v3][x1]     [vt] 
              [x2]  = 
              [x3]
    

    现在,要使用linprog,您可以这样做:

    X = linprog(c, A, b, Aeq, beq);
    

    c是为目标定义的系数数组。在这种情况下,它将被定义为[1 1 1]Ab是为不等式约束定义的矩阵和列向量,Aeqbeq是为等式约束定义的矩阵和列向量。因此,X会在linprog收敛后(即x1, x2, x3)为我们提供解决方案。因此,你会这样做:

    A = -eye(3,3);
    b = -rand(3,1);
    Aeq = [v1 v2 v3];
    beq = vt;
    c = [1 1 1];
    X = linprog(c, A, b, Aeq, beq);
    

    例如,假设v1 = 0.33, v2 = 0.5, v3 = 0.2vt = 2.5。因此:

    rng(123); %// Set seed for reproducibility
    v1 = 0.33; v2 = 0.5; v3 = 0.2;
    vt = 2.5;
    A = -eye(3,3);
    b = -rand(3,1);
    Aeq = [v1 v2 v3];
    beq = vt;
    c = [1 1 1];
    X = linprog(c, A, b, Aeq, beq);
    

    我明白了:

    X =
    
    0.6964
    4.4495
    0.2268
    

    要验证这等于vt,我们会这样做:

    s = Aeq*X
    
    s = 2.5000
    

    以上只是v1*x1 + v2*x2 + v3*x3。这是以点积形式计算的,因为X是列向量而v1, v2, v3已在Aeq中设置并且是行向量。


    因此,无论哪种方式都很好,但至少使用linprog,你不必保持循环,直到你满足条件为止!

    小警告

    我忘记在上述方法中提到的一个小警告是,您需要确保vt >= v1*rand1 + v2*rand2 + v3*rand3以确保收敛。既然你说v1,v2,v301之间有界限,最糟糕的情况是v1,v2,v3都等于1.因此,我们确实需要确保vt > rand1 + rand2 + rand3。如果这是的情况,则只需取rand1, rand2, rand3的每个值,然后除以(rand1 + rand2 + rand3) / vt。因此,这将确保总和将等于vt,假设所有权重均为1,这将允许线性程序正确收敛。

    如果不这样做,那么由于b中存在不等式条件,解决方案将无法收敛,您将无法得到正确的答案。只是一些值得思考的东西!因此,请在运行b

    之前为linprog执行此操作
    if sum(-b) > vt
       b = b ./ (sum(-b) / vt);
    end
    
    祝你好运!