Understanding Gurobi Variable Names

306 views
Skip to first unread message

Lauren Kuntz

unread,
Apr 7, 2020, 1:45:55 PM4/7/20
to pypsa
I have a network that is infeasible, so have been trying to use gurobi to save the model.ilp file so I can understand which constraints are making it infeasible. However, I'm struggling to interpret what the gurobi variable names relate to in the pypsa model. The .ilp file looks as follows:

Minimize
   <gurobi.LinExpr: 0.0>
Subject To
   c_l_x45807_ : <gurobi.LinExpr: x12970 + x23257> >= 0.0
   c_e_x48179_ : <gurobi.LinExpr: x23257 + x2900 + x418> = 22.70892072648328
Bounds
   -inf <= x12970 <= 859.1
   x23257  free
   1079.2570525 <= x2900 <= inf


Is there a way to understand what each x is referring to? I'm assuming there has to be some mapping as the pyomo model interprets the results from the gurobi solve, but after spending a few hours looking through the pypsa code, I couldn't track down where any such mapping was occuring. Any suggestions would be greatly appreciated.

Thanks!
Lauren

Fabian Neumann

unread,
Apr 7, 2020, 3:59:10 PM4/7/20
to Lauren Kuntz, pypsa
Hi Lauren,

the mapping is done in pyomo internally, and you are right it's a bit
tricky to interpret the lp files. This could work:

```
import pypsa
from pyomo.core import ComponentUID

n = pypsa.Network("some_network.nc")

pypsa.opf.network_lopf_build_model(n, **kwargs)

_, smap_id = n.model.write("test.lp")
symbol_map = n.model.solutions.symbol_map[smap_id]

mapping = {}
for symbol, var_weakref in symbol_map.bySymbol.items():
mapping[symbol] = ComponentUID(var_weakref())

pypsa.opf.network_lopf_prepare_solver(n, **kwargs)
pypsa.opf.network_lopf_solve(n, **kwargs)
```

The dictionary `mapping` will contain the translation.

Probably there is a more elegant way. I'd be glad if someone could tell me.

Best wishes,

Fabian N
> --
> You received this message because you are subscribed to the Google
> Groups "pypsa" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to pypsa+un...@googlegroups.com
> <mailto:pypsa+un...@googlegroups.com>.
> To view this discussion on the web, visit
> https://groups.google.com/d/msgid/pypsa/24efc843-d5d1-4aaf-8afa-ba3cb954a19b%40googlegroups.com
> <https://groups.google.com/d/msgid/pypsa/24efc843-d5d1-4aaf-8afa-ba3cb954a19b%40googlegroups.com?utm_medium=email&utm_source=footer>.

--
Karlsruhe Institute of Technology (KIT)
Institute for Automation and Applied Informatics (IAI)

Fabian Neumann (he/him)
PhD Student in Energy System Modelling

Phone: +49 721 608 25707 | Mobile: +49 171 2943831 |
Group: www.iai.kit.edu/english/esm.php | Personal: www.neumann.fyi |
Github: @fneum | Twitter: @fneum_

Learn about nearly-optimal power system models:
https://arxiv.org/abs/1910.01891

KIT Campus North, Building 445, Office 304
Hermann-von-Helmholtz-Platz 1
76344 Eggenstein-Leopoldshafen

KIT – The Research University in the Helmholtz Association

Lauren Kuntz

unread,
Apr 7, 2020, 7:10:42 PM4/7/20
to pypsa
Fabian - Wow thank you so much for the quick reply! That did exactly the trick - maybe not the prettiest but it worked which is all I needed. And saved me a lot of headache and confusion to boot

Many thanks!

denyin

unread,
Feb 25, 2021, 2:25:22 AM2/25/21
to pypsa
Dear pypsa,

I am also trying to understand my infeasibile model.
Concerning the code snippets provided by Fabian, my infeasible model doesn't work at
_, smap_id = n.model.write("test.lp").

