首页 > 编程语言 >线性规划之单纯形算法

线性规划之单纯形算法

时间:2023-08-13 22:23:50浏览次数:50  
标签:begin frac 线性规划 单纯形 算法 end cases &+ &-

学了很长时间,一直不是很能理解,所以就准备写一篇。
这篇文章只讲单纯形算法

假设我们已经得到了标准型:

\[\begin{aligned} \max:\sum\limits_{i=1}^na_ix_i\\ \sum\limits_{i=1}^nb_{j,i}x_i=c_j&,j=1,2\dots m\\ x_i\geqslant 0&,i=1,2\dots n \end{aligned}\]

而得到最优解的过程就是:
找到一个基变量和非基变量,将他们交换。我们通过不断地交换,不断地让答案更优。

这就是在凸壳上不断向最优解移动的过程。

先据一组数据作为具体的例子:

\[max:5x_1+2x_2 \]

\[\begin{cases} 30x_1+20x_2+x_3=160\\ 5x_1+x_2+x_4=15\\ x_1+x_5=4\\ x_1,x_2,x_3,x_4,x_5\geqslant 0 \end{cases}\]

有 \(m\) 条限制,我们分别令 \(x_3,x_4,x_5\) 为其基变量,\(x_1,x_2\) 为非基变量。
我们可以得到

\[\begin{aligned} max:&&5x_1&+2x_2\\ x_3&=160&-30x_1&-20x_2\\ x_4&=15&-5x_1&-x_2\\ x_5&=4&-x_1\\ \end{aligned} \]

我们令所有的非基变量为 \(0\),我们可以得到一组解 \(\begin{cases}x_1=0\\x_2=0\\x_3=160\\x_4=15\\x_5=4\end{cases}\)。

我们获得了一个小的可怜的答案——\(0\)。
而在我们要最大化的答案中,\(x_1\) 和 \(x_2\) 的系数均 \(>0\),也就意味着,我们增大其中任何一个数又可以让答案变优,所以我们贪心地选择系数较大的 \(x_1\)。
我们把它从 \(0\) 增大到某一个正实数,我们需要找到它的上界,也就是在 \(x_1\) 不断地增加的过程中,哪一个非基变量会先变成 \(0\)。

仍然令其它非基变量是 \(0\),我们可以得到三个基变量的限制:\(\begin{cases}x_3=160-30x_1\\x_4=15-5x_1\\x_5=4-x_1\end{cases}\),他们分别要求 \(\begin{cases}x_1\leqslant \frac{16}{3}\\x_1\leqslant 3\\x_1\leqslant 4\end{cases}\),其中最紧的限制为 \(x_4\),我们就将 \(x_4\) 变成非基变量,把 \(x_1\) 变成基变量。我们就需要用 \(x_4\) 和其他的非基变量来替换 \(x_1\),根据等式 \(x_4=15-5x_1-x_2\) 可以得到 \(x_1=3-\frac{1}{5}x_4-\frac{1}{5}x_2\)。

替换可以得到新的限制:

\[\begin{aligned} max:&15&-x_4&+x_2\\ x_3=&70&+6x_4&-14x_2\\ x_1=&3&-\frac{1}{5}x_4&-\frac{1}{5}x_2\\ x_5=&1&+\frac{1}{5}x_4&+\frac{1}{5}x_2\\ \end{aligned} \]

这个限制我们可以得到解 \(\begin{cases}x_1=3\\x_2=0\\x_3=70\\x_4=0\\x_5=1\end{cases}\)。
接下来我们继续重复这个过程,发现 \(x_4\) 的系数是负的,我们交换它不会使得答案变优,所以我们只能替换 \(x_2\)。

仍然是有三条限制:\(\begin{cases}x_3=70-14x_2\\x_1=3-\frac{1}{5}x_2\\x_5=1+\frac{1}{5}x_2\end{cases}\),三个方程分别解出来为 \(\begin{cases}x_2\leqslant 5\\x_2\leqslant 15\\x_2\geqslant -5\end{cases}\),显然第三条限制是没有用的,其中最紧的限制是 \(x_3\) 的限制,所以考虑将 \(x_2\) 和 \(x_3\) 进行交换,得到 \(x_2=5-\frac{1}{14}x_3+\frac{3}{7}x_4\)。

替换得到:

\[\begin{aligned} max:&20&-\frac{4}{7}x_4&-\frac{1}{14}x_3\\ x_2=&5&-\frac{1}{14}x_3&+\frac{3}{7}x_4\\ x_1=&2&-\frac{1}{70}x_3&-\frac{2}{7}x_4\\ x_5=&6&+\frac{1}{70}x_3&+\frac{2}{7}x_4\\ \end{aligned} \]

发现剩下的两个系数都是 \(<0\) 了,所以这就是可能的最优解了。

我们抽象一下刚才的过程,我们就可以得到一个具体的过程了:
找到最大的系数 \(a_i\),如果其大于 \(0\),我们找到所有对其限制最大的编号最小的一个基变量,将这两个变量进行一次交换,然后重复这个过程。

实现代码如下:

