C++实现单纯性算法

这篇文章是针对我前段时间提出的问题——(4条消息) 实现单纯性算法时遇到的精度问题-编程语言-CSDN问答

的一个最终回答,实现了大M法和单纯性算法

#include <iostream>
#include <iomanip>
#include <vector>
#include <cmath>

using std::vector;
using std::cin;
using std::cout;
using std::endl;

#define M 1e+9

/**
 * 1. func scale: to scale a row, make the pivot variable 1;
 * 2. func subtract: to subtract one row from another in order to make the main variable on other lines 0;
**/
void scale(vector<vector<double>>& matrix, int row_index, double scale_num)
{
    // scale_num is  the value of the pivot variable
    for (int i = 0; i < matrix[row_index].size(); i++)
    {
        matrix[row_index].at(i) /= scale_num;
    }
}

void substract(vector<vector<double>>& matrix, int row_index_1, int pivot_row, double muti)
{
    /**
     * row_index_1 is some non-pivot row;
     * row_index_2 is the pivot row;
    **/
    
    for (int i = 0; i < matrix[row_index_1].size(); i++)
    {
        matrix[row_index_1].at(i) -= matrix[pivot_row].at(i) * muti;
    }
    
}

void gaussian(vector<vector<double>>& simplex_matrix, int pivot_column, int pivot_row)
{
    /*this function should make the pivot column value in other rows 0*/
    scale(simplex_matrix, pivot_row, simplex_matrix[pivot_row][pivot_column]);
    
    for (int pres_row = 0; pres_row < simplex_matrix.size(); pres_row++)
    {
        if(pres_row != pivot_row) 
        {
            double muti = simplex_matrix[pres_row][pivot_column] / simplex_matrix[pivot_row][pivot_column];
            substract(simplex_matrix, pres_row, pivot_row, muti);
        }
    }
}

/**
 * 1. input: input and store the constraints
 * 2. augment: augment the previous matrix, store the augmented form of the matrix(simplex matrix), initliaze the basis and variable values
**/
void input(vector<vector<double>>& simplex_matrix, vector<bool>& need_artificial_variable, int variable_num, int constraint_num)
{
    int RHS_index = simplex_matrix[0].size() - 1;
    int objective_function_index = simplex_matrix.size() - 1;

    /*input the constraint*/
    //cout<<"input constraint"<<endl;
    for (size_t i = 0; i < constraint_num; i++)
    {
        for (size_t j = 0; j < variable_num; j++)
        {
            cin>>simplex_matrix[i][j];
        }
    }
    
    /*input the RHS values*/
    //cout<<"input RHS values"<<endl;
    for (size_t i = 0; i < constraint_num; i++)
    {
        cin>>simplex_matrix[i][RHS_index];
        if(simplex_matrix[i][RHS_index] < 0) //If the RHS_value is negative, we need to transform it into a positive value.
        {
            for (size_t j = 0; j < simplex_matrix[i].size(); j++)
            {
                simplex_matrix[i][j] *= -1;
            }
            need_artificial_variable[i] = true;
        }
    }
    
    /*input the objective function*/
    //cout<<"input objective function"<<endl;
    for (size_t i = 0; i < variable_num; i++)
    {
        int temp;
        cin>>temp;
        simplex_matrix[objective_function_index][i] = -temp;
    }
}

void augment(vector<vector<double>>& simplex_matrix, vector<bool>& need_artificial_variable, vector<int>& basis, vector<double>& variable_values, int variable_num, int constratint_num)
{
    int RHS_index = simplex_matrix[0].size() - 1;
    int objective_function_index = simplex_matrix.size() - 1;

    /*add the slack variables*/
    int slack_index = variable_num;
    for (size_t i = 0; i < constratint_num; i++)
    {
        if(!need_artificial_variable[i])
        {
            simplex_matrix[i][slack_index] = 1;
        }
        else
        {
            simplex_matrix[i][slack_index] = -1;
        }
        basis[i] = slack_index;//The slack variable is going to be the basis, if there is no artificial variable in the constraint.
        slack_index++;
    }

    /*add the artificial variables*/
    int artificial_index = slack_index;
    for (size_t i = 0; i < constratint_num; i++)
    {
        if(need_artificial_variable[i])
        {
            simplex_matrix[i][artificial_index] = 1;
            simplex_matrix[objective_function_index][artificial_index] = M;
            basis[i] = artificial_index; //update the basis, if there is an artificial variable in the constraint, it is always the initial basis.
            /*Eliminate the coefficents in the objective function*/
            substract(simplex_matrix, objective_function_index, i, M);
            artificial_index++;
        }
    }

    /*initliaze the basis variable values*/
    for (size_t i = 0; i < basis.size(); i++)
    {
        variable_values[basis[i]] = simplex_matrix[i][RHS_index];
    }
}

