Python数学规划案例一
问题、模型、数据、算法、结果,统一地表述,是习惯也是效率。
我的公众号
数学规划模型表述习惯
采用五个部分:Set, Data, Variable, Objective, Constraints;每个Notation,采用一个主字符,上标表示含义,下标来自Set;已知的大写,未知的小写,下标用小写;妥善选择Notation中的每一个字符;对Notation、Objective、Constratins进行分组。模型即代码、即注释、即文章。
数学规划模型编码习惯
Ptyhon程序设计代码与模型表述严格一致 Set, Data, Variable, Objective, Constraints尽量相应“翻译”;将模型、数据预处理、模型结果后处理,分离开来,保持模型的干净、纯粹。代码即模型、即文档、即文章。
一个例子
预算约束下营养配餐。取自:
...\IBM\ILOG\CPLEX_Studio129\python\examples\mp\modeling\diet.py
模型
采用五个部分:Set, Data, Variable, Objective, Constraints建模。
代码
根据diet.py改写的代码如下。
# -*- coding: utf-8 -*-
from collections import namedtuple
from docplex.mp.model import Model
from docplex.util.environment import get_environment
# ----------------------------------------------------------------------------
# Initialize the problem data
# ----------------------------------------------------------------------------
FOODS = [
("Roasted Chicken", 0.84, 0, 10),
("Spaghetti W/ Sauce", 0.78, 0, 10),
("Tomato,Red,Ripe,Raw", 0.27, 0, 10),
("Apple,Raw,W/Skin", .24, 0, 10),
("Grapes", 0.32, 0, 10),
("Chocolate Chip Cookies", 0.03, 0, 10),
("Lowfat Milk", 0.23, 0, 10),
("Raisin Brn", 0.34, 0, 10),
("Hotdog", 0.31, 0, 10)
]
NUTRIENTS = [
("Calories", 2000, 2500),
("Calcium", 800, 1600),
("Iron", 10, 30),
("Vit_A", 5000, 50000),
("Dietary_Fiber", 25, 100),
("Carbohydrates", 0, 300),
("Protein", 50, 100)
]
FOOD_NUTRIENTS = [
("Roasted Chicken", 277.4, 21.9, 1.8, 77.4, 0, 0, 42.2),
("Spaghetti W/ Sauce", 358.2, 80.2, 2.3, 3055.2, 11.6, 58.3, 8.2),
("Tomato,Red,Ripe,Raw", 25.8, 6.2, 0.6, 766.3, 1.4, 5.7, 1),
("Apple,Raw,W/Skin", 81.4, 9.7, 0.2, 73.1, 3.7, 21, 0.3),
("Grapes", 15.1, 3.4, 0.1, 24, 0.2, 4.1, 0.2),
("Chocolate Chip Cookies", 78.1, 6.2, 0.4, 101.8, 0, 9.3, 0.9),
("Lowfat Milk", 121.2, 296.7, 0.1, 500.2, 0, 11.7, 8.1),
("Raisin Brn", 115.1, 12.9, 16.8, 1250.2, 4, 27.9, 4),
("Hotdog", 242.1, 23.5, 2.3, 0, 0, 18, 10.4)
]
Food = namedtuple("Food", ["name", "unit_cost", "qmin", "qmax"])
Nutrient = namedtuple("Nutrient", ["name", "qmin", "qmax"])
# ----------------------------------------------------------------------------
# Build the model
# ----------------------------------------------------------------------------
def build_diet_model(**kwargs):
# Create tuples with named fields for foods and nutrients
F = [f[0] for f in FOODS]
C = {f[0]:f[1] for f in FOODS}
Fmin = {f[0]:f[2] for f in FOODS}
Fmax = {f[0]:f[3] for f in FOODS}
N = [n[0] for n in NUTRIENTS]
Nmin = {n[0]:n[1] for n in NUTRIENTS}
Nmax = {n[0]:n[2] for n in NUTRIENTS}
D = {(F[f],N[n]): FOOD_NUTRIENTS[f][n+1] for f in range(len(F)) for n in range(len(N))}
# Model
mdl = Model(name='diet', **kwargs)
# Decision variables, limited to be >= Food.qmin and <= Food.qmax
x = mdl.continuous_var_dict(F, lb=Fmin, ub=Fmax, name=F) # 2,4
# Limit range of nutrients, and mark them as KPIs
for n in N:
y = mdl.sum(x[f] * D[f, n] for f in F)
mdl.add_range(Nmin[n], y, Nmax[n]) # 3
mdl.add_kpi(y, publish_name="Total %s" % n)
for f in F:
mdl.add_kpi(x[f], publish_name="Food %s" % f)
# Minimize cost
mdl.minimize(mdl.sum(x[f] * C[f] for f in F)) # 1
return mdl
# ----------------------------------------------------------------------------
# Solve the model and display the result
# ----------------------------------------------------------------------------
if __name__ == '__main__':
mdl = build_diet_model()
mdl.print_information()
mdl.export_as_lp()
if mdl.solve():
mdl.float_precision = 3
print("* model solved as function:")
mdl.print_solution()
mdl.report_kpis()
# Save the CPLEX solution as "solution.json" program output
with get_environment().get_output_stream("diet2.json") as fp:
mdl.solution.export(fp, "json")
else:
print("* model has no solution")
扩展阅读
Python数学规划之Cplex之旅
Python利器
Python哲学
Python研究生