我正在尝试使用or-tools解决MIP问题。如果使用较小的Number和Range,它可以运行得非常快,您可以将它们视为变量数量和约束数量。但是对于较大的值,它运行较慢,有时甚至无法获得可行的结果。如果还有其他方法可以通过Number = 1,000,000和Range = 10,000来提高速度?
问题描述
变量:x,r,#x =#r = Number
对象:最小化(sum(r))
受制于: (1)r为0或1。
(2)x是整数。
(3)x <= M * r,其中M为无穷大。
(4)对于存储桶中的任何唯一项目,sum(x [buckets == item])落在[count(item)* 0.9,count(item)* 1.1]
(5)如果x> 0 可能有一个下界
from __future__ import print_function
from ortools.sat.python import cp_model
import numpy as np
import pandas as pd
np.random.seed(1)
def set_up_buckets(Number,Range,mu=0,sigma=1):
buckets = (np.random.normal(0, 1, Number)*Range).astype(int)
print("number of buckets:",len(np.unique(buckets)))
return buckets
model = cp_model.CpModel()
Number = 1000000
Range = 10000
Infinity = int(Number/10)
buckets = set_up_buckets(Number,Range)
def reduce_intervals(buckets,Range,sigma_cnt,mu=0,sigma=1):
upper = (mu+sigma*sigma_cnt)*Range
lower = (mu-sigma*sigma_cnt)*Range
buckets_reduced = buckets[(buckets<=upper)&(buckets>=lower)]
return buckets_reduced
buckets_reduced = reduce_intervals(buckets,Range,2)
def set_up_variables(Number):
x,r = [],[]
for i in range(Number):
x.append(model.NewIntVar(0, Infinity, 'x{}'.format(i+1)))
r.append(model.NewBoolVar('r{}'.format(i+1)))
return np.array(x),np.array(r)
x,r = set_up_variables(Number)
%%time
def set_up_constraints(Number,unique_buckets):
M = Number
x_lower_bound = int(Number/10000)
# x_upper_bound = int(Number/10)
print("add attributes constraints")
for i in unique_buckets:
xs = x[buckets==i]
model.Add(sum(xs) <= int(1.1*len(xs)))
model.Add(sum(xs) >= int(0.9 * len(xs)))
print("add x&r constraints")
for i in range(Number):
model.Add(x[i] <= M*r[i])
model.Add(x_lower_bound - x[i] <= M*(1-r[i]))
model.Minimize(sum(r))
return model
model = set_up_constraints(Number,np.unique(buckets_reduced))
def solve_model(model,max_seconds = 60*60):
solver = cp_model.CpSolver()
solver.parameters.log_search_progress = True
solver.parameters.num_search_workers = 8
solver.parameters.max_time_in_seconds = max_seconds
status = solver.Solve(model)
return solver,status
solver,status = solve_model(model)
答案 0 :(得分:1)
set_up_constraints方法是灾难性的,您正在以密集的方式扫描O(Number ^ 2)个元素以建立非常稀疏的线性不等式。
您可以尝试使用其他代码,例如,下面的代码不会创建x [i] * 0的大部分,但是仍然很慢。
for i in unique_buckets:
xs = [x[j] for j in range(len(x)) if buckets[j] == i]
model.Add(sum(xs) <= int(1.1*len(xs)))
model.Add(sum(xs) >= int(0.9 * len(xs)))
无论如何,暂时的性能问题来自您的代码,而不是or工具。