如何序列化(保存)Google OR-Tools mathopt模型对象及替代方案
解决Google OR-Tools MathOpt模型持久化与修改问题
一、Pickle无法序列化MathOpt模型的原因
MathOpt的Model对象内部包含WeakSet等无法被Pickle序列化的本地对象,这是触发AttributeError的直接原因。而CP-SAT模型的底层实现结构不同,因此可以正常被Pickle序列化。
二、正确的Protobuf导出/导入方案
你之前的Protobuf导入失败,是因为错误地尝试将解析后的内容写入model.export_model()返回的临时对象,而非通过Model.from_proto()方法从Proto对象创建新模型。以下是修正后的完整实现:
导出模型
from google.protobuf import text_format from ortools.math_opt.python import mathopt def export_model(model, filename): model_proto = model.export_model() with open(filename, "w") as file: file.write(text_format.MessageToString(model_proto)) # 示例导出流程 model = mathopt.Model(name="getting_started_lp") x = model.add_variable(lb=0.0, ub=1.5, name="x") y = model.add_variable(lb=0.0, ub=1.0, name="y") # 给约束命名,方便后续定位修改 model.add_linear_constraint(x + y <= 2, name="sum_upper_bound") model.maximize(x + 2 * y) export_model(model, "model.prototxt")
导入模型
from google.protobuf import text_format from ortools.math_opt.python import mathopt from ortools.math_opt import model_pb2 def import_model(filename): model_proto = model_pb2.ModelProto() with open(filename, "r") as file: text_format.Parse(file.read(), model_proto) return mathopt.Model.from_proto(model_proto) # 示例导入流程 loaded_model = import_model("model.prototxt")
三、定位并修改目标约束
导入模型后,可通过约束名称快速定位并修改:
# 通过名称获取目标约束 target_constraint = loaded_model.linear_constraints["sum_upper_bound"] # 修改约束上界 target_constraint.set_upper_bound(1.8) # 若需要修改下界,执行以下代码 # target_constraint.set_lower_bound(0.5) # 重新求解模型 solver = mathopt.Solver("glop") result = solver.solve(loaded_model) print(f"目标值: {result.objective_value}") print(f"x取值: {result.variable_values[loaded_model.variables['x']]}") print(f"y取值: {result.variable_values[loaded_model.variables['y']]}")
四、多轮用户调用的注意事项
- 每次修改后重新求解时,建议创建新的
Solver实例,避免残留状态干扰结果。 - 若需频繁修改固定约束,导入模型后可提前缓存约束对象,减少重复查找的性能开销。
内容的提问来源于stack exchange,提问作者Bhartendu Awasthi
相关产品推荐
相关产品推荐

