简单的单纯形法

时间:2014-12-01 13:27:49

标签: java methods simplex

我编写了一个解决单纯形法的程序,但它仅适用于约束数等于或小于目标函数中变量数的方程式,如果有任何其他方程式存在OutOfBoundsException且我不这样做如何解决这个问题呢。如果有人知道,请告诉我或分享工作算法的链接。

private static int ROW;

private static int COL;

private static Scanner scanner = new Scanner(System.in);

private static double[] calctemp(double[] temp, double[][] constLeft,
        double[] targetFunc, int[] basic) {
    double[] calcTemp = new double[temp.length];
    for (int i = 0; i < COL; i++) {
        calcTemp[i] = 0;
        for (int j = 0; j < ROW; j++) {
            calcTemp[i] += targetFunc[basic[j]] * constLeft[j][i];
        }
        calcTemp[i] -= targetFunc[i];
    }
    return calcTemp;
}

private static int minimum(double[] arr) {
    double arrmin = arr[0];
    int minPos = 0;
    for (int i = 0; i < arr.length; i++) {
        if (arr[i] < arrmin) {
            arrmin = arr[i];
            minPos = i;
        }
    }
    return minPos;
}

private static void printFrame(double[] targetFunc) {
    StringBuilder sb = new StringBuilder();
    sb.append("Cj\t\t\t");
    for (int i = 0; i < targetFunc.length; i++) {
        sb.append(targetFunc[i] + "\t");
    }
    sb.append("\ncB\txB\tb\t");
    for (int i = 0; i < targetFunc.length; i++) {
        sb.append("a" + (i + 1) + "\t");
    }
    System.out.print(sb);
}

private static void printAll(double[] targetFunc, double[] constraintRight,
        double[][] constraintLeft, int[] basic) {
    printFrame(targetFunc);
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < ROW; i++) {
        sb.append("\n" + targetFunc[basic[i]] + "\tx" + (basic[i] + 1)
                + "\t" + constraintRight[i] + "\t");
        for (int j = 0; j < COL; j++) {
            sb.append(constraintLeft[i][j] + "\t");
        }
        sb.append("\n");
    }
    System.out.println(sb);
}

public static void main(String[] args) {
    double[] targetFunc = { 6, -5, 0, 0};
    ROW = 2;
    COL = 2 + ROW;
    double[][] constraintsLeft = { { 2, 5, 1, 0 },
            { 5, 2, 0, 1 }};
    double[] constraintsRight = { 10, 10 };

    double[] temp = new double[COL];

    int tempMinPos;
    double[] miniRatio = new double[ROW];
    int miniRatioMinPos = 0;
    double key;
    int goOutCol = 0;
    double z;
    double[] x = new double[COL];
    int[] basic = new int[ROW];
    int[] nonBasic = new int[ROW];
    boolean flag = false;

    for (int i = 0; i < ROW; i++) {
        basic[i] = (i + ROW);
        nonBasic[i] = i;
    }
    System.out.println("------------Calculating------------");
    while (!flag) {
        z = 0;
        temp = calctemp(temp, constraintsLeft, targetFunc, basic);

        tempMinPos = minimum(temp);
        printAll(targetFunc, constraintsRight, constraintsLeft, basic);
        System.out.print("Zj-Cj\t\t\t");
        for (int i = 0; i < COL; i++) {
            System.out.print(temp[i] + "\t");
        }
        System.out
                .println("\n--------------------------------------------------");
        System.out.println("Basic variables : ");
        for (int i = 0; i < ROW; i++) {
            x[basic[i]] = constraintsRight[i];
            x[nonBasic[i]] = 0;
            System.out.println("x" + (basic[i] + 1) + " = "
                    + constraintsRight[i]);
        }
        for (int i = 0; i < ROW; i++) {
            z = z + targetFunc[i] * x[i];
        }
        System.out.println("Max(z) = " + z);

        for (int i = 0; i < ROW; i++) {
            if (constraintsLeft[i][tempMinPos] <= 0) {
                miniRatio[i] = 999;
                continue;
            }
            miniRatio[i] = constraintsRight[i]
                    / constraintsLeft[i][tempMinPos];
        }
        miniRatioMinPos = minimum(miniRatio);

        for (int i = 0; i < ROW; i++) {
            if (miniRatioMinPos == i) {
                goOutCol = basic[i];
            }
        }
        System.out.println("Outgoing variable : x" + (goOutCol + 1));
        System.out.println("Incoming variable : x" + (tempMinPos + 1));

        basic[miniRatioMinPos] = tempMinPos;
        nonBasic[tempMinPos] = goOutCol;

        key = constraintsLeft[miniRatioMinPos][tempMinPos];
        constraintsRight[miniRatioMinPos] /= key;
        for (int i = 0; i < COL; i++) {
            constraintsLeft[miniRatioMinPos][i] /= key;
        }
        for (int i = 0; i < ROW; i++) {
            if (miniRatioMinPos == i) {
                continue;
            }
            key = constraintsLeft[i][tempMinPos];
            for (int j = 0; j < COL; j++) {
                constraintsLeft[i][j] -= constraintsLeft[miniRatioMinPos][j]
                        * key;
            }
            constraintsRight[i] -= constraintsRight[miniRatioMinPos] * key;
        }

        for (int i = 0; i < COL; i++) {
            flag = true;
            if (temp[i] < 0) {
                flag = false;
                break;
            }
        }
    }
}    

