Java实现完整单纯形法(非常好用)

目录

 整个代码分为两个部分,即两个类

第一个数据类

 第二个主类

如果使用者对java一窍不通,这里有傻瓜式教学:

运行示范:

注意


 整个代码分为两个部分,即两个类

第一个数据类

package cn.sgnxotsmicf.Demo;

import java.text.DecimalFormat;
import java.util.Scanner;

public class Simplex_Method_Data {
    public static double[] c;  // 目标函数中变量xj的价值系数cj
    public static double[] pi; // 检验系数π
    public static double[] theta; // 入基时对应的θ
    public static double[] b0; // 基本可行解中基变量的值
    public static int m; // 秩
    public static int n; // 变量个数
    public static int[] basicVar; //用来存储基变量的索引
    public static double var;
    public static int[] MData;
    public static String YN;
    public static double[][] centreMatrix_Creat(Scanner sc){
        System.out.println("请输入约束矩阵A的秩:");
        m = sc.nextInt();
        System.out.println("请输入约束矩阵变量个数:"); // 同时也确定了基变量和非基变量的个数
        n = sc.nextInt();
        double[][]A = new double[m][n];
         inputA(A,sc);
         return A;
    }

    /**
     * 用于初始化A
     * @param A 为初始约束条件系数矩阵
     */
    public static void inputA(double[][]A,Scanner sc) {
        for (int i = 0; i < m; i++) {
            System.out.println("请输入第"+(i+1)+"行元素:");
            for (int j = 0; j < n; j++) {
                A[i][j] = sc.nextDouble();
            }
        }
    }

    /**
     * 打印单纯性表
     */
    public static void printMatrix(double[][] E){
        DecimalFormat sc = new DecimalFormat("0.00");
        for (int i = 0; i < m; i++) {
            System.out.print(sc.format(b0[i])+",");
            for (int j = 0; j < n; j++) {
                System.out.print(sc.format(E[i][j])+(j==n-1?"":","));
            }
            System.out.println();
        }
        System.out.print(var+",");
        for (int j = 0; j < n; j++) {
            System.out.print(sc.format(pi[j])+(j==n-1?"":","));
        }
        System.out.println();
    }
}

 第二个主类

package cn.sgnxotsmicf.Demo;

import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.Scanner;

public class Simplex_Method extends Simplex_Method_Data{
    static {
        System.out.println("==================单纯形法求解线性规划=================");
    }

