(1)指派问题
将集合I中的元素唯一地与集合J中的元素进行匹配,传统的整数规划模型需要先定义一类0-1决策变量xij,然后有以下约束条件。
该整数规划模型有|I||J|个变量和|I|+|J|个约束条件。
若用约束满足的思路来构建,则定义一类整数变量yi,表示元素i匹配到的元素j的值,然后再加一类all different 约束(表示yi的值各不相同)
该模型的变量数为|I|个,约束数量为1类CS约束(从后面论文描述情况来看数量上也为|I|+|J|个,不过变量数肯定是减少了)。
(2)党派参选问题(The Progressive Party Problem)
定义0-1决策变量xijt表示人员j在时间t被分配到党派i时为1,否则为0,同时在任意时刻,对于每个人都只能选择1个党派。
该模型有|I||J||T|个变量,然后有|J|个约束。
若用约束满足的思路来构建,定义一个整数变量yjt表示人员j在时间t选择的党派,然后再加一类all different 约束
(3)课程排班问题(School Timetabling Problem)
定义0-1决策变量xijk,表示教师i在时段t被分配到班级j时为1,否则为0,模型考虑的约束如下
该模型包含|I||J||K|个变量,然后有|J||K|+|I||K|+|I||J|个约束。
采用约束满足的思路来构建时定义整数变量yjk做如下替换
该模型包含|I||J||K|个变量,然后有|J||K|+|I||K|+|I||J|个约束。
2. 如何用凸包刻画all different 约束
考虑如下的all different约束
其中A表示整数备选集合
那么使用凸包刻画该约束的公式为(论文中有详细推导证明公式)
举一个考虑3个变量的简单例子,对于all_different(x1,x2,x3),A={0,1,2},那么六个可行点均在平面x1+x2+x3=3上
3. 基于指派问题进行简单测试
from pyomo.environ import ConcreteModel, Set, Param, Var, Objective, minimize, Constraint
from pyomo.opt import SolverFactory
import pyomo.environ as pyo
import time
def read_assign_file(file_path):
with open(file_path, 'r') as file:
# 读取待分配物品数量n
n = int(file.readline().strip())
cost_matrix = []
current_row = []
count = 0
for line in file:
numbers = line.strip().split()
for num in numbers:
current_row.append(int(num))
count += 1
if count == n:
cost_matrix.append(current_row)
current_row = []
count = 0
return n, cost_matrix
def build_assignment_model(n, cost_matrix):
model = ConcreteModel()
# 定义物品集合
model.nums = Set(initialize=range(n))
# 定义决策变量x(i,j),表示物品i是否分配给物品j,是二进制变量
model.assign = Var(model.nums, model.nums, within=pyo.Binary)
# 定义成本参数,对应成本矩阵中的值
model.cost = Param(model.nums, model.nums, initialize=lambda model, i, j: cost_matrix[i][j])
# 目标函数,最小化总成本
def total_cost_rule(model):
return sum(model.cost[i, j] * model.assign[i, j] for i in model.nums for j in model.nums)
model.obj = Objective(rule=total_cost_rule, sense=minimize)
# 每个物品只能分配出去一次的约束
def assign_once_rule(model, i):
return sum(model.assign[i, j] for j in model.nums) == 1
model.assign_once = Constraint(model.nums, rule=assign_once_rule)
# 每个物品最多只能接收一个物品的约束
def receive_once_rule(model, j):
return sum(model.assign[i, j] for i in model.nums) <= 1
model.receive_once = Constraint(model.nums, rule=receive_once_rule)
return model
if __name__ == "__main__":
file_path = "assign400.txt"
n, cost_matrix = read_assign_file(file_path)
model = build_assignment_model(n, cost_matrix)
# 使用SCIP求解器
solver = SolverFactory('SCIP')
t1=time.time()
result = solver.solve(model)
t2= time.time()
print(f"用时为{t2-t1}")
if result.solver.termination_condition == 'optimal':
print("找到最优解!")
optimal_cost = model.obj()
print("最优总成本:", optimal_cost)
# 输出分配方案(示例,你可以根据需求调整展示格式等)
for i in range(n):
for j in range(n):
if model.assign[i, j].value == 1:
print(f"物品{i}分配给物品{j}")
else:
print("未找到最优解,求解器终止状态:", result.solver.termination_condition)
from pyomo.environ import ConcreteModel, Set, Param, Var, Objective, minimize, Constraint
from pyomo.opt import SolverFactory
import pyomo.environ as pyo
import time
def read_assign_file(file_path):
with open(file_path, 'r') as file:
# 读取待分配物品数量n
n = int(file.readline().strip())
cost_matrix = []
current_row = []
count = 0
for line in file:
numbers = line.strip().split()
for num in numbers:
current_row.append(int(num))
count += 1
if count == n:
cost_matrix.append(current_row)
current_row = []
count = 0
return n, cost_matrix
def build_assignment_model(n, cost_matrix):
# 创建具体的模型实例
model = pyo.ConcreteModel("AssignmentProblem")
I = list(i+1 for i in range(n))
# 定义决策变量
model.y = pyo.Var(I, within=pyo.PositiveIntegers)
# 约束条件1
def person_assigned_one_rule(model, h):
return sum(model.y[t] for t in range(1, h + 1)) >= (h - 1) * h / 2
model.person_assigned_once = pyo.Constraint(I, rule=person_assigned_one_rule)
# 约束条件2
def person_assigned_two_rule(model, h):
return sum(model.y[t] for t in range(1, h + 1)) <= h * (2 * len(I) - h + 1) / 2
model.person_assigned_two = pyo.Constraint(I, rule=person_assigned_two_rule)
# 目标函数:最小化总成本
def objective_rule(model):
val = 0
for i in I:
for j in I:
if model.y[i].value == j:
val += cost_matrix[i-1][j-1]
return val
model.obj = pyo.Objective(rule=objective_rule, sense=pyo.minimize)
return model
if __name__ == "__main__":
file_path = "assign500.txt"
n, cost_matrix = read_assign_file(file_path)
model = build_assignment_model(n, cost_matrix)
# 使用SCIP求解器
solver = SolverFactory('SCIP')
t1=time.time()
result = solver.solve(model)
t2= time.time()
print(f"用时为{t2-t1}")
if result.solver.termination_condition == 'optimal':
print("找到最优解!")
optimal_cost = model.obj()
print("最优总成本:", optimal_cost)
排版|小马
图片|小马
文字|小马
微信公众号后台回复
加群:加入全球华人OR|AI|DS社区硕博微信学术群
资料:免费获得大量运筹学相关学习资料
人才库:加入运筹精英人才库,获得独家职位推荐
电子书:免费获取平台小编独家创作的优化理论、运筹实践和数据科学电子书,持续更新中ing...
加入我们:加入「运筹OR帷幄」,参与内容创作平台运营
知识星球:加入「运筹OR帷幄」数据算法社区,免费参与每周「领读计划」、「行业inTalk」、「OR会客厅」等直播活动,与数百位签约大V进行在线交流
文章须知
文章作者:小马过河啊
微信编辑:疑疑
文章转载自『小马过河啊』公众号,原文链接:使用凸包刻画约束满足问题中的alldifferent约束使模型更紧凑
关注我们
FOLLOW US