with the error message
File "..\lib\site-packages\pyomo\core\base\block.py", line 1786, in write
(filename, smap) = problem_writer(self,
File "pyomo\repn\plugins\cpxlp.pyx", line 162, in pyomo.repn.plugins.cpxlp.ProblemWriter_cpxlp.__call__
File "pyomo\repn\plugins\cpxlp.pyx", line 163, in pyomo.repn.plugins.cpxlp.ProblemWriter_cpxlp.__call__
File "pyomo\repn\plugins\cpxlp.pyx", line 164, in pyomo.repn.plugins.cpxlp.ProblemWriter_cpxlp.__call__
File "pyomo\repn\plugins\cpxlp.pyx", line 645, in pyomo.repn.plugins.cpxlp.ProblemWriter_cpxlp._print_model_LP
AssertionError

In my model, the constraint_data.lower and constraint_data.upper of some constrains are both nan in cpxlp.py in pyomo pkg
if constraint_data.equality:
    assert value(constraint_data.lower) == \
           value(constraint_data.upper)

Do you know how to determine where the nan value occurs in the pypsa model?

Info:
pypsa.network is created with the pyomo = False option.
pypsa 0.17.1
pyomo 5.7.3
python 3.7


Best,
Ying

denyin

unread,
Mar 3, 2021, 1:09:34 AM3/3/21
to pypsa
Hi Fabian and PyPSA,

Thank you so much for your support and sorry for making you confused.

It is indeed a pyomo model for mapping. I have unnecessarily mentioned "setting pyomo=False". Basically, I solve the model by setting pyomo=False and exporting the pypsa network to a ".nc" file. Then the model is rebuilt by pypsa.opf.network_lopf_build_mode(network).

So far, my model has become feasible. I would also like to share my experience.

I detected the nan value by decreasing the model size (reduce number of nodes, add minimum components and then add more components) and debugging step by step. In my case, there is a single nan value in one of the time series.

In this, I borrowed the ideal from your code snippets and practically used the following (I use Gurobi to solve the problem):
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
def build_pyomo_model(nc_file):
    override_component_attrs = pypsa.descriptors.Dict({k: v.copy() for k, v in pypsa.components.component_attrs.items()})
    override_component_attrs["Link"].loc["bus2"] = ["string", np.nan, np.nan, "2nd bus", "Input (optional)"]
    override_component_attrs["Link"].loc["bus3"] = ["string", np.nan, np.nan, "3rd bus", "Input (optional)"]
    override_component_attrs["Link"].loc["efficiency2"] = ["static or series", "per unit", 1., "2nd bus efficiency", "Input (optional)"]
    override_component_attrs["Link"].loc["efficiency3"] = ["static or series", "per unit", 1., "3rd bus efficiency", "Input (optional)"]
    override_component_attrs["Link"].loc["p2"] = ["series", "MW", 0., "2nd bus output", "Output"]
    override_component_attrs["Link"].loc["p3"] = ["series", "MW", 0., "3rd bus output", "Output"]

    network = pypsa.Network(nc_file, override_component_attrs=override_component_attrs)
    pypsa.opf.network_lopf_build_model(network, formulation="kirchhoff")

    return network

def pyomo_parse_name(network, filename):
    instance = network.model
    instance.write(filename=filename, io_options={"symbolic_solver_labels": True})

def compute_IIS_gurobi(lp_file):
    """
    source: https://www.gurobi.com/documentation/9.1/examples/workforce2_py.html
    """
    model = gp.read(file_name)
    model.computeIIS()
    if model.IISMinimal:
        print('IIS is minimal\n')
    else:
        print('IIS is not minimal\n')
    print('\nThe following constraint(s) cannot be satisfied:')
    for c in model.getConstrs():
        if c.IISConstr:
            print('%s' % c.constrName)


nc_name = "my_model.nc"
file_name = "my_model.mps"
network = build_pyomo_model(nc_name)
pyomo_parse_name(network, file_name)
compute_IIS_gurobi(file_name)
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
The model prints the name of the constraints that cause the infeasibility. Then I go back to opf.py and check the parameters involved in the corresponding constraints.

Best,
Ying
Reply all
Reply to author
Forward
0 new messages