我输入了一些方程式来解决。这是正确的解决方案。 尝试更改此

    double[] targetFunc = { 8, 2, 0, 0, 0};

    ROW = 3;
    COL = 2 + ROW;
    double[][] constraintsLeft = { { 1, -4, 1, 0, 0 },
            { -4, 1, 0, 1, 0 },
            { 1, 1, 0, 0, 1}};
    double[] constraintsRight = { 4, 4, 6 };

1 个答案:

答案 0 :(得分:0)

这是我的scala版本。我在堕落的情况下尝试过它,我认为它支持&#34;品牌规则&#34;。

object Simplex {

    sealed trait Pivot {};
    case class Next(row: Int, col: Int) extends Pivot;
    object NoSolution extends Pivot;
    object NoMore extends Pivot;


    def minSuch[T,U](array: Array[T])(fn: (T,Int)=>Option[U])(implicit order: scala.math.Ordering[U]): Option[(Int, T, U)] = {
        @scala.annotation.tailrec
        def compute(idx: Int, res: Option[(Int, T, U)]): Option[(Int, T, U)] = if(idx>=array.length) res else (res, fn(array(idx), idx)) match {
            case (r , None) => compute(idx+1,r)
            case (r @ Some((_, _, u1)), Some(u2)) if order.lt(u1, u2) => compute(idx+1, r)
            case (_ , Some(u)) => compute(idx+1, Some((idx, array(idx), u)))
        }
        return compute(0, Option.empty[(Int, T, U)])
    }

    def solve[T](A: Array[Array[T]], Y: Array[T], C: Array[T])(implicit frac:scala.math.Fractional[T], classtag: scala.reflect.ClassTag[T]) : Option[(T,Array[T])] = {
        import scala.math.Fractional.Implicits._
        import scala.math.Ordering.Implicits._

        val N = (0 to  (C.length-1) by +1).toArray
        val B = (1 to -(Y.length  ) by -1).toArray
        val Z = C.map(-_)
        var z = frac.zero

        def pivot(): Pivot = minSuch(Z) { case (z,_) => 
            if( z<frac.zero ) Some(z) else None
        }.map { case (col, _, _) => 
            minSuch(A) { case(cells,row) =>
                if( cells(col)>frac.zero ) Some(Y(row)/cells(col)) else None
            }.map { case (row, _, _) =>
                new Next(row, col)
            }.getOrElse(NoSolution)
        }.getOrElse(NoMore)

        @scala.annotation.tailrec
        def resolve(): Option[(T, Array[T])] = pivot() match {
            case NoSolution => None
            case NoMore => {
                Some((z, Y.zip(B).foldLeft(Array.fill(C.length)(frac.zero))( (result, yb)=> 
                    if( yb._2 >= 0 ) result.updated(yb._2, yb._1) else result
                )))
            }
            case Next(row, col) => {
                val coef = A(row)(col)
                val tmp = B(row)
                B(row) = N(col)
                N(col) = tmp

                Z(col) = -Z(col) / coef
                z = z + Z(col) * Y(row)
                for(c <- 0 to Z.length-1 if(c!=col)) Z(c) = Z(c) + A(row)(c) * Z(col)

                Y(row) =  Y(row) / coef
                for(r <- 0 to Y.length-1 if(r!=row)) Y(r) = Y(r) - A(r)(col) * Y(row)

                A(row)(col) = frac.one / coef
                for(c <- 0 to A(row).length-1 if(col!=c) ) A(row)(c)=A(row)(c)/coef
                for(r <- 0 to A.length-1 if(row!=r); c <- 0 to A(r).length-1 if(col!=c)) A(r)(c)=A(r)(c) - A(r)(col) * A(row)(c)
                for(r <- 0 to A.length-1 if(row!=r)) A(r)(col) = -A(r)(col) / coef

                return resolve()
            }
        }

        return resolve();
    }

}

此用例有效。我试过一个循环的,它也有效......

    Simplex.solve(
        Array(
            Array(Rational(1), Rational(1)),
            Array(Rational(1), Rational(-2)),
            Array(Rational(-1), Rational(4))
        ),
        Array(
            Rational(2),
            Rational(0),
            Rational(1)
        ),
        Array(Rational(5), Rational(8))
    ).foreach { result=>
        println(result._1)
        result._2.foreach(println)
    }