有什么方法可以提高or-tools的速度吗?

时间:2020-07-29 10:23:43

标签: optimization mathematical-optimization or-tools mixed-integer-programming integer-programming

我正在尝试使用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)

1 个答案:

答案 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工具。