问题描述
我有一个分配问题要解决。我发现 ortools 是一个很好的工具,可以在这里使用。我设法解决了它,但它很慢,我需要它快。
我遇到的问题基本上是一堆商店以不同的价格出售相同的商品。我需要选择从哪里挑选这些商品,以达到最低的总价以及不超过 4 家商店。
这是我的代码,但如果提供的成本矩阵有 4 个以上的商店,它会很慢。问题在于商店最大限制约束。无论如何,这可以通过不同的编码来提高速度吗?
import numpy as np
from ortools.sat.python import cp_model
from ortools.linear_solver import pywraplp
#cost matrix,where j are stores,i are items
C = np.array([[38,13,73,10,76,6,80,65,17,2],[77,72,7,26,51,21,19,85,12,29],[30,15,69,88,95,97,87,14],[10,8,64,62,23,58,2,1,61,82],[ 9,89,14,48,31,4,71,22],[50,25,44,77,27,53,81],[42,83,16,99,27],[26,68,24,28,38,84,39],33,35,11,93],[75,63,47,56,66,78,4],[ 1,86,3,92,[76,37],[ 8,46,75,93,61],[25,98,55,83],[87,67,49,18,43],[21,54,56],[62,57,90,22,85],[44,60,72],[54,70,37,41,50,78]])
# the solver func
def Solve_Cost_Matrix_2(cost):
model = cp_model.CpModel()
max_stops=4
#generate ranges
num_items = len(cost)
num_shops = len(cost[0])
all_items = range(num_items)
all_shops = range(num_shops)
# Create bool Variable matrix
x=[]
for i in all_items:
t=[]
for j in all_shops:
t.append(model.NewBoolVar(f'i{i}_j{j}'))
x.append(t)
# Constraints
# Each item only assigned once to any store .
[model.Add(sum(x[i][j] for j in all_shops) == 1) for i in all_items]
# Adding the intermediate variable to constrain the number of the stores.
s=[]
for j in all_shops:
s.append( model.NewBoolVar(f's_{j}') )
for j in all_shops:
model.Add(sum(x[i][j] for i in all_items) >= 1).OnlyEnforceIf(s[j])
model.Add(sum(x[i][j] for i in all_items) == 0).OnlyEnforceIf(s[j].Not())
model.Add(sum(s[j] for j in all_shops) <= max_stops)
# Create the Objective function Variable
total_cost = model.NewIntvar(0,1000000,'total_cost')
# Create the Objective function,Minimize (Sum of cost)
model.Add(total_cost == (sum(x[i][j] * cost[i][j] for j in all_shops for i in all_items )))
model.Minimize(total_cost)
#Initialize the Solver ...
solver = cp_model.cpsolver()
status = solver.solve(model)
print(solver.ResponseStats())
Total_Cost,senario_cost = 0,0
#printing the solution
if status == cp_model.OPTIMAL:
senario_cost={'Items':[],'Assigned_to':[],'Item_cost':[],'Num_stops':0,'cost':[]}
Total_Cost = solver.ObjectiveValue()
for i in range(num_items):
for j in range(num_shops):
if solver.Value(x[i][j]) == 1:
senario_cost['Items'].append(i)
senario_cost['Assigned_to'].append(j)
senario_cost['Item_cost'].append(cost[i][j])
senario_cost['Num_stops'] = len(set(senario_cost['Assigned_to']))
senario_cost['cost'] = cost
return Total_Cost,senario_cost
else:
return None,None
我运行它时得到这个:
cpsolverResponse:
status: OPTIMAL
objective: 213
best_bound: 213
booleans: 210
conflicts: 106343
branches: 158796
propagations: 4242079
integer_propagations: 7844526
restarts: 878
lp_iterations: 0
walltime: 6.90529
usertime: 6.90529
deterministic_time: 4.67974
primal_integral: 0
cpu times: user 6.86 s,sys: 41 ms,total: 6.9 s
Wall time: 6.95 s
解决方法
当我在主分支上运行提供的代码时,没有并行性,我得到:
CpSolverResponse:
status: OPTIMAL
objective: 213
best_bound: 213
booleans: 210
conflicts: 31
branches: 617
propagations: 5226
integer_propagations: 8220
restarts: 428
lp_iterations: 130
walltime: 0.021303
usertime: 0.021303
deterministic_time: 0.0011162
primal_integral: 0.00536794
你得到不同的结果吗?