Python线性规划-两阶段法

Python线性规划-两阶段法

等式约束不等式约束都可以,不等式约束默认最小化,最大化转化成最小化就行,话不多说,直接上代码

import numpy as np
import time
class Simplex(object):
    def __init__(self,c,A_ub,b_ub,A_eq, b_eq):  #初始化函数
        self.c=c            #系数矩阵
        self.A_ub=A_ub      #不等式约束矩阵
        self.b_ub=b_ub      #不等式约束边界
        self.A_eq=A_eq      #等式约束矩阵
        self.b_eq=b_eq      #等式约束边界
        self.N_x=0          #变量个数
        self.meq=0          #等式约束个数
        self.mub = 0        #不等式约束个数
        self.m=0            #约束的总数
        self.T=[]           #将所有数据放入单纯形表T
        self.sign=[]        #记录基变量序号
        self.F=1            #判断迭代进行的情况:
                            # 1——继续迭代
                            # 0——无界解,停止迭代
    def Initial_value(self):
        self.N_x=len(self.c)
        # 按照约束类型求解
        if self.b_eq.any():  # 判断等式约束的有无
            self.meq = len(self.b_eq)
        if self.b_ub.any():  # 判断不等式约束的有无
            self.mub = len(self.b_ub)
        self.m = self.mub + self.meq  # 所有约束的行数
        # 建立第一阶段单纯型表。
        self.T = np.zeros([self.m + 1, self.N_x + self.m + 1], dtype='float')
        b = self.T[:-1, -1]
        # 判断两种约束的有无,
        # T矩阵上半部分为等式约束,下半部分为不等式约束
        if self.meq > 0:
            self.T[:self.meq, :self.N_x] = self.A_eq
            b[:self.meq] = self.b_eq
        if self.mub > 0:
            self.T[self.meq:self.m, :self.N_x] = self.A_ub
            b[self.meq:self.m] = self.b_ub
        #人工变量与松弛变量系数设为1
        np.fill_diagonal(self.T[:self.m, self.N_x:self.N_x + self.m], 1)
        # T矩阵最后一行表示(-c)
        # 第一阶段
        self.T[-1, self.N_x:self.N_x + self.meq] = -1 * np.ones(self.meq)
        for i in range(0, self.meq):
            self.T[-1] += self.T[i]
        l = [i for i in range(self.N_x, self.N_x + self.m)]  # 记录基变量列标,也可自行输入列标
        self.sign = list(l)
    def solve(self):  # 判断是否到达最优解
        num = 0
        flag = True
        while flag:
            # 直至所有非基变量检验数小于等于0
            # 合并多个解的情况,即使非基变量检验数等于0也停止迭代
            if max(list(self.T[-1][:-1])) <= 0:
                flag = False
            # 迭代,直至某个非基变量检验数等于0
            else:
                num += 1
                self.F=self.calculate()
            # 判断无界解,防止无限迭代
            if self.F==0:
                break
    # 进行迭代运算
    def calculate(self):
        H = list(self.T[-1, :-1])
        j_num = H.index(max(H))
        D = []
        for i in range(0, self.m):
            if self.T[i][j_num] == 0:
                D.append(float("inf"))
            else:
                D.append(self.T[i][-1] / self.T[i][j_num])
        if max(D) <= 0:# 判断无界解
            return 0
        # 找出最小比值所在行、列—i_num,j_num
        i_num = D.index(min([x for x in D if x >= 0]))
        self.sign[i_num] = j_num
        t = self.T[i_num][j_num]
        #换基迭代
        self.T[i_num] /= t
        for i in [x for x in range(0, self.m + 1) if x != i_num]:
            self.T[i] -= self.T[i_num] * self.T[i][j_num]
        return 1

    def change(self):#人工变量所在列变为0,替换上第二阶段的c
        self.T[:, self.N_x:self.N_x + self.meq] = 0
        self.T[-1, 0:self.N_x] = -self.c
        for i in range(0, self.m):
            self.T[-1] -= self.T[i] * self.T[-1][int(self.sign[i])]

    def Main(self):#主函数
        self.Initial_value()
        if self.meq > 0:  # 采用两阶段法
            # 第一阶段求解
            print("phase 1")
            self.solve()
            # 消去人工变量列
            self.change()
            #第二阶段求解
            print("phase 2")
            self.solve()
        else:
            # 直接进入第二阶段求解,消去人工变量列
            print("simple")
            self.change()
            self.solve()
        if self.F==1:
            print("Optimal solution:")
            j = 0
            for i in range(0, self.N_x):
                if i not in self.sign:
                    print("x" + str(i + 1) + "=0")
                else:
                    print("x" + str(i+1) + "=", self.T[j][-1])
                    j+=1
            print("Best Value:\n", self.T[-1][-1])
        else:
            print("出现无界解")

if __name__ == '__main__':
    '''
    Min Z=0.4*x1+0.5*x2+0*x3     # Min Z =CX
    st. 0.5*x1+0.5*x2=6             #A_ub*x1<=b_ub
        0.6*x1+0.4*x2-x3=6
        0.3*x1+0.1*x2<=2.7          #A_ub*x1<=b_ub
    '''

    c = np.array([0.4,0.5,0])
    # 不等式约束<=
    A_ub = np.array([[0.3,0.1,0]])
    b_ub = np.array([2.7])
    # 等式约束
    A_eq = np.array([[0.5,0.5,0],
                         [0.6,0.4,-1]])
    b_eq = np.array([6,6])
    '''
    x=4000                                        
    y=5*x                                        
    c = np.random.randint(-10, 10, (y))          
    # 不等式约束<=
    A_ub = np.array([])
    b_ub = np.array([])
    # 等式约束
    A_eq = np.random.randint(0, 20, (x, y))
    b_eq = np.random.randint(0, 50, (x))
    '''
    # 输出小数位数
    time.perf_counter()
    digit = 2
    Problem=Simplex(c, A_ub, b_ub, A_eq, b_eq)
    Problem.Main()
    print('Running time: %s Seconds', time.perf_counter())
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值