线性规划 单纯性法

<span style="font-family: Arial, Helvetica, sans-serif;">package linearProgramming;</span>
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;

/**
 * @author Administrator 单纯形法
 * 
 *         第一行第一个数字为1代表求目标函数的最大值,-1代表求目标函数的最小值; 第二个数字代表约束条件的个数; 第三个数字代表变量个数;
 *         第四、五、六个数字分别代表≤的约束条件个数,=的约束条件个数,≥的约束条件个数;
 *         接下来输入约束条件的系数矩阵和右端项,注意按照≤,=,≥的顺序; 最后按照变量下标顺序输入目标函数的价值系数;
 * 
 *
 */
public class Main {
	// W * X >= B
	public static int MAX = 1;
	public static int MIN = -1;
	public static int nCondition = 6; // row
	public static int nX = 7;		  // col
	public static int nLess = 0;
	public static int nEqual = 0;
	public static int nGreater = 6;
	public static double w[][] = {	{ 0, 1, 1, 1, 1, 1, 0, 12 },
									{ 0, 0, 1, 1, 1, 1, 1, 15 }, 
									{ 1, 0, 0, 1, 1, 1, 1, 12 },
									{ 1, 1, 0, 0, 1, 1, 1, 14 },
									{ 1, 1, 1, 0, 0, 1, 1, 16 },
									{ 1, 1, 1, 1, 0, 0, 1, 18 } };
	public static int x[] = { 1, 1, 1, 1, 1, 1, 1};

