目录
整个代码分为两个部分,即两个类
第一个数据类
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)(输出它),基变量等都可以自行添加。