Python解决两阶段法规划问题

前言

在做运筹学作业的过程中,我被复杂的数学逻辑困扰。于是有了做一个程序帮助我写作业的想法。
亮点:借助了前人的成果,改进的地方在于展示了每一步迭代的详细过程,输出美观的表格,贴近实际解题。改进了输入的逻辑,傻瓜式操作,仅需按提示输入条件。觉得有帮助可以点个赞。

代码

import numpy as np
import time

class Simplex(object):
    def __init__(self, c, A_ub=None, b_ub=None, A_eq=None, b_eq=None):
        self.c = c  # 系数矩阵
        self.A_ub = A_ub if A_ub is not None else np.array([])
        self.b_ub = b_ub if b_ub is not None else np.array([])
        self.A_eq = A_eq if A_eq is not None else np.array([])
        self.b_eq = b_eq if b_eq is not None else np.array([])
        self.N_x = 0  # 变量个数
        self.meq = 0  # 等式约束个数
        self.mub = 0  # 不等式约束个数
        self.m = 0  # 约束总数
        self.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]
        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
        np.fill_diagonal(self.T[:self.m, self.N_x:self.N_x + self.m], 1)
        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]
        self.sign = list(range(self.N_x, self.N_x + self.m))

    def solve(self):
        num = 0
        flag = True
        while flag:
            print(f"\n第 {num} 次迭代的单纯形表:")
            self.print_table()
            if max(list(self.T[-1][:-1])) <= 0:
                flag = False
            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 = 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):
        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()
        print("初始单纯形表:")
        self.print_table()
        if self.meq > 0:
            print("第一阶段")
            self.solve()
            self.change()
            print("第二阶段")
            self.solve()
        else:
            print("单阶段")
            self.change()
            self.solve()
        if self.F == 1:
            print("最优解:")
            j = 0
            for i in range(0, self.N_x):
                if i not in self.sign:
                    print(f"x{i + 1} = 0")
                else:
                    print(f"x{i + 1} = {self.T[j][-1]}")
                    j += 1
            print("最优值:\n", self.T[-1][-1])
        else:
            print("出现无界解")

    def print_table(self):
        header = ["变量"] + [f"x{i+1}" for i in range(self.N_x + self.m)] + ["常数"]
        rows = []
        for i, row in enumerate(self.T):
            if i < self.m:
                rows.append([f"x{self.sign[i]+1}"] + list(np.round(row, 2)))
            else:
                rows.append(["Z"] + list(np.round(row, 2)))
        print("\t".join(header))
        for row in rows:
            print("\t".join(map(str, row)))

def user_input():
    print("请输入目标函数的系数 (例如:6x1 + 3x2 + 4x3,输入 6, 3, 4):")
    c = list(map(float, input().strip().split(',')))

    print("请输入等式约束条件 (例如:x1 + x2 + x3 = 120,输入 1, 1, 1 = 120):")
    A_eq = []
    b_eq = []
    while True:
        constraint = input("等式约束 (输入 'done' 完成输入):")
        if constraint.lower() == 'done':
            break
        lhs, rhs = constraint.split('=')
        A_eq.append(list(map(float, lhs.strip().split(','))))
        b_eq.append(float(rhs.strip()))

    print("请输入不等式约束条件 (例如:x1 >= 30 转换为 -1x1 <= -30,输入 -1, 0, 0 <= -30):")
    A_ub = []
    b_ub = []
    while True:
        constraint = input("不等式约束 (输入 'done' 完成输入):")
        if constraint.lower() == 'done':
            break
        lhs, rhs = constraint.split('<=')
        A_ub.append(list(map(float, lhs.strip().split(','))))
        b_ub.append(float(rhs.strip()))

    return np.array(c), np.array(A_ub), np.array(b_ub), np.array(A_eq), np.array(b_eq)

if __name__ == '__main__':
    c, A_ub, b_ub, A_eq, b_eq = user_input()

    time_start = time.perf_counter()
    problem = Simplex(c, A_ub, b_ub, A_eq, b_eq)
    problem.Main()
    time_end = time.perf_counter()
    print('运行时间: %.2f 秒' % (time_end - time_start))

 

 

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

月白v

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值