Démarrage à chaud dans Pyomo + Xpress

0

La question

Je fais face à un gros problème d'optimisation. Pyomo est utilisé comme une enveloppe, xpress est utilisé comme un solveur. Chaque course je enregistrer les valeurs des variables pour le chargement de ces valeurs dans des variables avant de résoudre le problème à nouveau. Je tiens donc à mettre en œuvre un démarrage à chaud. Le solveur d'appel ressemble à ceci:

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

Dans le tee-log, je vois que le problème est résolu dès le début, et mes hypothèses sur les valeurs initiales ne sont pas prises en compte. J'ai deux questions:

  1. Comment interpréter tee journal (je n'ai pas trouvé de détails dans la documentation);
  2. Comment faire pour démarrage à chaud si nous avons sauvé le modèle précédent et à ses valeurs de variable?
1

La meilleure réponse

0

Voici un petit code qui montre comment utiliser un démarrage à chaud avec le Xpress optimiseur. Notez que je ne suis pas un expert en Pyomo, il peut donc y avoir de meilleures façons de mettre en œuvre les create_model fonction, mais pour l'utilisation de warmstarts vous devriez vous concentrer sur le reste du code, de toute façon.

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)

Afin d'utiliser un warmstart, vous affectez le warmstart de la valeur à chaque variable et chaque appel solve avec warmstart=True. Le journal de sortie affichée par l' tee ensuite contenir des lignes comme celles-ci:

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

La première ligne indique qu'un warmstart solution a été enregistré avec le solveur Xpress. Les deux dernières lignes indiquent que le warmstart solution a été traitée et acceptée. Un warmstart solution est signalé comme une solution de " U " heuristique dans le journal.

Notez que le traitement de warmstart solutions peut être retardée jusqu'à ce que, après le premier LP résoudre, alors il peut prendre un certain temps avant qu'ils sont rapportés dans le journal.

2021-11-23 10:48:22

Dans d'autres langues

Cette page est dans d'autres langues

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