メインコンテンツへスキップ

Gurobi reports negative reduced costs in optimal solution

回答済み

コメント

4件のコメント

  • David Torres Sanchez
    • Gurobi Staff

    Hi Julian,

    This is sometimes the case with column generation and degeneracy.
    Have you tried changing the covering constraint to \(\geq\) (as you are minimising and there is nothing else in the master problem this should be OK, but feel free to change it back later to solve the final MIP).

    Cheers, 
    David

    0
  • Julian Berzborn
    • Gurobi-versary
    • First Comment
    • First Question

    Hi David,

    thank you for your quick reply! I have followed your advice and relaxed the covering constraint as shown below. This indeed helped me retain positive reduced costs, thus solving my first issue (1.). Unfortunately my second issue (2.) was not solved by this. I can see that after adding new columns with negative reduced costs generated by the pricing problem to the master problem the following happens:

    • the dual values provided by the master problem stay constant
    • thus the MIP formulation of the pricing problem (see above) suggests the same columns to add to the master problem

    Now I am wondering whether the updating routine for the master problem (see above) might be insufficient - e.g., does not alter the model as expected?

     

    Relaxed covering constraint

    # covering constraint
    self.constr_covering = model.addConstrs(
        (gp.quicksum(self.var_pattern[p]
                     for p in pattern_indices if i in patterns[p])
       >= 1
         for i in self.nodes),
         name="covering_constraint")
    0
  • David Torres Sanchez
    • Gurobi Staff

    Hi Julian,

    • thus the MIP formulation of the pricing problem (see above) suggests the same columns to add to the master problem

    Indeed, this is a sign that something is not quite working as expected.
    To debug this you can write the model to a file via \(\texttt{model.write(f"master{iter}.lp")}\) (using model.write()). 

    In this case, I think the code

    # adjust existing constraints
    for p in range_new_patterns:
        pattern = self.patterns[p]
        model.getCol(self.var_pattern[p]).addTerms(
            [1.0]*len(pattern),                                 # coefficient in constraint is 1 for each node in pattern p
            [self.constr_covering[i] for i in pattern])         # only need to update those constraints corresponding to active nodes in pattern p

    Does not do what you expect as the changes in the column will not persist in the original column (similarly when you do the same for rows).

    You can add them as follows:

    for p in range_new_patterns:
        pattern = self.patterns[p]
        col = gp.Column([1.0] * len(pattern), [self.constr_covering[i] for i in pattern])
      v = model.addVar(
            obj=add_costs, vtype=GRB.CONTINUOUS, name=f"lambda{p}", column=col
        )


    Then update \(\texttt{self.var_pattern}\), please note that it is a tupledict.

    Do you want me to open an internal ticket to discuss this further?

    Cheers, 
    David

    0
  • Julian Berzborn
    • Gurobi-versary
    • First Comment
    • First Question

    Hi David,

    thanks again for the quick reply! I adjusted my pattern update code as you suggested and now everything works as expected. At this point I do not need to discuss further - thank you for the support :)

    Best regards,
    Julian

    0

サインインしてコメントを残してください。