相关文章推荐
曾经爱过的松树  ·  哪吒(1994年四川人民出版社出版的图书)_ ...·  7 月前    · 
豁达的小摩托  ·  深圳坪山今年新开办学校5所,提供公办学位10 ...·  9 月前    · 
稳重的煎饼果子  ·  六款游戏玩透世界文明史_百科TA说·  1 年前    · 
年轻有为的毛衣  ·  日常炮弹被吞【战争雷霆吧】_百度贴吧·  2 年前    · 
逆袭的围巾  ·  Snapseed ...·  2 年前    · 
Code  ›  最优解问题——PuLP解决线性规划问题(一)_pulp求解_悟乙己的博客
线性规划 目标函数
https://blog.csdn.net/sinat_26917383/article/details/116274144
坚强的玉米
3 年前
  • 1 PuLP介绍
    • 1.1 理论、流程介绍
    • 1.2 主函数介绍
      • 1.2.1 LpProblem类
      • 1.2.2 LpVariable类
      • 1.2.3 lpSum(vector)
    • 1.3 一些函数写法优化
      • 1.3.1 赋值
      • 1.3.2 PuLP里面不可使用的
    • 案例一:优化投放广告渠道的资源
    • 案例二:如何分配水库供水量,公司才能获利最多
    • 案例三: 求解最普通的线性规划问题
    • 案例四:运输问题
    • 案例五:指派问题

    1 PuLP介绍

    参考: 用Python的pulp解决线性规划问题

    1.1 理论、流程介绍

    线性规划是研究线性约束条件下线性目标函数的极值问题的数学理论和方法。Python中有许多第三方的工具可以解决这类问题,这里介绍常用的pulp工具包。pulp能够解包括整数规划在内的绝大多数线性规划问题,并且提供了多种solver,每种solver针对不同类型的线性规划问题有更好的效果。
    关于pulp工具包的详细介绍,请参见pulp官网。

    pip install pulp
    

    我们解决线性规划问题一般是通过以下三个步骤。

    • 1.列出约束条件及目标函数
    • 2.画出约束条件所表示的可行域
    • 3.在可行域内求目标函数的最优解及最优值

    1.2 主函数介绍

    1.2.1 LpProblem类

    LpProblem(name='NoName', sense=LpMinimize)
    构造函数,用来构造一个LP问题实例,其中name指定问题名(输出信息用),
    sense值是LpMinimize或LpMaximize中的一个,用来指定目标函数是求极大值还是极小值。

    solve(solver=None, **kwargs)
    在对LpProblem添加完约束条件后,调用该函数进行求解,如果不是求解特定的整数规划问题,solver一般使用默认即可。

    1.2.2 LpVariable类

    LpVariable(name, lowBound=None, upBound=None, cat='Continuous', e=None)
    构造函数,用来构造LP问题中的变量,name指定变量名,lowBound和upBound是下界和上界,
    默认分别是负无穷到正无穷,cat用来指定变量是离散(Integer,Binary)还是连续(Continuous)。
    取值包括:

    • LpInteger - 整数型
    • LpContinuous - 连续性

    dicts(name, indexs, lowBound=None, upBound=None, cat='Continuous', indexStart=[])
    用来构造变量字典,可以让我们不用一个个地创建Lp变量实例。name指定所有变量的前缀,
    index是列表,其中的元素会被用来构成变量名,后面三个参数和LbVariable中的一样。

    1.2.3 lpSum(vector)

    计算一个序列的值,使用lpSum求解比普通的sum函数要快得多。

    1.3 一些函数写法优化

    1.3.1 赋值

    变量定义,注意最后的LpInteger,当设置该参数时,则该决策变量只能取整数
    如果决策变量可以取小数,那就设置为LpContinuous

    x1 = LpVariable('日间电视',0,14,LpInteger)
    x2 = LpVariable('夜间电视',0,8,LpInteger)
    x3 = LpVariable('网络媒体',0,40,LpInteger)
    x4 = LpVariable('平面媒体',0,5,LpInteger)
    x5 = LpVariable('户外广告',0,50,LpInteger)
    
    Ingredients = ['日间电视','夜间电视','网络媒体','平面媒体','户外广告']
    ingredient_vars = LpVariable.dicts("Ingr",Ingredients,0)
    

    1.3.2 PuLP里面不可使用的

    不可以使用:
    x1/x2
    1/x1
    x2/3

    案例一:优化投放广告渠道的资源

    来看一个案例:如何用Python解决最优化问题?

    现有5个广告投放渠道,分别是日间电视、夜间电视、网络媒体、平面媒体、户外广告,每个渠道的效果、费用及限制如下表所示:

    在这里插入图片描述
    注:案例来自《活用数据:驱动业务的数据分析实战》,作者陈哲

    比如日间电视这个渠道,每做一次投放需要费用1000元,可以触达2000个用户(曝光量),带来咨询量600个(也可以看做app下载量等目标产出),该广告渠道最多投放14次。

    除了表格中的限制条件外,还要求:

    电视广告至少投放20次(包括日间和夜间);
    触达用户数(曝光量)不少于10万;
    电视广告投入费用不超过3万元;
    现在公司总共给到4万的营销费用,要求咨询量能最大化。

    这是一个线性规划问题,即在有限的资源(约束条件)下如何使效用(线性目标函数)最大化。
    把5个广告渠道各自能使用的次数作为决策变量,分别用
    在这里插入图片描述

    那么,现在要优化的目标函数是
    在这里插入图片描述

    约束条件:

    电视广告投放至少20次,

    用户曝光量至少10万,
    在这里插入图片描述
    电视广告费用不超过3万,
    在这里插入图片描述

    总广告费用不超过4万,
    在这里插入图片描述

    投放次数为正整数,且

    在这里插入图片描述
    使用PuLP的代码为:

    from pulp import *
    prob = LpProblem('营销优化问题',LpMaximize)
    # 变量定义,注意最后的LpInteger,当设置该参数时,则该决策变量只能取整数
    # 如果决策变量可以取小数,那就设置为LpContinuous
    x1 = LpVariable('日间电视',0,14,LpInteger)
    x2 = LpVariable('夜间电视',0,8,LpInteger)
    x3 = LpVariable('网络媒体',0,40,LpInteger)
    x4 = LpVariable('平面媒体',0,5,LpInteger)
    x5 = LpVariable('户外广告',0,50,LpInteger)
    # 需要优化的表达式
    prob += 600*x1+800*x2+500*x3+400*x4+300*x5
    # 约束条件
    prob += 1000*x1 + 2000*x2 <= 30000, '电视广告费用不超过3万'
    prob += x1+x2 >= 20, '电视广告至少20次'
    prob += 1000*x1+2000*x2+400*x3+1000*x4+100*x5 <= 40000, '广告总费用不超过4万'
    prob += 2000*x1+4000*x2+3000*x3+5000*x4+600*x5 >= 100000,'曝光人数不少于10万'
    #lp文件保存该优化问题的信息,可以用文本编辑器打开
    prob.writeLP("营销优化问题.lp")
    # 执行计算
    prob.solve()
    # 如果成功得到了最优值,则会输出 Optimal
    print(LpStatus[prob.status])
    # 得到最优值时,各决策变量的取值,如果没有找到最优值,则输出None
    for v in prob.variables():
        print(v.name, "=", v.varValue)
    # 输出最优值,如果没有找到最优值,则输出None
    print("最大咨询量为", value(prob.objective))
    

    输出结果:
    在这里插入图片描述
    可以看到最优值为39200,对应的决策变量的取值均为整数。

    PuLP的代码量看着虽然多,但是相对于scipy.optimize.linprog函数,PuLP的代码非常灵活,而且很直观,对参数取值是整数或者小数还有细分。

    案例二:如何分配水库供水量,公司才能获利最多

    python 之pulp 线性规划介绍及举例

    供水公司有三个水库分别为A,B,C向四个小区甲乙丙丁供水,A和B向所有小区供水,C仅向甲乙丙供水,水库最大供水量(千吨)
    在这里插入图片描述
    小区用水情况为
    在这里插入图片描述
    水库供水收入900元/千吨,支出费用为:其他费用450/千吨,引水管理费:
    在这里插入图片描述
    问 如何分配水库供水量,公司才能获利最多。
    目标函数为:

    z = 160.0*x11 + 130.0*x12 + 220.0*x13 + 170.0*x14 + 140.0*x21 + 130.0*x22 + 190.0*x23 + 150.0*x24 + 190.0*x31 + 200.0*x32 + 230.0*x33
    

    求的值,使Z最小。

    # coding=utf-8
    from pulp import *
    def get_re():
    def getresult(c, con):
    # 设置对象
        prob = LpProblem('myPro', LpMinimize)
    # 设置三个变量,并设置变量最小取值
        x11 = LpVariable("x11", lowBound=0)
        x12 = LpVariable("x12", lowBound=0)
        x13 = LpVariable("x13", lowBound=0)
        x14 = LpVariable("x14", lowBound=0)
        x21 = LpVariable("x21", lowBound=0)
        x22 = LpVariable("x22", lowBound=0)
        x23 = LpVariable("x23", lowBound=0)
        x24 = LpVariable("x24", lowBound=0)
        x31 = LpVariable("x31", lowBound=0)
        x32 = LpVariable("x32", lowBound=0)
        x33 = LpVariable("x33", lowBound=0)
        X = [x11, x12, x13, x14, x21, x22, x23, x24, x31, x32, x33]
        #c = [160, 130, 220, 170, 140, 130, 190, 150, 190, 200, 230]
        prob += x11+x12+x13+x14 == con[0]# 约束条件1
        prob += x21+x22+x23+x24 == con[1]
        prob += x31+x32+x33 == con[2]
        prob += x11+x21+x31 <= con[3]
        prob += x11+x21+x31 >= con[4]
        prob += x12 + x22 + x32 <= con[5]
        prob += x12 + x22 + x32 >= con[6]
        prob += x13 + x23 + x33 <= con[7]
        prob += x13 + x23 + x33 >= con[8]
        prob += x14 + x24 <= con[9]
        prob += x14 + x24 >= con[10]
        status = prob.solve()
        print(status)
        print(LpStatus[status])
        print(value(prob.objective))  # 计算结果
    # 显示结果
    #     for i in prob.variables():
    #         print(i.name + "=" + str(i.varValue))
        for i in prob.variables():
            print(i.varValue)
    if __name__ == '__main__':
        c = [160, 130, 220, 170, 140, 130, 190, 150, 190, 200, 230]
        con = [50, 60, 50, 80, 30, 140, 70, 30,10, 50, 10]
        getresult(mubiao, yueshu)
    

    输出结果:

    Optimal24400.00.050.00.00.00.050.00.010.040.00.010.0
    

    案例三: 求解最普通的线性规划问题

    【数学建模】线性规划各种问题的Python调包方法
    求解最普通的线性规划问题:在这里插入图片描述

    import pulp
    #目标函数的系数
    z = [2, 3, 1]
    a = [[1, 4, 2], [3, 2, 0]]
    b = [8, 6]
    #确定最大化最小化问题,最大化只要把Min改成Max即可
    m = pulp.LpProblem(sense=pulp.LpMinimize)
    #定义三个变量放到列表中
    x = [pulp.LpVariable(f'x{i}', lowBound=0) for i in [1,2,3]]
    #定义目标函数,lpDot可以将两个列表的对应位相乘再加和
    #相当于z[0]*x[0]+z[1]*x[0]+z[2]*x[2]
    m += pulp.lpDot(z, x)
    #设置约束条件
    for i in range(len(a)):
        m += (pulp.lpDot(a[i], x) >= b[i])
    m.solve()
    #输出结果
    print(f'优化结果:{pulp.value(m.objective)}')
    print(f'参数取值:{[pulp.value(var) for var in x]}')
    #output:
    #优化结果:7.0
    #参数取值:[2.0, 0.0, 3.0]
    

    每一步的说明已经注释在代码中,可以看到输出结果,两者的变量取值并不一致,但代入目标函数的结果都是一样的。
      同样的,如果存在类似x_1+2x_2+4x_3=101这种情况,可以:

    A_eq = [1,2,4]
    b_eq = 101
    m += (pulp.lpDot(A_eq, x) == b_eq)
    

    案例四:运输问题

    【数学建模】线性规划各种问题的Python调包方法
    在这里插入图片描述

    import pulp
    import numpy as np
    from pprint import pprint
    def transportation_problem(costs, x_max, y_max):
        row = len(costs)
        col = len(costs[0])
        prob = pulp.LpProblem('Transportation Problem', sense=pulp.LpMaximize)
        var = [[pulp.LpVariable(f'x{i}{j}', lowBound=0, cat=pulp.LpInteger) for j in range(col)] for i in range(row)]
        flatten = lambda x: [y for l in x for y in flatten(l)] if type(x) is list else [x]
        prob += pulp.lpDot(flatten(var), costs.flatten())
        for i in range(row):
            prob += (pulp.lpSum(var[i]) <= x_max[i])
        for j in range(col):
            prob += (pulp.lpSum([var[i][j] for i in range(row)]) <= y_max[j])
        prob.solve()
        return {'objective':pulp.value(prob.objective), 'var': [[pulp.value(var[i][j]) for j in range(col)] for i in range(row)]}
    

    然后构造参数传递进去:

    if __name__ == '__main__':
        costs = np.array([[500, 550, 630, 1000, 800, 700],
                           [800, 700, 600, 950, 900, 930],
                           [1000, 960, 840, 650, 600, 700],
                           [1200, 1040, 980, 860, 880, 780]])
        max_plant = [76, 88, 96, 40]
        max_cultivation = [42, 56, 44, 39, 60, 59]
        res = transportation_problem(costs, max_plant, max_cultivation)
        print(f'最大值为{res["objective"]}')
        print('各变量的取值为:')
        pprint(res['var'])
    #output:
    #最大值为284230.0
    #各变量的取值为:
    #[[0.0, 0.0, 6.0, 39.0, 31.0, 0.0],
    # [0.0, 0.0, 0.0, 0.0, 29.0, 59.0],
    # [2.0, 56.0, 38.0, 0.0, 0.0, 0.0],
    # [40.0, 0.0, 0.0, 0.0, 0.0, 0.0]]
    

    案例五:指派问题

    【数学建模】线性规划各种问题的Python调包方法
    在这里插入图片描述
    先定义通用解决方法,其中的flatten是递归展开列表用的。

    def assignment_problem(efficiency_matrix):
        row = len(efficiency_matrix)
        col = len(efficiency_matrix[0])
        flatten = lambda x: [y for l in x for y in flatten(l)] if type(x) is list else [x]
        m = pulp.LpProblem('assignment', sense=pulp.LpMinimize)
        var_x = [[pulp.LpVariable(f'x{i}{j}', cat=pulp.LpBinary) for j in range(col)] for i in range(row)]
        m += pulp.lpDot(efficiency_matrix.flatten(), flatten(var_x))
        for i in range(row):
            m += (pulp.lpDot(var_x[i], [1]*col) == 1)
        for j in range(col):
            m += (pulp.lpDot([var_x[i][j] for i in range(row)], [1]*row) == 1)
        m.solve()
        print(m)
        return {'objective':pulp.value(m.objective), 'var': [[pulp.value(var_x[i][j]) for j in range(col)] for i in range(row)]}
    

    输出结果:

    efficiency_matrix = np.array([
        [12, 7, 9, 7, 9],
        [8, 9, 6, 6, 6],
        [7, 17, 12, 14, 9],
        [15, 14, 6, 6, 10],
        [4, 10, 7, 10, 9]
    res = assignment_problem(efficiency_matrix)
    print(f'最小值{res["objective"]}')
    print(res['var'])
    #output
    #最小值32.0
    #[[0.0, 1.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 0.0, 1.0], [0.0, 0.0, 1.0, 0.0, 0.0], [1.0, 0.0, 0.0, 0.0, 0.0]]
                        文章目录1 PuLP介绍1.1 理论、流程介绍1.2 主函数介绍1.2.1 LpProblem类1.2.2  LpVariable类1.2.3  lpSum(vector)1.3 一些函数写法优化1.3.1 赋值1.3.2 PuLP里面不可使用的案例一:优化投放广告渠道的资源案例二:如何分配水库供水量,公司才能获利最多案例三: 求解最普通的线性规划问题案例四:运输问题案例五:指派问题1 PuLP介绍1.1 理论、流程介绍线性规划是研究线性约束条件下线性目标函数的极值问题的数学理论和方法。Pytho.
    1、基于字典的创建规划问题
    上篇中介绍了使用 LpVariable 对逐一定义每个决策变量,设定名称、类型和上下界,类似地对约束条件也需要逐一设置模型参数。在大规模的规划问题中,这样逐个定义变量和设置模型参数非常繁琐,效率很低。Pulp 库提供了一种快捷方式,可以结合 Python语言的循环和容器,使用字典来创建问题。
      (1)使用快捷方法建立一个规划问题,可以用字典类型(dict) 建立多个变量,例如:
    name = [‘废料1’, ‘废料2’, 
    混合0-1整数规划不同于普通的线性规划问题,它要求存在决策变量均为整数,且只能取值0或1;同时存在有些决策变量为整数,不限制取值为0或1;有些决策变量不限定为整数。
    一、混合0-1整数规划问题举例
    下图是一个混合0-1整数规划问题,我们通过python的Pulp库来实现该问题的求解。
    二、Pulp构造与求解
    1.例题实现
    from pulp import *
    1、什么是线性规划
    线性规划(Linear programming),在线性等式或不等式约束条件下求解线性目标函数的极值问题,常用于解决资源分配、生产调度和混合问题。例如:
    max		fx = 2*x1 + 3*x2 - 5*x3
    s.t.	x1 + 3*x2 + x3 <= 12
    		2*x1 - 5*x2 + x3 >= 10
    		x1 + x2 + x3 = 7
    		x1, x2, x3 >=0
    线性规划问题的建模和求解,通常
    标签:程序猿|C++选手|学生
    简介:因C语言结识编程,随后转入计算机专业,有幸拿过一些国奖、省奖…已保研。目前正在学习C++/Linux/Python
    学习经验:扎实基础 + 多做笔记 + 多敲代码 + 多思考 + 学好英语!
    初学Python 小白阶段
    文章仅作为自己的学习笔记 用于知识体系建立以及复习
    题不在多 学一题 懂一题
    知其然 知其所以然!
    某厂生产甲乙两种饮料,每百箱甲饮料需用原料6千克、工人10名,获利10万元;每百箱乙饮料需用原料5千克、工人20名,获利9万元。
    今工厂共有原料60千克、工人150名,又由于其他条件所限甲饮料产量不超过8百箱。
     (1)问如何安排生产计划,即两种饮料各生产多少使获利最大?
     (2)若投资0.8万元可增加原料1千克,是否应作这项投资?投资多少合理?
     (3)若每百箱甲饮料获利可增加1万元,是否应否改变生产计划?
    				
    Python 实例介绍固定费用问题的建模与求解。 学习 PuLP工具包中处理复杂问题的快捷使用方式。 『Python小白的数学建模课 @ Youcans』带你从数模小白成为国赛达人。 前文讲到几种典型的 0-1 规划问题,给出了 PuLP 求解的案例。由于 0-1 规划问题种类很多,又是数模竞赛热点,有必要再结合几个实例进行介绍。 1. 固定费用问题案例解析 1.1 固定费用问题(Fixed cost problem) 固定费用问题,是指求解生产成本最小问题时,总成本包括固定成本和变动成本,而选择不同.
    问题描述 上图所示的Whiskas猫粮由Ben生产。Ben希望尽可能便宜地生产其猫粮,同时确保它们满足罐头上所示的规定的营养分析要求。因此,他们希望改变每种成分的使用量(主要成分是鸡肉,牛肉,羊肉,大米,小麦和凝胶),同时仍要满足其营养标准。 鸡肉,牛肉和羊肉的成本分别为0.013美元,0.008美元和0.010美元,而大米,小麦和凝胶的成本分别为0.002美元,0.005美元和0.001美元。(所有成本均为每克。)在此练习中,我们将忽略维生素和矿物质成分。(无论如何,这些的任何费用都可能很小。)
 
推荐文章
曾经爱过的松树  ·  哪吒(1994年四川人民出版社出版的图书)_百度百科
7 月前
豁达的小摩托  ·  深圳坪山今年新开办学校5所,提供公办学位10830个_深圳24小时_深新闻_奥一网
9 月前
稳重的煎饼果子  ·  六款游戏玩透世界文明史_百科TA说
1 年前
年轻有为的毛衣  ·  日常炮弹被吞【战争雷霆吧】_百度贴吧
2 年前
逆袭的围巾  ·  Snapseed 使用攻略:你想要的,都能做到 - 掘金
2 年前
今天看啥   ·   Py中国   ·   codingpro   ·   小百科   ·   link之家   ·   卧龙AI搜索
删除内容请联系邮箱 2879853325@qq.com
Code - 代码工具平台
© 2024 ~ 沪ICP备11025650号