表格法求解线性规划问题代码实现

表格法求解线性规划问题代码实现


最近组合优化课程布置的课程作业,记录一下,也方便有需要的同学。 如果是要交作业的亲们,改下代码逻辑哈,加点没用的循环之类的,怕查重😅

代码实现

import numpy as np

# 获取目标函数 y = 2x1 + 3x2 即输入 2 3
def gettarget(column):
    y = []
    print("请输入目标函数:")
    for i in range(0, column):
        para = int(input())
        y = y + [para]
    return y

# 判断y系数是否全小于0
def belowzero(y):
    flag = 0
    for i in range(0, len(y)):
        if y[i] < 0 :
            flag = 1
            break
    return flag


if __name__ == '__main__':
    # 获取约束条件:
    # 例如:2x1 + x3 <= 4
    # 则依次输入 2 0(x2的系数) 1 4
    print("请输入问题相关信息:")
    print("请输入变量个数:")
    column = int(input())   # 原变量个数(不算松弛变量)即为列数
    print("请输入约束条件个数:")
    row = int(input())    # 约束条件数即为行数,也为即将添加的松弛变量个数
    # 系数矩阵初始化
    matrix = np.ones((row, column + 1))
    print("请输入约束条件(系数为零的变量也需要输入):")
    for r in range(0, row):
        for c in range(0, column+1):
            print("请输入第{.d}个约束条件中第{.d}个变量的系数")
            matrix[r,c] = int(input())
    
    y = gettarget(column)
    print("y: ")
    print(y)
    print("s.t.: ")
    print(matrix)
    print("\n")
    
    for i in range(0, len(y)):
        y[i] = -y[i] # 目标函数系数取反

    # 换个变量名方便阅读= =
    stnum = row
    vanum = column
    
    # new[]矩阵为解决问题的变换矩阵
    # 第0行: 非松弛变量角标,第0列:松弛变量角标
    # 最后一行:目标函数系数,最后一列:约束条件系数以及目标函数极值 
    newrow = stnum
    newcolumn = vanum
    newvanum = vanum + stnum
    new = np.zeros((newrow+2, newcolumn+2))
    for i in range(1, vanum+1):
        new[0][i] = i
    for i in range(1, stnum+1):
        new[i][0] = i + vanum
    for i in range(1, vanum+2):
        for j in range(1, stnum+1):
            new[i][j] = st[i-1][j-1]
        new[i][0] = i + vanum

    print("表格:")
    print(new)

    # solve
    target = 0 # 目标函数值
    time = 1 # 循环次数
    while(belowzero(y)):
        print("第"+str(time)+"轮迭代:")
        if time > vanum+stnum:
            break
        
        # 寻找关键元素
        minratio = new[1][vanum+1]/new[1][1]
        newretio = -1.0
        position = [1, 1] # 关键元素的位置
        for i in range(1, stnum+1):
            for j in range(1, vanum+1):
                newretio = new[i][vanum+1]/new[i][j]
                if newretio>0:
                    if minratio<0:
                        minratio = newretio
                    if newretio<=minratio:
                        minratio = newretio
                        position[0] = i
                        position[1] = j
                        
        # 关键元素
        key = new[position[0], position[1]]
        print("key"+str(key))
        
        # 用remain记录原new,再对new进行操作
        remain = new.copy()
        
        # 关键元素取倒 
        new[position[0], position[1]] = 1 / key
        # 关键元素所在行变化
        for i in range(1, vanum+2):
            if i!= position[1]:
                new[position[0], i] = remain[position[0], i] / key
        # 关键元素所在列变化
        for i in range(1, stnum+2):
            if i != position[0]:
                new[i, position[1]] = -1 * (remain[i, position[1]] / key)
        # 非最后一列的其他位置变化
        for i in range(1, stnum+2):
            for j in range(1, vanum+1):
                if((i!=position[0])&(j!=position[1])):
                    new[i][j] = remain[i][j] - (remain[i, position[1]] * remain[position[0], j] / key)
        # 最后一列变化
        for i in range(1, stnum+2):
            if i != position[0]:
                new[i][vanum+1] = new[i][vanum+1] - (remain[i, position[1]] * remain[position[0], vanum+1]/ key)
        # 交换该次松弛变量与非松弛变量
        xnum = remain[0, position[1]]
        new[0, position[1]] = new[position[0], 0]
        new[position[0], 0] = xnum
        # 记录当前目标函数
        for i in range(0, len(y)):
            y[i] = new[stnum+1, i+1]
            target = new[stnum+1][vanum+1]
        print("new: ")
        print(new)
        print("\n")
        time = time + 1
        
    # 打印最终target值
    print(target)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值