单纯形算法求解线性规划问题(依据《算法导论》实现)

该博客介绍如何依据《算法导论》实现单纯形算法,用于求解线性规划问题。通过输入线性规划的松弛形式,初始化单纯形表格,然后迭代寻找最优解。当所有非基变量的系数小于等于0时,算法终止,输出最优解。
摘要由CSDN通过智能技术生成
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
const int MAXN  = 100;
const double INF = 999999.0;
const double EPS = 1e-9;
double b[MAXN]; //constraint in each equation
double x[MAXN]; //last result
double a[MAXN][MAXN]; //coefficient of each non-basic variable
double c[MAXN]; //coefficient of target function
int n; //denote number of non-basic variables as n
int m; //denote number of basic variables as m
int z; //target function
bool isBasic[MAXN]; //mark the basic

double b1[MAXN]; //constraint in each equation
double a1[MAXN][MAXN]; //coefficient of each non-basic variable
double c1[MAXN]; //coefficient of target function

void InitializeSimplex();
void Simplex();
void GetPivot(int leave, int enter);

int main() {

    //input a linear programming as slack form
    InitializeSimplex();
    Simplex();
    cout << "the optimal solution is " << z << endl;
    return 0;
}

void InitializeSimplex(){
    cin >> n >> m;
    memset(a, 0.0, sizeof(a));
    memset(isBasic, false, sizeof(isBasic));
    for (int i = 1; i <= n; i++) {
        cin >> c[i];
    }
    for (int i = 1; i <= m; i++) {
        cin >> b[i+n];
        for (int j = 1; j <= n; j++) {
            cin >> a[i+n][j];
        }
        isBasic[i+n] = true;
    }
    z = 0;
}

void Simplex() {
    int z = 0;
    while (1) {
        //find s non-basic variable to enter.if all c[] are less than 0, break;
        bool flag = false;
        int enter = 0;
        for (int i = 1; i <= n+m; i++) {
            if (!isBasic[i] && c[i] > 0) {
                flag = true;
                enter = i;
                break;
            }
        }
        if (!flag) break;

        //find a basic variable to leave
        double minimalConstraint = INF;
        int leave = 0;
        for (int i = 1; i <= n+m; i++) {
            if (isBasic[i] && a[i][enter] > 0) {
                if (minimalConstraint > b[i] / a[i][enter]) {
                    minimalConstraint = b[i] / a[i][enter];
                    leave = i;
                }
            }
        }

        //unbounded
        if (fabs(minimalConstraint - INF) < EPS) {
            cout << "UNBOUNDED!" << endl;
            return;
        }
        else {
            // cout <<"***"<<endl;
            // cout <<leave<< " "<<enter<<endl;
            GetPivot(leave, enter);
        }

    }

    int ans = 1;
    for (int i = 1; i <= n+m; i++) {
         if (isBasic[i]) {
            x[ans] = b[i];
            cout <<"x" << ans <<": " << x[ans] << endl;
            ans ++;
         }
    }
}

void GetPivot(int leave, int enter) {
    //compute the coefficients of the equation for new basic variable xe
    b1[enter] = b[leave] / a[leave][enter];
    for (int i = 1; i <= n+m; i++) {
        if (!isBasic[i] && (i != enter)) {
            a1[enter][i] = a[leave][i] / a[leave][enter];
        }
    }
    a1[enter][leave] = 1.0 / a[leave][enter];

    //compute the coefficients of the remaining constraints
    for (int i = 1; i <= n+m; i++) {
        if (isBasic[i] && (i != leave)){
            b1[i] = b[i] - a[i][enter] * b1[enter];
            for (int j = 1; j <= n+m; j++) {
                if (!isBasic[j] && (j != enter)) {
                    a1[i][j] = a[i][j]  - a[i][enter] * a1[enter][j];
                }
            }
            a1[i][leave] = -1 * a[i][enter] * a1[enter][leave];
        }
    }

    //compute the objective function
    z = z + c[enter] * b1[enter];
    for (int i = 1; i <= n+m; i++) {
        if (!isBasic[i] && (i != enter)) {
            c1[i] = c[i] - c[enter] * a1[enter][i];
        }
    }
    c1[leave] = -1 * c[enter] * a1[enter][leave];

    //update new sets of basic and nonbasic variables
    isBasic[leave] = false;
    isBasic[enter] = true;

    for (int i = 1; i <= n+m; i++) {
        c[i] = c1[i];
        b[i] = b1[i];
       // cout <<"c="<<c[i]<<" b="<<b[i]<<endl;
        for (int j = 1; j <= n+m; j++) {
            a[i][j] = a1[i][j];
           // if (a[i][j]!=0)
           // cout <<" a[i][j] = " <<a[i][j]<<endl;
        }
    }
}
/*
3 3
2 -3 3
7 1 1 1
-7 -1 -1 1
4 1 -2 2
// 6 1 0   9

3 3
3 1 2
30 1 1 3
24 2 2 5
36 4 1 2
//8 4 18 28
*/

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值