【问题标题】:solve iteratively with cplex?用 cplex 迭代求解?
【发布时间】:2022-01-03 08:42:11
【问题描述】:

我正在尝试通过 python 解决一个带有 cplex 和 pyomo 的优化程序。我想迭代地解决它,在每次迭代中我改变变量为二进制的时间段。(例如,在第一次迭代中,我用变量在前 100 小时内保持二进制,而在其他小时内变量是连续的,所以在第二次迭代中,接下来的 100 小时内只有变量是二进制的,依此类推......)。我正在尝试一个while循环,其中求解器使用for循环在不同的时间范围内工作(如果需要,我可以添加代码)。但它似乎太慢了,也许我的周期不正确。有一种更快的方法来编写这个并解决很多时间一个模型迭代? 谢谢

【问题讨论】:

    标签: optimization while-loop cplex pyomo


    【解决方案1】:

    可以使代码更快的是在搜索中使用热启动而不是从零开始。见Saving a .sol file from one instance and using it as WARM_START for another instance on PYOMO

    import pyomo.environ as pyo
    from pyomo.opt import SolverFactory
    
    opt = pyo.SolverFactory('cplex')
    
    model = pyo.ConcreteModel()
    
    model.nbBus = pyo.Var([40,30], domain=pyo.PositiveIntegers)
    
    model.OBJ = pyo.Objective(expr = 500*model.nbBus[40] + 400*model.nbBus[30])
    
    model.Constraint1 = pyo.Constraint(expr = 40*model.nbBus[40] + 30*model.nbBus[30] >= 300)
    
    
    model.nbBus[40]=8
    model.nbBus[30]=1
    
    results = opt.solve(model,warmstart=True)
    
    print("nbBus40=",model.nbBus[40].value)
    print("nbBus30=",model.nbBus[30].value)
    

    在 docplex CPLEX API 中,您可以做一些incremental changes

    from docplex.mp.model import Model
    
    # original model
    
    mdl = Model(name='buses')
    nbbus40 = mdl.integer_var(name='nbBus40')
    nbbus30 = mdl.integer_var(name='nbBus30')
    mdl.add_constraint(nbbus40*40 + nbbus30*30 >= 300, 'kids')
    mdl.minimize(nbbus40*500 + nbbus30*400)
    
    mdl.solve()
    
    for v in mdl.iter_integer_vars():
        print(v," = ",v.solution_value)
    
    #now 350 kids instead of 300
    
    print()
    print("now 350 kids instead of 300")    
        
    mdl.get_constraint_by_name("kids").rhs=350;
    mdl.solve()
    
    for v in mdl.iter_integer_vars():
        print(v," = ",v.solution_value)
    
    # no more than 4 buses 40 seats
    
    print()
    print("no more than 4 buses 40 seats")
    
    
    mdl.get_var_by_name("nbBus40").ub=4
    mdl.solve()
    
    for v in mdl.iter_integer_vars():
        print(v," = ",v.solution_value)
    
    #change the objective so that cost for 40 seats is 450
    #and remove the limit on the number of buses 40 seats
    
    print()
    print("change the objective so that cost for 40 seats is 450")
    print("and remove the limit on the number of buses 40 seats  ")  
        
    mdl.get_var_by_name("nbBus40").ub=1000
    mdl.set_objective("min",nbbus40*450 + nbbus30*400);
    mdl.solve()
    
    for v in mdl.iter_integer_vars():
        print(v," = ",v.solution_value)
    

    【讨论】:

    • 我不应该创建模型的实例吗?
    【解决方案2】:

    如果您使用通常的pyomo.environ.SolverFactory 方法,这会为您的模型创建一个instance,然后生成一个.lp 文件,通过shell 命令发送到求解器,求解器解决问题并生成一个@ 987654326@ 文件并将其加载回模型。要解决模型中一些增量更改的相同问题,您可以使用Persisten Solver Interface。这将从pyomo 模型创建一个gurobipydocplex(分别用于gurobicplex 求解器)模型,那么使用这种方法可能会更快更好。还有 de APPSI interface 但我从未使用过它。

    【讨论】:

    • 我应该在每次迭代时使用这些增量更改来更新变量值吗?
    • 我不完全明白你的全部问题是什么。如果您编辑您的问题并向我们展示一个最小的可重现示例,那就更好了。如果您的问题是模型构建缓慢,您可以使用一些方法来提高速度,如果缓慢来自求解器,您将需要查看您是否为您的问题使用了正确的公式。
    • 第一次迭代:0-100小时的二进制变量,101-8760的连续并求解第二次:修复之前找到的二进制变量的值,二进制变量在101-201周期,202-连续8760,再次求解等等.. 这是一个一段时间的循环,在每次迭代中,我都会在一段时间内更改变量的域。我的问题是如何修复上一次迭代中找到的值?我不确定这一点。也许您所说的持久求解器是正确的方法。
    • 你可以这样做。固定变量不再是变量,而是参数,因此,每次迭代都会减少求解时间。求解模型后,您可以使用model.x[k].fixed = True 修复任何x[k] Var 并使用model.x[k].domain = pyo.Binary 更改任何x[k] Var 的域。完成修复和更改模型后,您可以使用您喜欢的方法再次解决。我不知道你的模型,但肯定的是,以每小时为基础的一整年建模每次求解都需要一段时间
    • 我创建一个具有持久性的实例然后我创建循环:while n
    猜你喜欢
    • 2018-03-01
    • 2013-05-27
    • 2015-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-21
    相关资源
    最近更新 更多