TulipaEnergy / TulipaEnergyModel.jl

An energy system optimization model that is flexible, computationally efficient, and academically robust.
Apache License 2.0
27 stars 18 forks source link

Add a How-To for dealing with infeasible solutions of the model #472

Closed datejada closed 7 months ago

datejada commented 8 months ago

Description

I have been working with the model in some cases, and it will be awesome to have a section with some hints to deal with infeasibilities in the model. We don't need to implement anything special (for now); it should be more of a guide on using the JuMP and MOI functions that help the user identify the infeasibilities in the model. The tutorial could be done with the same case study we use for the infeasibility in the tests. Then, show how to explore the model and understand the infeasibility. Here are some useful commands that I have been using, but more details and comments will be needed

using TulipaEnergyModel
using JuMP

INPUT_FOLDER = joinpath(pwd(), "AAA")
dir = joinpath(INPUT_FOLDER, "AAA")

energy_problem = create_energy_problem_from_csv_folder(dir)

using Gurobi
optimizer = Gurobi.Optimizer
parameters = Dict("OutputFlag" => 1)

create_model!(energy_problem; write_lp_file = true)
solve_model!(energy_problem, optimizer; parameters = parameters)

if energy_problem.termination_status == MOI.INFEASIBLE_OR_UNBOUNDED
    compute_conflict!(energy_problem.model)
    MOI.get.(energy_problem.model, MOI.ConstraintConflictStatus(), energy_problem.model[:max_output_flows_limit]
end

In this example, after calculating the conflict, I query the constraint max_output_flows_limit because I knew the problem was there. But we might use more generic code that explores all the constraints, finds the ones with a conflict status IN_CONFLICT, and prints them.

More information here: https://jump.dev/MathOptInterface.jl/stable/reference/models/#Conflict-Status

For instance, this is an example in Python using gurobipy of how to print them nicely (it is in Python, but the idea could be implemented quite similarly using the functions from MOI and JuMP:

# Print out the IIS constraints and variables
print('\nThe following constraints and variables are in the IIS:')
for c in model.getConstrs():
    if c.IISConstr: print(f'\t{c.constrname}: {model.getRow(c)} {c.Sense} {c.RHS}')

for v in model.getVars():
    if v.IISLB: print(f'\t{v.varname} ≥ {v.LB}')
    if v.IISUB: print(f'\t{v.varname} ≤ {v.UB}')

Here is the link to the complete Gurobi example: https://support.gurobi.com/hc/en-us/articles/15656630439441-How-do-I-use-compute-IIS-to-find-a-subset-of-constraints-that-are-causing-model-infeasibility

Related Issues

No response

datejada commented 8 months ago

WILD AND CRAZY IDEA! 💡⚡ @abelsiqueira It would be helpful to have a report similar to the one that Gurobi has, but created using functions in MOI and JuMP. I think it's possible to do, so if you're interested, we could collaborate on it and submit a pull request to the JuMP repository. You may be able to allocate time from the budget for generalization since it could be used for Tulipa/SpineOpt and any other model in JuMP.

datejada commented 8 months ago

BTW: for this issue in Tulipa, it will be enough to have the tutorial with hints on how to use the commands

abelsiqueira commented 8 months ago

@datejada, cool idea, we should talk about it.

datejada commented 8 months ago

WILD AND CRAZY IDEA! 💡⚡ @abelsiqueira It would be helpful to have a report similar to the one that Gurobi has, but created using functions in MOI and JuMP. I think it's possible to do, so if you're interested, we could collaborate on it and submit a pull request to the JuMP repository. You may be able to allocate time from the budget for generalization since it could be used for Tulipa/SpineOpt and any other model in JuMP.

Nevermind @abelsiqueira it already exists. The function is called ‘copy_conflict‘. And it is quite useful 😊

https://jump.dev/JuMP.jl/stable/api/JuMP/#JuMP.copy_conflict

So, we might add how to use it in this section.

These guys from JuMP are quite smart 🙃