• MindOpt有关于Python的建模与优化



    前言

    周四,天气渐渐凉快了下来。

    一、安装

    优化求解器之手把手教你申请试用与运行MindOpt求解器.

    个人建议:先使用在线版的看一下效果,毕竟本机装环境超麻烦的好吗。
    MindOpt 优化求解器-线上版.

    二、Python 的建模与优化

    例子:这里我们使用官方案例【LP专题-2】营养调配:如何吃少花钱又营养.

    2-1、MdoModel类

    MdoModel:用以创建优化模型类对象
    类对象所调用的函数介绍

    1、model.add_var(): 向模型引入新变量(列)的函数。参数介绍如下,返回值是创建的变量对象。

    • lb(浮点数) – 新变量的下限值。默认值为 。0.0
    • ub(浮点数) – 新变量的上限值。默认值为 。1.E+20
    • obj(浮点数) – 新变量的目标系数。默认值为 。0.0
    • col (MdoCol) – 保存非零元素的列对象。默认值为 。None
    • name (str) – 用于保存列名的字符串对象。默认值为 。“”
    • is_integer (bint) – 一个布尔标志,指定这是否为整数变量。默认值为 。False

    2、model.add_cons():向模型引入新约束(行)的函数。

    • lhs(浮点型或 MdoTempLinear) – 新约束或临时线性对象的左侧值。下限!
    • rhs(浮点型或 str 型)– 新约束的右侧值,或约束名称的字符串。上限!
    • expr (MdoExprLinear) – 持有新线性约束的表达式。默认值为 。None
    • name (str) – 用于保存列名的字符串对象。默认值为 。“”

    3、 model.solve_prob():

    4、 model.get_infinity(): 用于检索无穷大值的函数,返回无穷大的值,返回类型是浮点数。

    5、 model.set_int_attr(): 用于更改整数值模型属性的值的函数。

    6、 model.set_str_param(): 用于更改字符串值参数的值的函数。

    • par (str) – 要访问的字符串值参数。
    • value (int) – 字符串值参数的新值。

    7、model.submit_task(): 此函数将优化模型任务提交到远程服务器进行优化。模型任务文件以二进制格式包含问题数据、参数设置和解决方案。

    • 返回:一个字符串,指定已提交作业的 ID。用户可以使用此作业 ID 查询优化结果。(str)

    8、model.retrieve_task(): 该函数检查已提交任务的状态,然后检索相应的优化结果(如果可用)。所有可能的状态值为:“Submitted” “Solving” “Canceled” “Finished” “Failed”

    • 参数:
    • job_id (str) – 指定已提交作业的 ID 的字符串。
    • 返回值(四个值):
    • 已提交任务的状态(str)
    • 模型状态(int)
    • 相应代码,优化状态(int)
    • 标志,指定方案的可用性(bool)

    9、model.explain_result():此函数解释求解器结果代码的详细信息。

    • 参数:
    • 优化状态,model.retrieve_task()得到的返回值。(第三个)
    • 返回:
    • 一个字符串,保存给定求解器状态代码的详细信息。

    10、model.explain_status(): 此函数解释求解器状态代码的详细信息。

    • 参数:
    • 模型状态,model.retrieve_task()得到的返回值。(第二个)
    • 返回:
    • 一个字符串,保存给定求解器状态代码的详细信息。

    11、model.display_results(): 显示当前求解器结果的函数。

    12、model.get_status(): 用于检索求解器状态的函数。

    • 返回值:
    • 状态码(int)
    • 状态信息(str)

    13、model.get_real_attr():用于检索实值模型属性的值的函数。

    • 参数
    • 要访问的属性(str)
    • 返回
    • 实值模型属性的当前值。

    2-2、MdoExprLinear类

    MdoExprLinear: 此对象实现数据结构以保存线性约束表达式对象,该对象由一组系数-变量对组成。使用该类的步骤如下:

    1、通过使用 model.add_var() 创建一系列变量对象。
    2、使用MdoExprLinear()类创建一个空的对象。
    3、使用重载运算符(+、-、×、/),或者是使用成员函数MdoExprLinear.add_terms()

    官方例子

    MdoVar x1 = model.add_var()
    MdoVar x3 = model.add_var()
    expr1 = 1 * x1
    expr1 = expr1 + x2
    MdoVar x3 = model.add_var()
    expr2 = expr1 + x3
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2-3、官方案例——营养调配

    """
    /**
     *  example_2_py1.py
     *  Description 
     *  -----------
     *
     *  Linear optimization (diet problem).
     * 
     *  The goal is to select foods that satisfy daily nutritional requirements while minimizing the total cost. 
     *  The constraints in this problem limit the number of calories, the volume of good consumed, and the amount of 
     *  vitamins, protein, carbohydrates, calcium, and iron in the diet.
     *
     *  Note
     *  ----
     * 
     *  The model below will be inputted in a row-wise order.
     *
     *  Formulation
     *  -----------
     *
     * Minimize
     * Obj:        1.840000000 Cheeseburger + 2.190000000 HamSandwich + 1.840000000 Hamburger + 1.440000000 FishSandwich +
     *             2.290000000 ChickenSandwich + 0.770000000 Fries + 1.290000000 SausageBiscuit + 0.600000000 LowfatMilk + 
     *             0.720000000 OrangeJuice
     * Subject To
     * Cal:        510 Cheeseburger + 370 HamSandwich + 500 Hamburger + 370 FishSandwich +
     *             400 ChickenSandwich + 220 Fries + 345 SausageBiscuit + 110 LowfatMilk + 80 OrangeJuice >= 2000
     * Carbo:      34 Cheeseburger + 35 HamSandwich + 42 Hamburger + 38 FishSandwich + 42 ChickenSandwich + 
     *             26 Fries + 27 SausageBiscuit + 12 LowfatMilk + 20 OrangeJuice <= 375
     * Carbo_low:  34 Cheeseburger + 35 HamSandwich + 42 Hamburger + 38 FishSandwich + 42 ChickenSandwich + 
     *             26 Fries + 27 SausageBiscuit + 12 LowfatMilk + 20 OrangeJuice >= 350
     * Protein:    28 Cheeseburger + 24 HamSandwich + 25 Hamburger + 14 FishSandwich + 31 ChickenSandwich + 
     *             3 Fries + 15 SausageBiscuit + 9 LowfatMilk + OrangeJuice >= 55
     * VitA:       15 Cheeseburger + 15 HamSandwich + 6 Hamburger + 2 FishSandwich + 8 ChickenSandwich + 
     *             4 SausageBiscuit + 10 LowfatMilk + 2 OrangeJuice >= 100
     * VitC:       6 Cheeseburger + 10 HamSandwich + 2 Hamburger + 15 ChickenSandwich + 
     *             15 Fries + 4 LowfatMilk + 120 OrangeJuice >= 100
     * Calc:       30 Cheeseburger + 20 HamSandwich + 25 Hamburger + 15 FishSandwich + 
     *             15 ChickenSandwich + 20 SausageBiscuit + 30 LowfatMilk + 2 OrangeJuice >= 100
     * Iron:       20 Cheeseburger + 20 HamSandwich + 20 Hamburger + 10 FishSandwich + 
     *             8 ChickenSandwich + 2 Fries + 15 SausageBiscuit + 2 OrangeJuice >= 100
     * Volume:     4 Cheeseburger + 7.500000000 HamSandwich + 3.500000000 Hamburger + 5 FishSandwich + 
     *             7.300000000 ChickenSandwich + 2.600000000 Fries + 4.100000000 SausageBiscuit + 8 LowfatMilk + 12 OrangeJuice <= 75
     * Bounds
     * End
     */
    """
    from mindoptpy import *
    
    
    if __name__ == "__main__":
    
        MDO_INFINITY = MdoModel.get_infinity()
        token = "**********"
        server = "mindopt.tianchi.aliyun.com"
        desc = "tianchi example2 MdoRemotLdDiet PY1"
        filepath = "./tmp/"
    
        req = \
        {   
            # requirement: ( lower bound,   upper bound)
            "Cal"        : (         2000, MDO_INFINITY), 
            "Carbo"      : (          350,          375),
            "Protein"    : (           55, MDO_INFINITY), 
            "VitA"       : (          100, MDO_INFINITY),
            "VitC"       : (          100, MDO_INFINITY),
            "Calc"       : (          100, MDO_INFINITY), 
            "Iron"       : (          100, MDO_INFINITY), 
            "Volume"     : (-MDO_INFINITY,           75)
        }
    
        food = \
        {
            # food            : ( lower bound,  upper bound, cost)
            "Cheeseburger"    : (           0, MDO_INFINITY, 1.84),
            "HamSandwich"     : (           0, MDO_INFINITY, 2.19),
            "Hamburger"       : (           0, MDO_INFINITY, 1.84),
            "FishSandwich"    : (           0, MDO_INFINITY, 1.44),
            "ChickenSandwich" : (           0, MDO_INFINITY, 2.29),
            "Fries"           : (           0, MDO_INFINITY, 0.77),
            "SausageBiscuit"  : (           0, MDO_INFINITY, 1.29),
            "LowfatMilk"      : (           0, MDO_INFINITY, 0.60),
            "OrangeJuice"     : (           0, MDO_INFINITY, 0.72)
        }
    
        req_value = \
        {  
            # (requirement, food              ) : value
            ( "Cal",        "Cheeseburger"    ) : 510,
            ( "Cal",        "HamSandwich"     ) : 370,
            ( "Cal",        "Hamburger"       ) : 500,
            ( "Cal",        "FishSandwich"    ) : 370,
            ( "Cal",        "ChickenSandwich" ) : 400,
            ( "Cal",        "Fries"           ) : 220,
            ( "Cal",        "SausageBiscuit"  ) : 345,
            ( "Cal",        "LowfatMilk"      ) : 110,
            ( "Cal",        "OrangeJuice"     ) : 80,
    
            ( "Carbo",      "Cheeseburger"    ) : 34,
            ( "Carbo",      "HamSandwich"     ) : 35,
            ( "Carbo",      "Hamburger"       ) : 42,
            ( "Carbo",      "FishSandwich"    ) : 38,
            ( "Carbo",      "ChickenSandwich" ) : 42,
            ( "Carbo",      "Fries"           ) : 26,
            ( "Carbo",      "SausageBiscuit"  ) : 27,
            ( "Carbo",      "LowfatMilk"      ) : 12,
            ( "Carbo",      "OrangeJuice"     ) : 20,
    
            ( "Protein",    "Cheeseburger"    ) : 28,
            ( "Protein",    "HamSandwich"     ) : 24,
            ( "Protein",    "Hamburger"       ) : 25,
            ( "Protein",    "FishSandwich"    ) : 14,
            ( "Protein",    "ChickenSandwich" ) : 31,
            ( "Protein",    "Fries"           ) : 3,
            ( "Protein",    "SausageBiscuit"  ) : 15,
            ( "Protein",    "LowfatMilk"      ) : 9,
            ( "Protein",    "OrangeJuice"     ) : 1,
    
            ( "VitA",       "Cheeseburger"    ) : 15,
            ( "VitA",       "HamSandwich"     ) : 15,
            ( "VitA",       "Hamburger"       ) : 6,
            ( "VitA",       "FishSandwich"    ) : 2,
            ( "VitA",       "ChickenSandwich" ) : 8,
            ( "VitA",       "Fries"           ) : 0,
            ( "VitA",       "SausageBiscuit"  ) : 4,
            ( "VitA",       "LowfatMilk"      ) : 10,
            ( "VitA",       "OrangeJuice"     ) : 2,
    
            ( "VitC",       "Cheeseburger"    ) : 6,
            ( "VitC",       "HamSandwich"     ) : 10,
            ( "VitC",       "Hamburger"       ) : 2,
            ( "VitC",       "FishSandwich"    ) : 0,
            ( "VitC",       "ChickenSandwich" ) : 15,
            ( "VitC",       "Fries"           ) : 15,
            ( "VitC",       "SausageBiscuit"  ) : 0,
            ( "VitC",       "OrangeJuice"     ) : 4,
            ( "VitC",       "LowfatMilk"      ) : 120,
    
            ( "Calc",       "Cheeseburger"    ) : 30,
            ( "Calc",       "HamSandwich"     ) : 20,
            ( "Calc",       "Hamburger"       ) : 25,
            ( "Calc",       "FishSandwich"    ) : 15,
            ( "Calc",       "ChickenSandwich" ) : 15,
            ( "Calc",       "Fries"           ) : 0,
            ( "Calc",       "SausageBiscuit"  ) : 20,
            ( "Calc",       "LowfatMilk"      ) : 30,
            ( "Calc",       "OrangeJuice"     ) : 2,
    
            ( "Iron",       "Cheeseburger"    ) : 20,
            ( "Iron",       "HamSandwich"     ) : 20,
            ( "Iron",       "Hamburger"       ) : 20,
            ( "Iron",       "FishSandwich"    ) : 10,
            ( "Iron",       "ChickenSandwich" ) : 8,
            ( "Iron",       "Fries"           ) : 2,
            ( "Iron",       "SausageBiscuit"  ) : 15,
            ( "Iron",       "LowfatMilk"      ) : 0,
            ( "Iron",       "OrangeJuice"     ) : 2,
    
            ( "Volume",     "Cheeseburger"    ) : 4,
            ( "Volume",     "HamSandwich"     ) : 7.5,
            ( "Volume",     "Hamburger"       ) : 3.5,
            ( "Volume",     "FishSandwich"    ) : 5,
            ( "Volume",     "ChickenSandwich" ) : 7.3,
            ( "Volume",     "Fries"           ) : 2.6,
            ( "Volume",     "SausageBiscuit"  ) : 4.1,
            ( "Volume",     "LowfatMilk"      ) : 8,
            ( "Volume",     "OrangeJuice"     ) : 12
        }
    
        # Step 1. Create a model and change the parameters.
        model = MdoModel()
    
        try:
            # Step 2. Input model.
            # Change to minimization problem.
            model.set_int_attr("MinSense", 1)
    
            # Add variables.
            var = {}
            for food_name, food_data in food.items():
                var[food_name] = model.add_var(food_data[0], food_data[1], food_data[2], None, food_name, False)
    
            # Add constraints.
            for req_name, req_data in req.items():
                expr = MdoExprLinear()
                for food_name in food.keys():
                    expr += req_value[req_name, food_name] * var[food_name]
                model.add_cons(req_data[0], req_data[1], expr, req_name)
    
            # Step 3. Input parameters related to the remote computing server.
            model.set_str_param("Remote/Token", token)
            model.set_str_param("Remote/Desc", desc)
            model.set_str_param("Remote/Server", server)
            model.set_str_param("Remote/File/Path", filepath)
    
            # Step 4. Upload the serialized model and parameters to server, and then optimize the model.   
            job_id = model.submit_task()
            if job_id == "":
                print("ERROR: Empty job ID.")
                raise MdoError(-1)
            else:
                print("Job was submitted to server successfully.")
                print("User may query the optimization result with the following job ID: {}".format(job_id))
    
            # Step 5. Check the solution status periodically, and             
            #         download the its upon availability.       
            status = "Submitted"
            while status == 'Submitted' or status == 'Solving': 
                status, model_status, result, has_soln = model.retrieve_task(job_id)
    
                # Sleep for 10 seconds.
                time.sleep(10)
    
            model_status_details = model.explain_status(model_status)
            result_details = model.explain_result(result)
    
            print(" - Job status             : {}".format(status)) 
            print(" - Model status           : {0} ({1})".format(model_status_details, model_status))
            print(" - Optimization status    : {0} ({1})".format(result_details, result))
            print(" - Solution availability  : {0}".format("available" if has_soln else "not available"))
    
            if has_soln:
                print("\nPopulating solution.")
    
                model.display_results()
                status_code, status_msg = model.get_status()
                if status_msg == "OPTIMAL":
                    print("Optimizer terminated with an OPTIMAL status (code {0}).".format(status_code))
                    print("Daily cost           : ${0}".format(round(model.get_real_attr("PrimalObjVal"), 2)))
                    for food_name, food_var in var.items():
                        val = round(food_var.get_real_attr("PrimalSoln"), 2)
                        if val > 0.01:
                            print(f" - {food_name: <17} : {val}")
                else:
                    print("Optimizer terminated with a(n) {0} status (code {1}).".format(status_msg, status_code))
    
        except MdoError as e:
            print("Received Mindopt exception.")
            print(" - Code          : {}".format(e.code))
            print(" - Reason        : {}".format(e.message))
        except Exception as e:
            print("Received exception.")
            print(" - Reason        : {}".format(e))
        finally:
            pass
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245

    参考文章:
    MindOpt 优化求解器-线上版.
    MindOpt 官方文档.


    总结

    yeah,快下班了!

  • 相关阅读:
    【Python】学生管理系统——详细解释+代码+详细注释(课设必过)
    基于nginx在视频播放器与服务器之间反向代理流程
    C++中的语法知识虚继承和虚基类
    2022年最新西藏水利水电施工安全员考试题库及答案
    网络安全 记录
    Nacos Linux & Windows安装
    拓扑排序板子练习
    微服务项目:尚融宝(6)(上手复习mybatisplus)
    CLUE模型如何实现对未来土地利用/土地覆盖的时空预测
    OpenCV技术应用(3)— 把.png图像保存为.jpg图像
  • 原文地址:https://blog.csdn.net/weixin_42475060/article/details/126523393