namespace XG{
    double a[50][50],tr;
    int n,m,ind[50];
    void turn(int x,int y)
    {
        for(int i=0;i<=n;i++)
            if(i!=x)
            {
                tr=a[i][y]/a[x][y];
                for(int j=1;j<=m;j++)
                    a[i][j]-=a[x][j]*tr;
            }
        tr=a[x][ind[x]=y];
        for(int i=1;i<=m;i++)
            a[x][i]/=tr;
    }
    double solve()
    {
        while(1)
        {
            double maxn=0,lim=1e18;
            int x=0,y=0;
            for(int i=1;i<=m;i++)
                if(a[0][i]>maxn)
                    x=i,maxn=a[0][i];
            if(!x) break;
            for(int i=1;i<=n;i++)
                if(a[i][x]>0&&lim>a[i][m]/a[i][x])
                    lim=a[i][m]/a[i][x],y=i;
            if(!y) break;
            turn(y,x);
        }
        return -a[0][m];
    }
}

标签:begin,frac,线性规划,单纯形,算法,end,cases,&+,&-
From: https://www.cnblogs.com/Xun-Xiaoyao/p/17627227.html

相关文章

  • k\log_k N 极小值|k 分算法是 k 越大越好吗?
    引入我们有二分算法,就是:定义二分查找(英语:binarysearch),也称折半搜索(英语:half-intervalsearch)、对数搜索(英语:logarithmicsearch),是用来在一个有序数组中查找某一元素的算法。过程以在一个升序数组中查找一个数为例。它每次考察数组当前部分的中间元素,如果中间元素刚好是要......
  • 【web_逆向04】MD5摘要算法
    MD5是一个非常常见的摘要(hash)算法,其特点就是小巧.速度快.极难被破解。所以,md5依然是国内非常多的互联网公司选择的密码摘要算法这玩意不可逆.所以.摘要算法就不是一个加密逻辑.相同的内容计算出来的摘要应该是一样的不同的内容(哪怕是一丢丢丢丢丢不一样)......
  • 数据结构与算法 --- 组数、链表、栈和队列(一)
    数组、链表、栈和队列是四种基础数据结构,他们是高级、复杂的数据结构和算法的基础。本篇先来讲述数组,链表,及算法的优化策略。数组定义数组:数组是一种线性表数据结构,它用一组连续的内存空间存储一组具有相同类型的数据。定义中有三个关键词:线性表连续的内存空间相同类型数......
  • 数据结构与算法 --- “哨兵”思想
    引言哨兵思想是指在算法中使用一个特殊值来检测或标记某些条件的发生,它的目的是为了简化代码,并使其更容易理解,常常用于在循环中优化边界条件的判断。介绍在算法中,"哨兵"思想是指在循环中设置一个特殊的元素(称为哨兵),以便在循环过程中能够更高效地处理某些边界情况或结束条件。......
  • 数据结构与算法 --- 组数、链表、栈和队列(二)
    继数据结构与算法---组数、链表、栈和队列(一)讲解完数组,链表及算法的优化策略之后,接下来继续讲解两种特殊的线性表结构,栈和队列。栈对“栈”有一个很形象的比喻,栈就像一摞叠在一起的盘子,放盘子时,只能放在上面,不能将盘子插入到中间的任意位置;取盘子时,只能从最上面取,不能从中间任......
  • 数据结构与算法 --- 排序算法(一)
    引言按照时间复杂度,将一些常见排序算法进行分类,分为以下三类:\(O(n^2)\):冒泡排序,插入排序,选择排序。\(O(nlogn)\):快速排序,归并排序。\(O(n)\):桶排序,计数排序,基数排序。本篇文章讨论以下第一类:冒泡排序,插入排序,选择排序。上一篇数据结构与算法---如何分析排序算法提......
  • 数据结构与算法 --- 递归(二)
    引言上文数据结构与算法---递归(一)讲述了什么是递归算法,如何编写递归算法及如何写好递归算法,本文着重讲述一下如何避免递归过深导致的堆栈溢出问题。探究产生堆栈溢出的原因函数调用采用函数调用栈来保存当前“快照”(局部变量,返回地址等)。函数调用栈是内存中开辟的一块存储空......
  • 数据结构与算法 --- 递归(一)
    什么是递归?递归(Recursion)是一种解决问题的方法,它将问题分解为更小的子问题,并逐层解决这些子问题。递归算法的核心思想是:一个函数可以直接或间接地调用自身。通过这种自我调用,我们可以用简洁的代码来解决复杂问题。满足递归的条件一般来说,满足下面三个条件就可以使用递归:待......
  • 数据结构与算法 --- 排序算法(二)
    title:数据结构与算法---排序算法(二)category:数据结构与算法tags:算法updatedAt:2023-05-18T15:29:17.847ZcreatedAt:2023-05-13T14:43:31.656Z引言上一篇数据结构与算法---排序算法(一)中,学习了冒泡排序,插入排序,选择排序这三种时间复杂度为\(O(n^2)\)的算法。实......
  • C语言中的排序算法及其实现方法
    C语言中的排序算法及其实现方法排序算法是计算机科学中的重要部分,它们在数据处理和算法设计中起着关键作用。在C语言编程开发中,掌握不同的排序算法及其实现方法对于提高代码质量和性能至关重要。本文将围绕C语言中的排序算法展开讨论,介绍几种常见的排序算法及其实现方法。1C语言中......