Search code examples
pythonlinear-programmingcplex

Python CPLEX warm starts from infeasible solution


I currently have an (integer) LP problem solved which has, amongst others, the following mathematical constraint as pseudocode.

Packages_T1 + Packages_T2 + Packages_T3 + RPackages = 25

It represents three package trucks (T1, T2 and T3) to each of which packages can be assigned plus a residual/spilled package variable which is used in the objective function. The current value of 25 represents the total package demand.

Lets say I want to re-solve this problem but change the current demand of 25 packages to 35 packages. When I warm start from the previous solution with 25 packages CPLEX errors out in stating that the provided solution is infeasible: which makes perfect sense. However, it subsequently fails to repair the previous solution even though the most straight-forward way to do this would be to "up" the RPackages variable for each of these constraints.

My question is whether there is any possibility to still use the information from the previously solved problem as a warm start to the new one. Is there a way to, for example, drop all RPackages from the solution and have them recalculated to fit the new constraint right-hand side? A "last resort" effort I thought of would be to manually recalculate all these RPackages values myself and replace them in the old solution but a more automated solution to this problem would be preferred. I am using the standard CPLEX Python API for reference.

Thank you in advance.


Solution

  • even if the warmstart is not feasible CPLEX can use some information.

    Let me use the zoo example from

    https://www.linkedin.com/pulse/making-optimization-simple-python-alex-fleischer/

    from docplex.mp.model import 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)
    
    warmstart=mdl.new_solution()
    warmstart.add_var_value(nbbus40,4)
    warmstart.add_var_value(nbbus30,0)
    mdl.add_mip_start(warmstart)
    
    
    sol=mdl.solve(log_output=True)
    
    for v in mdl.iter_integer_vars():
        print(v," = ",v.solution_value)
    

    gives

    Warning:  No solution found from 1 MIP starts.
    Retaining values of one MIP start for possible repair.