/**
 * 1. test_optimal: test whether the solution is optimal
 * 2. test_unbounded: test whether the problem is unbounded
 * 3. test_feasible: test whether the problem has no feasiable solution
**/
bool test_optimal(vector<vector<double>>& simplex_matrix)
{
    /*checks the objective function*/
    int positive_counter = 0;
    int RHS_index = simplex_matrix[0].size() - 1;
    int objective_function_index = simplex_matrix.size() - 1;

    for (size_t i = 0; i < simplex_matrix[objective_function_index].size() - 1; i++)
    {
        if (simplex_matrix[objective_function_index][i] >= -1e-5)
        {
            positive_counter++;
        }
    }
    
    if (positive_counter == simplex_matrix[objective_function_index].size() - 1)
    {
        return true;
    }
    
    return false;
}

bool test_unbounded(vector<vector<double>>& simplex_matrix, int pivot_column)
{
    int negative_counter = 0;
    int RHS_index = simplex_matrix[0].size() - 1;
    int objective_function_index = simplex_matrix.size() - 1;

    for (size_t i = 0; i < simplex_matrix.size() - 1; i++)
    {
        if (simplex_matrix[i][pivot_column] <= 0)
        {
            negative_counter++;
        }
    }
    
    if (negative_counter == simplex_matrix.size() - 1)
    {
        return true;
    }
    return false;

}

bool test_fasiable(vector<int>& basis, vector<double>& variable_values, int variable_num, int constraint_num)
{
    int slack_num = variable_num + constraint_num;
    for (size_t i = 0; i < basis.size(); i++)
    {
        if (basis[i] >= slack_num && std::abs(variable_values[basis[i]]) >= 1e-5)
        {
            return true;
        }
    }
    
    return false;
}

/**
 * 1. find_in_variable: find the in-basis variable(which way to go)
 * 2. find_out_variable: find the out-basis variable(how far to go)
**/
int find_in_variable(vector<vector<double>>& simplex_matrix, vector<int>& basis, vector<double>& variable_values, int variable_num, int constraint_num)
{
    /*find the non-basis variable with the minimum coefficent*/
    int RHS_index = simplex_matrix[0].size() - 1;
    int objective_function_index = simplex_matrix.size() - 1;

    double min_value = 1e+9;
    int min_index = -1;
    for (size_t i = 0; i < simplex_matrix[objective_function_index].size() - 1; i++)
    {
        if(simplex_matrix[objective_function_index][i] < min_value)
        {
            bool in_basis = false;
            for (size_t j = 0; j < basis.size(); j++)
            {
                if (basis[j] == i)
                {
                    in_basis = true;
                    break;
                }
            }

            if(!in_basis && simplex_matrix[objective_function_index][i] < 0)
            {
                min_value = simplex_matrix[objective_function_index][i];
                min_index = i;
            }
        }
    }
    
    return min_index;
}

int find_out_variable(vector<vector<double>>& simplex_matrix, vector<int>& basis, vector<double>& variable_values, int pivot_column, int variable_num, int constraint_num)
{
    /*find the minium ratio in the pivot column*/
    int RHS_index = simplex_matrix[0].size() - 1;
    int objective_function_index = simplex_matrix.size() - 1;

    double min_ratio = 1e+9;
    int min_index = -1;
    for (size_t i = 0; i < simplex_matrix.size() - 1; i++)
    {
        if(simplex_matrix[i][pivot_column] <= 0)
        {
            continue;
        }
        double ratio = simplex_matrix[i][RHS_index] / simplex_matrix[i][pivot_column];
        //cout<<"ratio:"<<ratio<<endl;
        if (ratio < min_ratio)
        {
            //cout<<"min!"<<endl;
            min_ratio = ratio;
            min_index = i;
        }
    }
    
    return min_index;
}

