原单纯形法求解线性规划

前言:最近学习使用智能算法求解线性规划问题过程中,为了对算法结果进行比对,思前想后还是使用单纯形法进行验证。原因是单纯形法曾出现于运筹学课堂,并且使用编程语言编写过,还有那么些印象。

单纯形法:
具体步骤是,从线性方程组找出一个个的单纯形,每一个单纯形可以求得一组解,然后再判断该解使目标函数值是增大还是变小了,决定下一步选择的单纯形。通过优化迭代,直到目标函数实现最大或最小值。

原理描述可参考博客:运筹学——线性规划及单纯形法求解

一般线性规划满足:
max z=c_1x_1+c_2x_2+…+c_nx_n
a_ij*x_j=b_j
x_j>=0

求解过程:
(1)若c_j均小于或者等于0,则当前为最优解;否则,进行下一步;
(2)使用max{c_j|c_j>0}计算进基列;
(3)使用min{b_j/a_ij|a_ij>0}计算变换行;
(4)进行行初等变换;
(5)得到最优解。

对于线性规划:
max z=2x_1+3x_2
2x_1+2x_2<=12
x_1+2x_2<=8
4x_1<=16
4x_2<=12
有最优解z=14,并且x_1=4以及x_2=2。

以下使用单纯形法求解该线性规划问题,表格形式为个人使用习惯
(1)建立如下单纯形表
在这里插入图片描述
其中:黄色区域表示b_j;
红色区域表示-z;
绿色区域表示a_ij;
蓝色区域表示b_j。
(2)确定进基列
在这里插入图片描述
(3)确定变换行
在这里插入图片描述
得到变换行(黄色),和进基列(棕色),
在这里插入图片描述
然后将该元素化为1,得到:
在这里插入图片描述
(4)行初等变换
在这里插入图片描述
(5)判断是否继续迭代
在这里插入图片描述
该元素大于0.则继续迭代。
(6)3次迭代以后,得到
在这里插入图片描述
根据表格得到计算结果:Z(4,2,0,0,0,4)=14
在这里插入图片描述
将该计算过程代码化即可得到原单纯形法求解线性规划问题。
(1)判断原则

//判断原则->c_j是否全小于等于0
double Principle(double target_col[var_num]) {
	//初始化目标行
	for (int j = 0; j < var_num; j++) {
		target_col[j] = simplex_tab[0][j];
	}
	int count = 0;//计数
	for (int i = 0; i < var_num; i++) {
		if (target_col[i] <= 0)
			count++;
	}
	
	if (count == var_num) {
		optimal_val = simplex_tab[0][6] * (-1.0);
		return true;//满足判断原则:目标系数<=0;
	}
	else
		return false;
}

(2)进基列

//进基列
double EnterCol(double target_col[var_num]) {
	//目标行最大的正数
	int column_max;//记录最大列
	
	double count_max = target_col[0];
	column_max = 0;
	for (int i = 1; i < var_num;i++) {
		if (target_col[i] > 0) {
			if (target_col[i] > count_max) {
				count_max = target_col[i];
				column_max = i;
			}
		}
	}
	return column_max;
}

(3)变换行

//进基行
double EnterRow() {
	int row_min;//记录最小行

	double specific_val[cons_num+1];//记录比值
	int row_val[cons_num+1];//记录行号
	for (int i = 0; i < cons_num+1;i++) {
		specific_val[i] = -1;
		row_val[i] = -1;
	}
	
	for (int i = 1; i < cons_num+1;i++) {
		if ((simplex_tab[i][enter_var_col] > 0) && (simplex_tab[i][var_num] >= 0)) {
			specific_val[i] = simplex_tab[i][var_num] / simplex_tab[i][enter_var_col];
			row_val[i] = i;
		}
	}
	for (int i = 0; i < cons_num + 1; i++) {
		cout << specific_val[i] << " ";
	}
	cout << endl;
	//比较大小
	int count_min = 1000;
	for (int i = 0; i < cons_num + 1; i++) {
		if (specific_val[i] != -1) {
			if (specific_val[i] < count_min) {
				count_min = specific_val[i];
				row_min = i;
			}
		}
	}
	return row_min;
}

(4)单纯形法

//简单单纯形法
void ClassSimplex(){
	int count = 0;
	//while(count<3){
	while (Principle(target_col)==false) {
		Principle(target_col);
		enter_var_col = EnterCol(target_col);//确定进基列
		enter_var_row = EnterRow();//确定进基行
		cout << enter_var_col << endl;
		cout << enter_var_row << endl;

		//进基行列化为1
		double row_col_val = simplex_tab[enter_var_row][enter_var_col];
		for (int j = 0; j < var_num + 1;j++) {
			simplex_tab[enter_var_row][j] = double(int(simplex_tab[enter_var_row][j]*100/ row_col_val))/100.0;
		}
		for (int i = 0; i < cons_num + 1; i++) {for (int j = 0; j < var_num + 1; j++) {cout << simplex_tab[i][j] << " ";}cout << endl;}cout << endl;
		
		//行初等变换
		for (int i = 0; i < cons_num + 1;i++) {
			double count_change = (-1.0)*simplex_tab[i][enter_var_col] / simplex_tab[enter_var_row][enter_var_col];
			cout << endl<< count_change << endl;
			if (i != enter_var_row) {
				for (int j = 0; j < var_num + 1; j++) {
					simplex_tab[i][j] += simplex_tab[enter_var_row][j] * count_change;
				}
			}
		}
		for (int i = 0; i < cons_num + 1; i++) { for (int j = 0; j < var_num + 1; j++) { cout << simplex_tab[i][j] << " "; }cout << endl; }cout << endl;
		count++;
	}
	cout << "最优解:" << optimal_val << endl;
}

(5)变量值

//对应的变量值
void SolveVal(double simplex_tab[cons_num + 1][var_num + 1]) {
	//初始化变量值
	for (int i = 0; i < var_num;i++) {
		var_value[i] = 0;
	}

	double column_val[cons_num+1];//记录列值

	for (int j = 0; j < var_num + 1;j++) {
		int count_0 = 0;
		int count_1 = 0;
		int count_1_index = 0;
		for (int i = 0; i < cons_num + 1; i++) {
			column_val[i] = simplex_tab[i][j];
			if (column_val[i] == 0)
				count_0++;
			if (column_val[i] == 1) {
				count_1_index = i;
				count_1++;
			}
		}
		if (count_0==cons_num && count_1==1) {
			var_value[j] = simplex_tab[count_1_index][var_num];
		}
	}
	cout << "变量值:";
	for (int j = 0; j < var_num + 1; j++) {
		cout << var_value[j] << " ";
	}
	cout << endl;
}

备注:原单纯形法求解线性规划问题是比较直观的,但计算过程复杂。在实际应用过程中,改进单纯形法的应用效果是显著的。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南音小榭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值