利用c++实现单纯形表算法

文章目录

  • 利用c++实现单纯形表算法
    • 0.背景
    • 1.原理
    • 2.具体代码
    • 3.总结

利用c++实现单纯形表算法

0.背景

对于线性规划问题,使用单纯形法进行表上作业所得到的表格。直接用公式进行单纯形法的迭代计算是很不方便的,其中最复杂的是进行基变换,但施行基变换所用的实际上是消元法。由线性代数知道,用消元法解线性方程组可在增广矩阵上利用行初等变换进行计算。因此,我们可以将单纯形法的全部计算过程在一个类似增广矩阵的数表上进行,这种表格称为单纯形表(simplex table)。

1.原理

略(不是重点)

2.具体代码

由于写代码的时候打算顺便复习一下 面向对象的编程,所以就写了个类,来实现单纯形法。实际上不用类,写几个函数也是完全可以实现的。
还有就是因为核心是算法,就没有在输入上过多纠结,直接提前在代码中设定好行和列了。

#include
using namespace std;
typedef long double ld;
const int ROW = 4;
const int COLUMN = 6;
class dan_chun_xing_table 
{
    private:
        ld table[ROW][COLUMN];
        int row;
        int column;
    public:
        bool if_best;
        bool if_gg;
        dan_chun_xing_table();
        bool best_judge();
        bool gg_judge();
        int row_judge(int column);
        int column_judge();
        void change(int row, int column);
        void show();
        ~dan_chun_xing_table();
};
int main()
{
    bool Continue = 1;
    while(Continue)
    {
        dan_chun_xing_table table1;
        int times = 0;
        while(!(table1.if_best))
        {
            times++;
            cout<<"迭代次数"<<times<<endl;
            if(table1.if_gg)
            {
                cout<<"无界"<<endl;
                goto lable1;
            }
            int column = table1.column_judge();
            int row;
            if (column != -1)
            {
                row = table1.row_judge(column);
            }
            if(table1.if_best)
            {
                cout<<"best"<<endl;
                goto lable1;
            }
            if(table1.if_gg)
            {
                cout<<"无界"<<endl;
                goto lable1;
            }
            table1.change(row,column);
            table1.show();
            if (times == 10)
            {
                return 0;
            }
        }
        cout<<"出来啦~"<<endl;
        lable1:
        table1.show();
        cout<<"继续计算请输入1 结束程序请输入0"<<endl;
        cin>>Continue;
    };
    return 0;
}

dan_chun_xing_table::dan_chun_xing_table()
{
    for (int i = 0; i < ROW; i++)
    {
        for (int j = 0; j < COLUMN; j++)
        {
            cout<<i<<" "<<j<<endl;
            cin>>table[i][j];
        }
    }
    // cout<<"完啦"<
    if_best = best_judge();
    if_gg = gg_judge();
}
bool dan_chun_xing_table::best_judge()
{
    for (int i = 0; i < COLUMN; i++)
    {
        if (table[0][i] > 0)
        {
            return 0;
        }
    }
    return 1;
}

bool dan_chun_xing_table::gg_judge()
{
    for(int i = 0; i < COLUMN; i++)
    {
        if(table[0][i] > 0)
        {
            bool tmp = 1;
            for (int j = 0; j < ROW; j++)
            {
                if (table[j][i] > 0)
                {
                    tmp = 0;
                    break;
                }
            }
            if (tmp == 1)
            {
                return 1;
            }
        }
    }
    return 0;
}

int dan_chun_xing_table::column_judge()
{
    for (int i = 0; i < COLUMN; i++)
    {
        if (table[0][i]>0)
        {
            return i;
        }
    }
    if_best = 1;
    return -1;
}

int dan_chun_xing_table::row_judge(int column)
{
    ld min = 9999999999999999.0;
    int res = -1;
    for(int i = 1; i < ROW; i++)
    {
        if ((table[i][COLUMN-1]/table[i][column]<min)&&(table[i][COLUMN-1]/table[i][column]>0)&&(table[i][column]!=0))
        {
            min = table[i][COLUMN-1]/table[i][column];
            res = i;
        }
    }
    if(res == -1)
    {
        if_gg = 1;
    }
    return res;
}

void dan_chun_xing_table::change(int row, int column)
{
    ld tmp_0 = table[row][column];
    cout<<"row:"<<row<<"column:"<<column<<"tmp_0:"<<tmp_0<<endl;
    for (int i = 0; i < COLUMN; i++)
    {
        table[row][i]= table[row][i]/tmp_0;
        if ((table[row][i]<1e-10)&&(table[row][i]>-1e-10))
        {
            table[row][i]=0;
        }
    }
    for (int i = 0; i < ROW; i++)
    {
        if (i == row)
        {
            continue;
        }
        ld tmp_1 = table[i][column];
        ld tmp_2 = table[row][column];
        for (int j = 0; j < COLUMN; j++ )
        {
            
            table[i][j] = table[i][j] - tmp_1 / tmp_2 * table[row][j];
            if ((table[i][j]<1e-10)&&(table[i][j]>-1e-10))
            {
                table[i][j]=0;
            }
        }
    }
}

void dan_chun_xing_table::show()
{
    for (int i = 0; i < ROW; i++)
    {
        for (int j = 0; j < COLUMN; j++)
        {
            cout<<table[i][j]<<" ";
        }
        cout<<endl;
    }
    cout<<"最佳:"<<if_best<<"无解:"<<if_gg;
    cout<<endl<<"最小值为"<<table[0][COLUMN-1]<<endl;
}

dan_chun_xing_table::~dan_chun_xing_table()
{
    cout<<"finish"<<endl;
}

遇到的bug:
1.数组最后一个元素的序号是长度-1(白给)
2.浮点运算有误差,会使得本来是0的结果变成一个极小的值。
3.数组中的数会变,要提前用临时变量把目标的数搞出来。

3.总结

写代码的时候就应该直接写成便于调试的形式,而不是直接一步到位的成品形式。
回头有时间会补充一下算初始解的算法。

你可能感兴趣的:(算法,c++,线性代数)