	public static void main(String[] args) {
//		readFile();
		// showMatrix();
		double t1 = System.currentTimeMillis();
		LP lp = new LP(MIN, nCondition, nX, nLess, nEqual, nGreater, w, x);
		double[] ans = lp.solve();
		double t2 = System.currentTimeMillis();
		showAns(ans);
		System.out.println("####### time = " + (t2 - t1));
		System.out.println(nCondition);
		System.out.println(nX);
	}
	private static void showAns(double[] ans) {
		System.out.println("\n####### answer as follow");
		int xCount = 0;
		int xSum = 0;
		for(int i = 0; i < ans.length - 1; i++){
			if(ans[i] == 0) continue;
			xCount++;
			xSum += ans[i];
			System.out.println("X" + (i+1) + " = " + ans[i]);
		}
		System.out.println("min = " + ans[ans.length - 1]);
		System.out.println("xCount = " + xCount);
		System.out.println("xSum = " + xSum);
		
	}
	private static void readFile() {
		ArrayList<String> lines = new ArrayList<String>();
		File file = new File("src/com/W.csv");
		try {
			BufferedReader br = new BufferedReader(new FileReader(file));
			while(br.ready()){
				lines.add(br.readLine().trim());
			}
			br.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		nCondition = lines.size();
		nX = lines.get(0).split(",").length;
		nLess = 0;
		nEqual = 0;
		nGreater = nCondition;
		w = new double[nCondition][nX + 1];
		x = new int[nX];
		for(int i = 0; i < x.length; i++){
			x[i] = 1;
		}
		for(int i = 0; i < lines.size(); i++){
			String[] strs = lines.get(i).split(",");
			for(int j = 0; j < strs.length; j++){
				w[i][j] = Double.parseDouble(strs[j]);
			}
		}
		
		file = new File("src/com/A.csv");
		try {
			BufferedReader br = new BufferedReader(new FileReader(file));
			int i = 0;
			while(br.ready()){
				w[i++][nX] = Math.ceil(Double.parseDouble(br.readLine().trim()) / 1000);
			}
			br.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
	public static void showMatrix(){
//		System.out.println("第一行第一个数字为1代表求目标函数的最大值,-1代表求目标函数的最小值; ");
//		System.out.println("第二个数字代表约束条件的个数;");
//		System.out.println("第三个数字代表变量个数;");
//		System.out.println("第四、五、六个数字分别代表≤的约束条件个数,=的约束条件个数,≥的约束条件个数;");
//		System.out.println("接下来输入约束条件的系数矩阵和右端项,注意按照≤,=,≥的顺序;");
//		System.out.println("最后按照变量下标顺序输入目标函数的价值系数;");
//		System.out.println("系数矩阵");
//		System.out.println("-1 7 7 0 0 7");
//		System.out.println("系数矩阵");
		System.out.println("####### W * X>= B");
		for (int i = 0; i < w.length; i++) {
			for (int j = 0; j < w[i].length; j++) {
				System.out.print(w[i][j] + " ");
			}
			System.out.println();
		}
		System.out.println("\n####### the weights of goaling X");
		for (int i = 0; i < x.length; i++) {
			System.out.print(x[i] + " ");
		}
		System.out.println();
	}
}
 
 
package linearProgramming;


public class LP {
<span style="white-space:pre">	</span>private int m; // 约束条件的个数
<span style="white-space:pre">	</span>private int n; // 变量个数
<span style="white-space:pre">	</span>private int m1; // <=的约束条件个数
<span style="white-space:pre">	</span>private int m2; // =的约束条件个数
<span style="white-space:pre">	</span>private int m3; // >=的约束条件个数
<span style="white-space:pre">	</span>private int error; // 判断是否是错误的
<span style="white-space:pre">	</span>private int basic[];
<span style="white-space:pre">	</span>private int nonbasic[];
<span style="white-space:pre">	</span>private double a[][]; // 约束条件的系数矩阵
<span style="white-space:pre">	</span>private double minmax; // 目标函数的最大值或最小值


<span style="white-space:pre">	</span>/**
<span style="white-space:pre">	</span> * 
<span style="white-space:pre">	</span> * @param minmax
<span style="white-space:pre">	</span> *            -求函数的最大值或最小值
<span style="white-space:pre">	</span> * @param m
<span style="white-space:pre">	</span> *            -约束条件的个数
<span style="white-space:pre">	</span> * @param n
<span style="white-space:pre">	</span> *            -变量个数
<span style="white-space:pre">	</span> * @param m1
<span style="white-space:pre">	</span> *            -<=的约束条件个数
<span style="white-space:pre">	</span> * @param m2
<span style="white-space:pre">	</span> *            -=的约束条件个数
<span style="white-space:pre">	</span> * @param m3
<span style="white-space:pre">	</span> *            ->=的约束条件个数
<span style="white-space:pre">	</span> * @param a
<span style="white-space:pre">	</span> *            -约束条件的系数矩阵
<span style="white-space:pre">	</span> * @param x
<span style="white-space:pre">	</span> *            -目标函数的价值系数
<span style="white-space:pre">	</span> */
<span style="white-space:pre">	</span>public LP(double minmax, int m, int n, int m1, int m2, int m3,
<span style="white-space:pre">			</span>double a[][], int x[])// 构造函数
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>double value;
<span style="white-space:pre">		</span>this.error = 0;
<span style="white-space:pre">		</span>this.minmax = minmax;
<span style="white-space:pre">		</span>this.m = m;
<span style="white-space:pre">		</span>this.n = n;
<span style="white-space:pre">		</span>this.m1 = m1;
<span style="white-space:pre">		</span>this.m2 = m2;
<span style="white-space:pre">		</span>this.m3 = m3;
<span style="white-space:pre">		</span>if (m != m1 + m2 + m3)// 约束条件的溢出
<span style="white-space:pre">		</span>{
<span style="white-space:pre">			</span>this.error = 1;
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>this.a = new double[m + 2][];
<span style="white-space:pre">		</span>for (int i = 0; i < m + 2; i++) {
<span style="white-space:pre">			</span>this.a[i] = new double[n + m + m3 + 1];
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>this.basic = new int[m + 2];
<span style="white-space:pre">		</span>this.nonbasic = new int[n + m3 + 1];
<span style="white-space:pre">		</span>for (int i = 0; i <= m + 1; i++)// 初始化基本变量和非基本变量
<span style="white-space:pre">		</span>{
<span style="white-space:pre">			</span>for (int j = 0; j <= n + m + m3; j++) {
<span style="white-space:pre">				</span>this.a[i][j] = 0.0;
<span style="white-space:pre">			</span>}
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>for (int j = 0; j <= n + m3; j++) {
<span style="white-space:pre">			</span>nonbasic[j] = j;
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>for (int i = 1, j = n + m3 + 1; i <= m; i++, j++) {
<span style="white-space:pre">			</span>basic[i] = j;
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>// 引入松弛变量和人工变量
<span style="white-space:pre">		</span>for (int i = m - m3 + 1, j = n + 1; i <= m; i++, j++) {
<span style="white-space:pre">			</span>this.a[i][j] = -1;
<span style="white-space:pre">			</span>this.a[m + 1][j] = -1;
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>// 输入约束系数和右端项
<span style="white-space:pre">		</span>for (int i = 1; i <= m; i++) {
<span style="white-space:pre">			</span>for (int j = 1; j <= n; j++) {
<span style="white-space:pre">				</span>value = a[i - 1][j - 1];
<span style="white-space:pre">				</span>this.a[i][j] = value;
<span style="white-space:pre">			</span>}
<span style="white-space:pre">			</span>value = a[i - 1][n];
<span style="white-space:pre">			</span>if (value < 0) {
<span style="white-space:pre">				</span>error = 1;
<span style="white-space:pre">			</span>}
<span style="white-space:pre">			</span>this.a[i][0] = value;
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>for (int j = 1; j <= n; j++) // 输入目标函数系数
<span style="white-space:pre">		</span>{
<span style="white-space:pre">			</span>value = x[j - 1];
<span style="white-space:pre">			</span>this.a[0][j] = value * minmax;
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>// 引入人工变量,构造第一阶段的辅助目标函数
<span style="white-space:pre">		</span>for (int j = 1; j <= n; j++) {
<span style="white-space:pre">			</span>value = 0;
<span style="white-space:pre">			</span>for (int i = m1 + 1; i <= m; i++)
<span style="white-space:pre">				</span>value += this.a[i][j];
<span style="white-space:pre">			</span>this.a[m + 1][j] = value;
<span style="white-space:pre">		</span>}


<span style="white-space:pre">	</span>}


<span style="white-space:pre">	</span>// 函数enter(objrow)根据目标函数系数所在的行objrow,选取入基变量
<span style="white-space:pre">	</span>public int enter(int objrow) {
<span style="white-space:pre">		</span>int col = 0;
<span style="white-space:pre">		</span>for (int j = 1; j <= this.n + this.m3; j++) {
<span style="white-space:pre">			</span>if (this.nonbasic[j] <= this.n + this.m1 + this.m3
<span style="white-space:pre">					</span>&& this.a[objrow][j] > 10e-8) {
<span style="white-space:pre">				</span>col = j;
<span style="white-space:pre">				</span>break;
<span style="white-space:pre">			</span>}
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>return col;
<span style="white-space:pre">	</span>}


<span style="white-space:pre">	</span>// 函数leave(col)根据入基变量所在的列col,选取离基变量
<span style="white-space:pre">	</span>public int leave(int col) {
<span style="white-space:pre">		</span>double temp = -1;
<span style="white-space:pre">		</span>int row = 0;
<span style="white-space:pre">		</span>for (int i = 1; i <= this.m; i++) {
<span style="white-space:pre">			</span>double val = this.a[i][col];
<span style="white-space:pre">			</span>if (val > 10e-8) {
<span style="white-space:pre">				</span>val = this.a[i][0] / val;
<span style="white-space:pre">				</span>if (val < temp || temp == -1) {
<span style="white-space:pre">					</span>row = i;
<span style="white-space:pre">					</span>temp = val;
<span style="white-space:pre">				</span>}
<span style="white-space:pre">			</span>}
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>return row;
<span style="white-space:pre">	</span>}


<span style="white-space:pre">	</span>// 函数swapbasic(row, col)交换基本变量row和非基本变量col的位置
<span style="white-space:pre">	</span>public void swapbasic(int row, int col) {
<span style="white-space:pre">		</span>int temp = this.basic[row];
<span style="white-space:pre">		</span>this.basic[row] = this.nonbasic[col];
<span style="white-space:pre">		</span>this.nonbasic[col] = temp;
<span style="white-space:pre">	</span>}


<span style="white-space:pre">	</span>// 函数pivot(row, col)以入基变量所在的列col和离基变量所在的行row交叉处元素a[row][col]为轴心,作转轴变换
<span style="white-space:pre">	</span>public void pivot(int row, int col) {
<span style="white-space:pre">		</span>for (int j = 0; j <= this.n + this.m3; j++) {
<span style="white-space:pre">			</span>if (j != col) {
<span style="white-space:pre">				</span>this.a[row][j] = this.a[row][j] / this.a[row][col];
<span style="white-space:pre">			</span>}
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>this.a[row][col] = 1.0 / this.a[row][col];
<span style="white-space:pre">		</span>for (int i = 0; i <= this.m + 1; i++) {
<span style="white-space:pre">			</span>if (i != row) {
<span style="white-space:pre">				</span>for (int j = 0; j <= this.n + this.m3; j++) {
<span style="white-space:pre">					</span>if (j != col) {
<span style="white-space:pre">						</span>this.a[i][j] = this.a[i][j] - this.a[i][col]
<span style="white-space:pre">								</span>* this.a[row][j];
<span style="white-space:pre">						</span>if (Math.abs(this.a[i][j]) < 10e-8)
<span style="white-space:pre">							</span>this.a[i][j] = 0;
<span style="white-space:pre">					</span>}
<span style="white-space:pre">				</span>}
<span style="white-space:pre">				</span>this.a[i][col] = -this.a[i][col] * this.a[row][col];
<span style="white-space:pre">			</span>}
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>swapbasic(row, col);
<span style="white-space:pre">	</span>}


<span style="white-space:pre">	</span>// 函数simplex(objrow)根据目标函数系数所在的行objrow,执行约束标准型线性规划问题的单纯形算法
<span style="white-space:pre">	</span>public int simplex(int objrow) {
<span style="white-space:pre">		</span>int row = 0;
<span style="white-space:pre">		</span>while (true) {
<span style="white-space:pre">			</span>int col = enter(objrow);
<span style="white-space:pre">			</span>if (col > 0) {
<span style="white-space:pre">				</span>row = leave(col);
<span style="white-space:pre">			</span>} else {
<span style="white-space:pre">				</span>return 0;
<span style="white-space:pre">			</span>}
<span style="white-space:pre">			</span>if (row > 0) {
<span style="white-space:pre">				</span>pivot(row, col);
<span style="white-space:pre">			</span>} else {
<span style="white-space:pre">				</span>return 2;
<span style="white-space:pre">			</span>}
<span style="white-space:pre">		</span>}
<span style="white-space:pre">	</span>}


<span style="white-space:pre">	</span>// 构造初始基本可行解的第一阶段单纯形算法由phase1()实现
<span style="white-space:pre">	</span>public int phase1() {
<span style="white-space:pre">		</span>this.error = simplex(this.m + 1);
<span style="white-space:pre">		</span>if (this.error > 0) {
<span style="white-space:pre">			</span>return this.error;
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>for (int i = 1; i <= this.m; i++) {
<span style="white-space:pre">			</span>if (this.basic[i] > this.n + this.m1 + this.m3) {
<span style="white-space:pre">				</span>if (this.a[i][0] > 10e-8) {
<span style="white-space:pre">					</span>return 3;
<span style="white-space:pre">				</span>}
<span style="white-space:pre">				</span>for (int j = 1; j <= this.n; j++) {
<span style="white-space:pre">					</span>if (Math.abs(this.a[i][j]) >= 10e-8) {
<span style="white-space:pre">						</span>pivot(i, j);
<span style="white-space:pre">						</span>break;
<span style="white-space:pre">					</span>}
<span style="white-space:pre">				</span>}
<span style="white-space:pre">			</span>}
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>return 0;
<span style="white-space:pre">	</span>}


<span style="white-space:pre">	</span>public int phase2() {
<span style="white-space:pre">		</span>return simplex(0);
<span style="white-space:pre">	</span>}


<span style="white-space:pre">	</span>// 函数对一般的线性规划问题执行2阶段单纯形算法
<span style="white-space:pre">	</span>public int compute() {
<span style="white-space:pre">		</span>if (this.error > 0)
<span style="white-space:pre">			</span>return this.error;
<span style="white-space:pre">		</span>if (this.m != this.m1) {
<span style="white-space:pre">			</span>this.error = phase1();
<span style="white-space:pre">			</span>if (this.error > 0)
<span style="white-space:pre">				</span>return this.error;
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>return phase2();
<span style="white-space:pre">	</span>}


<span style="white-space:pre">	</span>// 函数时执行2阶段单纯形算法的共有函数
<span style="white-space:pre">	</span>public double[] solve() {
<span style="white-space:pre">		</span>error = compute();
<span style="white-space:pre">		</span>switch (error) {
<span style="white-space:pre">		</span>case 0:
<span style="white-space:pre">			</span>return output();
<span style="white-space:pre">		</span>case 1:
<span style="white-space:pre">			</span>System.out.println("输入数据错误!");
<span style="white-space:pre">			</span>break;
<span style="white-space:pre">		</span>case 2:
<span style="white-space:pre">			</span>System.out.println("无界解!");
<span style="white-space:pre">			</span>break;
<span style="white-space:pre">		</span>case 3:
<span style="white-space:pre">			</span>System.out.println("无可行解!");
<span style="white-space:pre">			</span>break;
<span style="white-space:pre">		</span>default:
<span style="white-space:pre">			</span>break;
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>return new double[0];
<span style="white-space:pre">	</span>}


<span style="white-space:pre">	</span>// 函数输出2阶段单纯形算法的计算结果
<span style="white-space:pre">	</span>public double[] output() {
<span style="white-space:pre">		</span>int basicp[] = new int[n + 1];
<span style="white-space:pre">		</span>for (int i = 0; i <= n; i++) {
<span style="white-space:pre">			</span>basicp[i] = 0;
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>for (int i = 1; i <= m; i++) {
<span style="white-space:pre">			</span>if (basic[i] >= 1 && basic[i] <= n) {
<span style="white-space:pre">				</span>basicp[basic[i]] = i;
<span style="white-space:pre">			</span>}
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>double[] ans = new double[n+1];
<span style="white-space:pre">		</span>for (int i = 1; i <= n; i++) {
//<span style="white-space:pre">			</span>System.out.print("x" + i + "=");
<span style="white-space:pre">			</span>if (basicp[i] != 0) {
<span style="white-space:pre">				</span>//System.out.print(a[basicp[i]][0]);
<span style="white-space:pre">				</span>ans[i-1] = Math.ceil(a[basicp[i]][0]);
<span style="white-space:pre">			</span>} else {
<span style="white-space:pre">				</span>ans[i-1] = 0;
<span style="white-space:pre">				</span>//System.out.print("0");
<span style="white-space:pre">			</span>}
<span style="white-space:pre">			</span>//System.out.println();
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>ans[n] = Math.ceil(-1 * minmax * a[0][0]);
<span style="white-space:pre">		</span>//System.out.println("最优值:" + -minmax * a[0][0]);
<span style="white-space:pre">		</span>return ans;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>// public static void main(String[] args) {
<span style="white-space:pre">	</span>// double a[][] = {{1,-2,1,11},{-2,0,1,1},{-4,1,2,3}};
<span style="white-space:pre">	</span>// int x[] = {-3,1,1};
<span style="white-space:pre">	</span>// xx lp = new xx(-1,3,3,1,1,1,a,x);
<span style="white-space:pre">	</span>// lp.solve();
<span style="white-space:pre">	</span>// }
}


你可能感兴趣的:(线性规划 单纯性法)