本文介绍 Python 语言调用 SCIP 求解器,求解选址模型的代码示例。
安装 SCIP 和 PySCIPOpt
安装 SCIP 求解器的教程:
SCIP | 数学规划求解器SCIP超详细的使用教程.
笔者在 Windows 10 系统上安装了 SCIP v7.0.0,并通过清华镜像源安装了 PySCIPOpt v3.2.0,Python 版本为 3.7.8
(UserWarning 显示,该版本的 PySCIPOpt 建议使用 SCIP v7.0.1)
pip install PySCIPOpt==3.2.0 -i https://pypi.tuna.tsinghua.edu.cn/simple
选址模型代码示例
模型模块:
from typing import List, Dict
from pyscipopt import Model, quicksum
def location(num_node: int, num_centre: int, mat_distance: List[List[float]]) -> Dict[int, List[int]]:
"""
location model
:param num_node: number of nodes
:param num_centre: number of centres
:param mat_distance: distance matrix
:return: dict_res: {centre node: [node] list} dictionary
"""
model = Model("location")
x = {(i, j): model.addVar(vtype="B", name="x_[{},{}]".format(i, j)) for i in range(num_node)
for j in range(num_node)}
# basic constraint
for j in range(num_node):
model.addCons(quicksum(x[i, j] for i in range(num_node)) == 1, name="basic_cover_[{}]".format(j))
for i in range(num_node):
model.addCons(x[i, j] <= x[i, i], name="basic_centre_[{},{}]".format(i, j))
# number of centres
model.addCons(quicksum(x[i, i] for i in range(num_node)) == num_centre, name="num_centre")
# objective: min, total distance
model.setObjective(quicksum(mat_distance[i][j] * x[i, j] for i in range(num_node) for j in range(num_node)),
sense="minimize")
# time limit
model.setRealParam("limits/time", 1000)
# solve
model.optimize()
print()
# status
status = model.getStatus()
print("model status: {}".format(status), '\n')
if status != "optimal":
return {}
# optimal objective value
obj_value = model.getObjVal()
print("optimal objective value: {}".format(obj_value), '\n')
# optimal solution
x_ = {(i, j): model.getVal(x[i, j]) for i in range(num_node) for j in range(num_node)}
# result process
dict_res = {}
for i in range(num_node):
if x_[i, i] > 0.9:
list_tmp = []
for j in range(num_node):
if x_[i, j] > 0.9:
list_tmp.append(j)
dict_res[i] = list_tmp
print("centre code {} serves nodes: {}".format(i, list_tmp))
return dict_res
主程序:
import random
from model import location
num_node = 100
ran_coo = (0, 100)
random.seed(a=1024)
list_coo = [(random.randint(ran_coo[0], ran_coo[1]),
random.randint(ran_coo[0], ran_coo[1])) for _ in range(num_node)]
mat_dist = [[((list_coo[i][0] - list_coo[j][0]) ** 2 + (list_coo[i][1] - list_coo[j][1]) ** 2) ** 0.5
for j in range(num_node)] for i in range(num_node)]
num_amount = 10
dict_res = location(num_node=num_node, num_centre=num_amount, mat_distance=mat_dist)
求解日志: