Teplý start v Pyomo + Xpress

0

Otázka

Potýkám se s velkým optimalizační problém. Pyomo je použit jako obal, xpress se používá jako řešitel. Každý běh jsem uložit hodnoty proměnných za účelem načtení těchto hodnot do proměnných, než řešení problému znovu. Tak jsem chtěl provést teplý start. Řešitel volání vypadá takto:

opt = SolverFactory('xpress_direct')    
results = opt.solve(model, warmstart=True, tee=True)

V tee-log vidím, že problém je vyřešen od začátku, a mé předpoklady o počáteční hodnoty nejsou brány v úvahu. Mám dvě otázky:

  1. Jak interpretovat tee log (nenašel jsem podrobnosti v dokumentaci);
  2. Jak teplý start, pokud zachránili jsme předchozí model a jeho proměnné hodnoty?
1

Nejlepší odpověď

0

Zde je malý kód, který ukazuje, jak použít teplý start s Xpress optimizer. Vědomí, že nejsem odborník v Pyomo, takže tam může být lepší způsoby, jak realizovat create_model funkce, ale pro použití warmstarts byste se měli zaměřit na zbytek kódu stejně.

import pyomo.environ as pyo
from pyomo.environ import value
from pyomo.opt import SolverFactory

def create_model():
    """Create a model that is non-trivial to solve.
    The returned model has two variables: `x` and `s`. It also has an
    objective function that is stored in `obj`.
    """
    model = pyo.ConcreteModel()
    model.X = pyo.RangeSet(50)
    model.S = pyo.RangeSet(6)
    model.x = pyo.Var(model.X, within=pyo.Binary)
    x = model.x
    model.s = pyo.Var(model.S, bounds = (0, None))
    s = model.s
    model.obj = pyo.Objective(expr=s[1] + s[2] + s[3] + s[4] + s[5] + s[6])
    model.cons = pyo.ConstraintList()

    model.cons.add(s[1] + 25*x[1] + 35*x[2] + 14*x[3] + 76*x[4] + 58*x[5] + 10*x[6] + 20*x[7]
                   + 51*x[8] + 58*x[9] + x[10] + 35*x[11] + 40*x[12] + 65*x[13] + 59*x[14] + 24*x[15]
                   + 44*x[16] + x[17] + 93*x[18] + 24*x[19] + 68*x[20] + 38*x[21] + 64*x[22] + 93*x[23]
                   + 14*x[24] + 83*x[25] + 6*x[26] + 58*x[27] + 14*x[28] + 71*x[29] + 17*x[30]
                   + 18*x[31] + 8*x[32] + 57*x[33] + 48*x[34] + 35*x[35] + 13*x[36] + 47*x[37]
                   + 46*x[38] + 8*x[39] + 82*x[40] + 51*x[41] + 49*x[42] + 85*x[43] + 66*x[44]
                   + 45*x[45] + 99*x[46] + 21*x[47] + 75*x[48] + 78*x[49] + 43*x[50] == 1116)
    model.cons.add(s[2] + 97*x[1] + 64*x[2] + 24*x[3] + 63*x[4] + 58*x[5] + 45*x[6] + 20*x[7]
                   + 71*x[8] + 32*x[9] + 7*x[10] + 28*x[11] + 77*x[12] + 95*x[13] + 96*x[14]
                   + 70*x[15] + 22*x[16] + 93*x[17] + 32*x[18] + 17*x[19] + 56*x[20] + 74*x[21]
                   + 62*x[22] + 94*x[23] + 9*x[24] + 92*x[25] + 90*x[26] + 40*x[27] + 45*x[28]
                   + 84*x[29] + 62*x[30] + 62*x[31] + 34*x[32] + 21*x[33] + 2*x[34] + 75*x[35]
                   + 42*x[36] + 75*x[37] + 29*x[38] + 4*x[39] + 64*x[40] + 80*x[41] + 17*x[42]
                   + 55*x[43] + 73*x[44] + 23*x[45] + 13*x[46] + 91*x[47] + 70*x[48] + 73*x[49]
                   + 28*x[50] == 1325)
    model.cons.add(s[3] + 95*x[1] + 71*x[2] + 19*x[3] + 15*x[4] + 66*x[5] + 76*x[6] + 4*x[7]
                   + 50*x[8] + 50*x[9] + 97*x[10] + 83*x[11] + 14*x[12] + 27*x[13] + 14*x[14]
                   + 34*x[15] + 9*x[16] + 99*x[17] + 62*x[18] + 92*x[19] + 39*x[20] + 56*x[21]
                   + 53*x[22] + 91*x[23] + 81*x[24] + 46*x[25] + 94*x[26] + 76*x[27] + 53*x[28]
                   + 58*x[29] + 23*x[30] + 15*x[31] + 63*x[32] + 2*x[33] + 31*x[34] + 55*x[35]
                   + 71*x[36] + 97*x[37] + 71*x[38] + 55*x[39] + 8*x[40] + 57*x[41] + 14*x[42]
                   + 76*x[43] + x[44] + 46*x[45] + 87*x[46] + 22*x[47] + 97*x[48] + 99*x[49] + 92*x[50]
                   == 1353)
    model.cons.add(s[4] + x[1] + 27*x[2] + 46*x[3] + 48*x[4] + 66*x[5] + 58*x[6] + 52*x[7] + 6*x[8]
                   + 14*x[9] + 26*x[10] + 55*x[11] + 61*x[12] + 60*x[13] + 3*x[14] + 33*x[15]
                   + 99*x[16] + 36*x[17] + 55*x[18] + 70*x[19] + 73*x[20] + 70*x[21] + 38*x[22]
                   + 66*x[23] + 39*x[24] + 43*x[25] + 63*x[26] + 88*x[27] + 47*x[28] + 18*x[29]
                   + 73*x[30] + 40*x[31] + 91*x[32] + 96*x[33] + 49*x[34] + 13*x[35] + 27*x[36]
                   + 22*x[37] + 71*x[38] + 99*x[39] + 66*x[40] + 57*x[41] + x[42] + 54*x[43] + 35*x[44]
                   + 52*x[45] + 66*x[46] + 26*x[47] + x[48] + 26*x[49] + 12*x[50] == 1169)
    model.cons.add(s[5] + 3*x[1] + 94*x[2] + 51*x[3] + 4*x[4] + 25*x[5] + 46*x[6] + 30*x[7]
                   + 2*x[8] + 89*x[9] + 65*x[10] + 28*x[11] + 46*x[12] + 36*x[13] + 53*x[14]
                   + 30*x[15] + 73*x[16] + 37*x[17] + 60*x[18] + 21*x[19] + 41*x[20] + 2*x[21]
                   + 21*x[22] + 93*x[23] + 82*x[24] + 16*x[25] + 97*x[26] + 75*x[27] + 50*x[28]
                   + 13*x[29] + 43*x[30] + 45*x[31] + 64*x[32] + 78*x[33] + 78*x[34] + 6*x[35]
                   + 35*x[36] + 72*x[37] + 31*x[38] + 28*x[39] + 56*x[40] + 60*x[41] + 23*x[42]
                   + 70*x[43] + 46*x[44] + 88*x[45] + 20*x[46] + 69*x[47] + 13*x[48] + 40*x[49]
                   + 73*x[50] == 1160)
    model.cons.add(s[6] + 69*x[1] + 72*x[2] + 94*x[3] + 56*x[4] + 90*x[5] + 20*x[6] + 56*x[7]
                   + 50*x[8] + 79*x[9] + 59*x[10] + 36*x[11] + 24*x[12] + 42*x[13] + 9*x[14]
                   + 29*x[15] + 68*x[16] + 10*x[17] + x[18] + 44*x[19] + 74*x[20] + 61*x[21] + 37*x[22]
                   + 71*x[23] + 63*x[24] + 44*x[25] + 77*x[26] + 57*x[27] + 46*x[28] + 51*x[29]
                   + 43*x[30] + 4*x[31] + 85*x[32] + 59*x[33] + 7*x[34] + 25*x[35] + 46*x[36] + 25*x[37]
                   + 70*x[38] + 78*x[39] + 88*x[40] + 20*x[41] + 40*x[42] + 40*x[43] + 16*x[44]
                   + 3*x[45] + 3*x[46] + 5*x[47] + 77*x[48] + 88*x[49] + 16*x[50] == 1163)

    return model

for load in [False, True]:
    model = create_model()
    opt = SolverFactory('xpress_direct')
    opt.options['MAXNODE'] = 1
    
    if not load:
        # In the first iteration just solve and store the best solution
        # found in x_start and s_start.
        print('First iteration: Solve to get a feasible solution')
        opt.solve(model, tee=True)
        print('Saving solution with objective %f' % value(model.obj))
        x_start, s_start = dict(), dict()
        for i in model.x:
            x_start[i] = model.x[i].value
        for i in model.s:
            s_start[i] = model.s[i].value
    else:
        # In the second iteration load the solution from x_start and
        # s_start and then solve. The log should show lines like
        #   User solution (_) stored.
        #   ...
        #   Its Type    BestSoln    BestBound   Sols    Add    Del     Gap     GInf   Time
        #   User solution (_) accepted: Feasible after reoptimizing with fixed globals.
        #   U           62.000000      .000000      3                    62        0      0
        # That indicate that the user solution was used and accepted.
        print('Second iteration: Solve with a warmstart')
        for i in model.x:
            model.x[i] = x_start[i]
        for i in model.s:
            model.s[i] = s_start[i]
        opt.solve(model, warmstart=True, tee=True)

Aby bylo možné používat startem, přiřadit startem hodnotu každé proměnné a volání solve s warmstart=True. Výstup protokolu zobrazí přes tee pak bude obsahovat řádky, jako jsou tyto:

User solution (_) stored.
...
User solution (_) accepted: Feasible after reoptimizing with fixed globals.
U           62.000000      .000000      3                    62        0      0

První řádek označuje, že startem řešení byla zapsána s Xpress řešitel. Poslední dva řádky ukazují, že startem řešení byl zpracován a přijat. Před startem řešení je hlášena jako řešení z " U " heuristické v protokolu.

Všimněte si, že zpracování startem řešení může být odloženo až po počáteční LP vyřešit, takže to může chvíli trvat, než jsou hlášeny v protokolu.

2021-11-23 10:48:22

V jiných jazycích

Tato stránka je v jiných jazycích

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................