前言
周四,天气渐渐凉快了下来。
一、安装
个人建议:先使用在线版的看一下效果,毕竟本机装环境超麻烦的好吗。
二、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
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
参考文章:
总结
yeah,快下班了!