int simplex(vector<vector<double>>& simplex_matrix, vector<int>& basis, vector<double>& variable_values, int variable_num, int constraint_num)
{
    int RHS_index = simplex_matrix[0].size() - 1;
    int objective_function_index = simplex_matrix.size() - 1;
    int iter_counter = 0;

    while (true)
    {
        /*cout<<"----------------------------------------------------------------------------------------------------------"<<endl;
        for (size_t i = 0; i < simplex_matrix.size(); i++)
        {
            for (size_t j = 0; j < simplex_matrix[i].size(); j++)
            {
                cout<<std::setw(15)<<simplex_matrix[i][j];
            }
            cout<<endl;
        }
        cout<<"basis: ";
        for (size_t i = 0; i < basis.size(); i++)
        {
            cout<<basis[i]<<' ';
        }
        cout<<endl;

        cout<<"variable_values: ";
        for (size_t i = 0; i < variable_values.size(); i++)
        {
            cout<<variable_values[i]<<' ';
        }
        cout<<endl;*/
        
        if (test_optimal(simplex_matrix))
        {
            return 1;
        }
        int in_variable = find_in_variable(simplex_matrix, basis, variable_values, variable_num, constraint_num);
        //cout<<"in variable: "<<in_variable<<endl;

        if (test_unbounded(simplex_matrix, in_variable))
        {
            return 2;
        }
        int out_variable = find_out_variable(simplex_matrix, basis, variable_values, in_variable, variable_num, constraint_num);
        //cout<<"out variable: "<<out_variable<<endl;

        gaussian(simplex_matrix, in_variable, out_variable);

        variable_values[basis[out_variable]] = 0;
        basis[out_variable] = in_variable;
        for (size_t i = 0; i < basis.size(); i++)
        {
            variable_values[basis[i]] = simplex_matrix[i][RHS_index] / simplex_matrix[i][basis[i]];
        }
    }

}

int main()
{
    int variable_num, constraint_num;
    cin>>constraint_num>>variable_num;

    vector<vector<double>> simplex_matrix(constraint_num + 1, vector<double>(variable_num + constraint_num*2 + 1));
    vector<int> basis(constraint_num); //The current basis
    vector<bool> need_artificial_variable(constraint_num, false);
    vector<double> variable_values(variable_num + constraint_num*2);
    int RHS_index = simplex_matrix[0].size() - 1;
    int objective_function_index = simplex_matrix.size() - 1;

    input(simplex_matrix, need_artificial_variable, variable_num, constraint_num);
    augment(simplex_matrix, need_artificial_variable, basis, variable_values, variable_num, constraint_num);
    
    int return_code = simplex(simplex_matrix, basis, variable_values, variable_num, constraint_num);
    for (size_t i = 0; i < basis.size(); i++)
    {
        variable_values[basis[i]] = simplex_matrix[i][RHS_index];
    }
    /*for (int i = 0; i < variable_num; i++)
    {
        cout<<std::fixed<<std::showpoint<<std::setprecision(15)<<variable_values[i]<<' ';
    }
    cout<<endl;*/

    if (test_fasiable(basis, variable_values, variable_num, constraint_num))
    {
        return_code = 3;
    }

    switch (return_code)
    {
    case 1:
        cout<<"Bounded solution"<<endl;
        
        for (int i = 0; i < variable_num; i++)
        {
            cout<<std::fixed<<std::showpoint<<std::setprecision(15)<<variable_values[i]<<' ';
        }
        cout<<endl;
        break;    
    case 2:
        cout<<"Infinity"<<endl;
        break;
    case 3:
        cout<<"No solution"<<endl;
        break;
    default:
        break;
    }

    return 0;   
}

代码如上

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值