    /**
     * 主方法
     */
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        double[][] A = centreMatrix_Creat(sc);
        Search_XB(sc);
        Init(sc,A);
        LocalDateTime startTime = LocalDateTime.now();
        LogicLoopJudge(A);
        LocalDateTime endTime = LocalDateTime.now();
        IterationTime(startTime,endTime);
    }

    /**
     *用于计算迭代时间
     * @param startTime 迭代前时间
     * @param endTime  迭代后时间
     *
     */
    private static void IterationTime(LocalDateTime startTime, LocalDateTime endTime) {
        System.out.println("迭代时间大约为:"+ ChronoUnit.MILLIS.between(startTime, endTime)+"毫秒");
    }

    private static void LogicLoopJudge(double[][] A) {
        int number = 0;
        while (true){
            int tempt = 0;
            int negativeIndex = 0;
            for (int i = 0; i < pi.length; i++) {
                if (pi[i]<=0){
                    tempt++;
                }
                else if (pi[i]>0) {
                    for (int j = 0;j < m;j++){
                        if (A[j][i]<=0){
                            negativeIndex++;
                        }
                    }
                    if (negativeIndex ==m){
                        System.out.println("此线性规划问题无最优解!");
                        return;
                    }
                }
            }
            if (tempt == n){
                printResult(A,number);
                break;
            }
            // 开始操作;
            System.out.println("=================开始第"+(number+1)+"次迭代================");
            int index = IntoBaseVar_Judge();//入基索引
            UpDataTheta(A,index);
            int index2 = OutOfBaseVar_Judge(index);//出基索引
            RotationTransformation(A,index,index2);
            number++;
        }
    }

    /**
     *用于A的旋转变化,更新A
     * @param index 入基变量
     * @param index2 出基变量
     */
    private static void RotationTransformation(double[][] A,int index,int index2) {
        if (A[index2][index] != 1) {
            double positiveFactor = A[index2][index];
            //A[index2][index] = 1;
            for (int j = 0; j < n; j++) {
                A[index2][j] /= positiveFactor; //初等行变化
            }
            b0[index2] /= positiveFactor;
        }
        RotatingCenter(A,index,index2);
    }

    private static void RotatingCenter(double[][] A, int index, int index2) {
        for (int i = 0; i < m; i++) {
            if (A[i][index]!=0 && i!=index2){
                double factor = -A[index2][index]*A[i][index];
                double b0_factor = factor*b0[index2];
                b0[i] += b0_factor;
                for (int j = 0; j < n; j++) {
                    double A_factor = A[index2][j]*factor;
                    A[i][j] += A_factor;
                }
            }
        }
        double factor = -A[index2][index]*pi[index];
        for (int j = 0; j < n; j++) {
            double pi_factor = factor*A[index2][j];
            pi[j] += pi_factor;
        }
    }

    private static void printResult(double[][] A,int number) {
        for (int i = 0; i < m; i++) {
           var += c[basicVar[i]]*b0[i];
        }
        System.out.println("======================循环结束======================");
        System.out.println("最优值为:"+var);
        System.out.println("最优解为:");
        boolean logic = OptimalSolution();
        if (!logic){
            return;
        }
        System.out.println("基向量为:");
        for (int j : basicVar) {
            System.out.print("x" + (j + 1)+"\t");
        }
        System.out.println();
        System.out.println("迭代次数:"+number);
        System.out.println("最后一步单纯形表为:");
        printMatrix(A);
    }

    private static boolean OptimalSolution() {
        DecimalFormat sc = new DecimalFormat("0.00");
        String[] OptimalSData = new String[n];
        for (int i = 0; i < basicVar.length; i++) {
            OptimalSData[basicVar[i]] = sc.format(b0[i]);
        }
        for (int i = 0; i < OptimalSData.length; i++) {
            if (OptimalSData[i] == null){
                OptimalSData[i] = "0.00";
            }
        }
        System.out.println(Arrays.toString(OptimalSData));
        //0.25 0 0 1 0 -0.25   -2 0 -1 0 1 -3    1 1 0 0 0 1   1.5 6 10   2 3 0 0 10000 10000
        if (YN.equals("yes")) {
            for (int mDatum : MData) {
                for (int j = 0; j < m; j++) {
                    if (mDatum == basicVar[j] && b0[j] != 0) {
                        System.out.println("由于最优解中存在正的人工变量,则原问题是不可行的");
                        return false;
                    }
                }
            }
        }
        return true;
    }

    /**
     *
     * @param index 为入基索引
     * @return 返回出基索引
     * 使用的是Dantzig出基规则
     */
    private static int OutOfBaseVar_Judge(int index) {
        int index2 = 0;
        for (int i = 1; i < m; i++) {
            if (theta[index2]>theta[i]){
                index2 = i;
            }
        }
        System.out.println("出基变量为:x"+((basicVar[index2]+1)));
        basicVar[index2] = index;
        return index2;
    }

    /**
     *
     * @return 返回的是入基索引
     * 使用的是Dantzig入基规则
     */
    private static int IntoBaseVar_Judge() {
        int index = 0;
        for (int i = 1; i < n; i++) {
            if (pi[index]<pi[i]){
                index = i;
            }
        }
        System.out.println("入基变量为:x"+(index+1));
        return index;
    }

    /**
     * 用于更新θ
     * @param index 入基变量
     */
    private static void UpDataTheta(double[][] A,int index) {
            theta = new double[m];
        for (int i = 0; i < m; i++) {
            if (A[i][index]<=0){
                theta[i] = 1000;
            }else {
            theta[i] = b0[i]/A[i][index];
            }
        }
    }

    /**
     * 搜索单位矩阵
     */
    private static void Search_XB(Scanner sc) {
        basicVar = new int[m];
        System.out.println("请输入单位矩阵所对应的"+m+"个初始基变量的下标:");
        for (int i = 0; i < m; i++) {
            int tempt = sc.nextInt();
            basicVar[i] = (tempt-1);
        }
        System.out.println("基变量为:");
        for (int j : basicVar) {
            System.out.print("x" + (j + 1) + " ");
        }
        System.out.println();
    }

    /**
     * 数据初始化
     */
    private static void Init(Scanner sc,double[][] A) {
        int MJudge = TheBigMMethod(sc);
        // 初始化基变量的值
        b0 = new double[m];
        if (MJudge == 1){
            System.out.println("请输入人工变量的个数:");
            int M = sc.nextInt();
             MData= new int[M];
            for (int i = 0; i < M; i++) {
                System.out.println("请输入第"+(i+1)+"个人工变量下标:");
                int tempt = sc.nextInt();
                MData[i] = (tempt-1); //人工变量索引
            }
        }
        System.out.println("请输入基本可行解中基变量的初始值:"); //等于B^-1*b ---基于初始单位阵I
        for (int i = 0; i < m; i++) {
            b0[i] = sc.nextDouble();
        }
        // 初始化 价值系数c
        c = new double[n];
        System.out.println("请输入目标函数中变量xj的价值系数cj:");
        for (int i = 0; i < n; i++) {
            c[i] = sc.nextDouble();
        }
        
        // 初始检验数
        initPi(A);
    }

    /**
     * 大M法判断
     * @return 返回判断逻辑
     */
    private static int TheBigMMethod(Scanner sc) {
        System.out.println("是否有人工变量?(yes/no)");
        String MJudge = sc.next();
        YN = MJudge;
        if (MJudge.equals("yes")){
            System.out.println("==================下面进行大M法求解线性最优化问题=============");
            return 1;
        }
        return 0;
    }

    /**
     *初始化检验数π
     */
    private static void initPi(double[][] A) {
        pi = new double[n];
        for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    pi[i] += c[basicVar[j]]*A[j][i];
                }
            pi[i] -= c[i];
        }
    }
}

如果使用者对java一窍不通,这里有傻瓜式教学:

首先两个类(代码)使用前必须先创建两个类,分别存这两个代码,然后要改掉类名,即public class 后面的英文,改成你自己的类名(文件名)和包名,即package后面的cn.sgnxotsmicf.Demo;也要改成自己的。

然后是如何输入运行,其实非常简单(前提是你得懂单纯性法的原理),本代码不仅支持一般的线性规划问题,还提供了解决特殊线性规划问题的大M法;

注意:A是指B^-1*A, B指一组基变量对应的列向量矩阵,初始状态为(单位阵)

           b0指B^-1*b,即基变量的值 

运行示范:

注意

每次迭代时为了方便没有打印出单纯性表和其他数据,其实代码都提供了方法:

在数据类里提供了打印方法:printMatrix(double[][] E)   输出为:printMatrix(E),E为A

其他诸如检验数Arrays.toString(pi)(输出它),基变量等都可以自行添加。

  • 6
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值