3
$\begingroup$

I have a Pyomo model with many constraints and variables. When solving it with Gurobi, I get the message "Model is infeasible or unbounded". Now I would like to find out which constraints cause the problem. Here in this question Finding out reason of Pyomo model infeasibility there is an advice to use the following command

log_infeasible_constraints(model)

The problem with this approach is that it just prints out every single value of a variable that causes problems. As I have quite many variables the printed out information is too large for the console of Spyder. So basically I have 2 questions:

  1. Can I print out the information from the log into a txt file? I tried the following but I get an error message:
file = open("Log.txt", "w") 
file.write(log_infeasible_constraints(model)) 
file.close()

--> TypeError: write() argument must be str, not None

  1. Is there another approach for finding out what is causing the problem in Pyomo? Can I somehow see the values of all variables at the time the infeasibility or unboundedness is found out?

Reminder: Does anyone have an idea how I can get more precise information about the error? Especially seeing the values of the variables would be quite helpful. Any idea?

$\endgroup$
2
  • $\begingroup$ Use "model.write(filename="your_model_name.lp",io_options={"symbolic_solver_labels":True})" and debugging on created lp file you can find problems. $\endgroup$ – kur ag Apr 23 at 11:04
  • 1
    $\begingroup$ This is not Pyomo specific, but it explains very well how to achieve what you want, whatever modeler or solver you are using. $\endgroup$ – Kuifje Apr 26 at 7:36
3
+50
$\begingroup$

You can find out which constraints cause the infeasibility by the following code. For details look at here:

log_infeasible_constraints(m)

$m$ is your model's name. In the provided link, you can find details of how the infeasible constraints log in Pyomo. The output of the provided code is a dictionary with constraint name, constraint's body value, constraint's lower bound, etc. These values can be obtained individually as well. Instead of write, I suggest using print to see what the output is.

UPDATE: The following is an MWE for your question:

from pyomo.environ import Param, ConcreteModel, Var, Objective, ConstraintList, value, minimize
from pyomo.opt import SolverFactory
from pyomo.util.infeasible import log_infeasible_constraints
import logging

m = ConcreteModel()
m.LE = set([1, 2, 3])
m.x = Var(m.LE, initialize=0)
m.M = Param(initialize=1000000)

def obj_rule(m):
        return sum(m.x[i] * 1 for i in m.LE)

m.z = Objective(rule=obj_rule, sense=minimize)
m.cons1 = ConstraintList()

for i in m.LE:
    m.cons1.add(10**2 * m.x[i] >= m.M)
    m.cons1.add(10**2 * m.x[i] <= -3)

solver = SolverFactory('glpk')
solution = solver.solve(m, tee=False)
log_infeasible_constraints(m, log_expression=True, log_variables=True)
logging.basicConfig(filename='example.log', encoding='utf-8', level=logging.INFO)
print(value(m.z))

And the example.log is the generated .txt file which includes the following data:

INFO:pyomo.util.infeasible:CONSTR cons1[1]: 1000000.0 </= 0
  - EXPR: 1000000.0 </= 100*x[1]
  - VAR x[1]: 0
INFO:pyomo.util.infeasible:CONSTR cons1[2]: 0 </= -3.0
  - EXPR: 100*x[1] </= -3.0
  - VAR x[1]: 0
INFO:pyomo.util.infeasible:CONSTR cons1[3]: 1000000.0 </= 0
  - EXPR: 1000000.0 </= 100*x[2]
  - VAR x[2]: 0
INFO:pyomo.util.infeasible:CONSTR cons1[4]: 0 </= -3.0
  - EXPR: 100*x[2] </= -3.0
  - VAR x[2]: 0
INFO:pyomo.util.infeasible:CONSTR cons1[5]: 1000000.0 </= 0
  - EXPR: 1000000.0 </= 100*x[3]
  - VAR x[3]: 0
INFO:pyomo.util.infeasible:CONSTR cons1[6]: 0 </= -3.0
  - EXPR: 100*x[3] </= -3.0
  - VAR x[3]: 0

example.log is generated in the same location that you run your code (same folder).

$\endgroup$
20
  • $\begingroup$ Thanks Oguz for your answer. Your posted solution is exactly what I was also using and what is mentioned in my question. And the 2 mentioned problems still persist (as it is exactly the same code). 1) I can't print it into a file and the console itself it soo small to see the whole message. 2) This approach is quite imprecise as it just reports every single value of a not valid constraint for every set which leads to an error for every value of a variable. Is there no better way of finding out what the problematic constraint or variables are? $\endgroup$ – PeterBe Apr 14 at 16:21
  • $\begingroup$ By the way: Using print did not change anything. When using it for the console, the output is still too big sucht that it does not fit into the console. When using together with the file file.print(log_infeasible_constraints(model)) I get an error AttributeError: '_io.TextIOWrapper' object has no attribute 'print' $\endgroup$ – PeterBe Apr 14 at 16:23
  • $\begingroup$ Thanks Oguz for your answer. Any comments to my last comments? Where can I see the dictionary you mentioned with the constraints? I'd highly appreciate every further comment from you. $\endgroup$ – PeterBe Apr 15 at 7:40
  • $\begingroup$ Any comments on my last comments? $\endgroup$ – PeterBe Apr 16 at 6:28
  • 1
    $\begingroup$ @PeterBe, one possible way would be scaling your problem as small as possible and trying to solve it and find out how you can fix it. As a second stuff, the IIS information might be tighter and helpful. Also, referred to the mentioned link by Kuifje. $\endgroup$ – A.Omidi Apr 27 at 7:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.