Search code examples
outputsolverpyomo

Understanding the output of a pyomo model, number of solutions is zero?


I am using this code to create a solve a simple problem:

import pyomo.environ as pyo
from pyomo.core.expr.numeric_expr import LinearExpression

model = pyo.ConcreteModel()
model.nVars = pyo.Param(initialize=4)
model.N = pyo.RangeSet(model.nVars)
model.x = pyo.Var(model.N, within=pyo.Binary)

model.coefs = [1, 1, 3, 4]

model.linexp = LinearExpression(constant=0,
                                linear_coefs=model.coefs,
                                linear_vars=[model.x[i] for i in model.N])
def caprule(m):
    return m.linexp <= 50
model.capme = pyo.Constraint(rule=caprule)

model.obj = pyo.Objective(expr = model.linexp, sense = maximize)

results = SolverFactory('glpk', executable='/usr/bin/glpsol').solve(model)
results.write()

And this is the output:

# ==========================================================
# = Solver Results                                         =
# ==========================================================
# ----------------------------------------------------------
#   Problem Information
# ----------------------------------------------------------
Problem: 
- Name: unknown
  Lower bound: 50.0
  Upper bound: 50.0
  Number of objectives: 1
  Number of constraints: 2
  Number of variables: 5
  Number of nonzeros: 5
  Sense: maximize
# ----------------------------------------------------------
#   Solver Information
# ----------------------------------------------------------
Solver: 
- Status: ok
  Termination condition: optimal
  Statistics: 
    Branch and bound: 
      Number of bounded subproblems: 0
      Number of created subproblems: 0
  Error rc: 0
  Time: 0.09727835655212402
# ----------------------------------------------------------
#   Solution Information
# ----------------------------------------------------------
Solution: 
- number of solutions: 0
  number of solutions displayed: 0

It says the number of solutions is 0, and yet it does solve the problem:

print(list(model.x[i]() for i in model.N))

Will output this:

[1.0, 1.0, 1.0, 1.0]

Which is a correct answer to the problem. what am I missing?


Solution

  • The interface between pyomo and glpk sometimes (always?) seems to return 0 for the number of solutions. I'm assuming there is some issue with the generalized interface between the pyomo core module and the various solvers that it interfaces with. When I use glpk and cbc solvers on this, it reports the number of solutions as zero. Perhaps those solvers don't fill that data element in the generalized interface. Somebody w/ more experience in the data glob returned from the solver may know precisely. That said, the main thing to look at is the termination condition, which I've found to be always accurate. It reports optimal.

    I suspect that you have some mixed code from another model in your example. When I fix a typo or two (you missed the pyo prefix on a few things), it solves fine and gives the correct objective value as 9. I'm not sure where 50 came from in your output.

    (slightly cleaned up) Code:

    import pyomo.environ as pyo
    from pyomo.core.expr.numeric_expr import LinearExpression
    
    model = pyo.ConcreteModel()
    model.nVars = pyo.Param(initialize=4)
    model.N = pyo.RangeSet(model.nVars)
    model.x = pyo.Var(model.N, within=pyo.Binary)
    
    model.coefs = [1, 1, 3, 4]
    
    model.linexp = LinearExpression(constant=0,
                                    linear_coefs=model.coefs,
                                    linear_vars=[model.x[i] for i in model.N])
    def caprule(m):
        return m.linexp <= 50
    model.capme = pyo.Constraint(rule=caprule)
    
    model.obj = pyo.Objective(expr = model.linexp, sense = pyo.maximize)
    
    solver = pyo.SolverFactory('glpk') #, executable='/usr/bin/glpsol').solve(model)
    results = solver.solve(model)
    
    print(results)
    
    model.obj.pprint()
    model.obj.display()
    

    Output:

    Problem: 
    - Name: unknown
      Lower bound: 9.0
      Upper bound: 9.0
      Number of objectives: 1
      Number of constraints: 2
      Number of variables: 5
      Number of nonzeros: 5
      Sense: maximize
    Solver: 
    - Status: ok
      Termination condition: optimal
      Statistics: 
        Branch and bound: 
          Number of bounded subproblems: 0
          Number of created subproblems: 0
      Error rc: 0
      Time: 0.00797891616821289
    Solution: 
    - number of solutions: 0
      number of solutions displayed: 0
    
    obj : Size=1, Index=None, Active=True
        Key  : Active : Sense    : Expression
        None :   True : maximize : x[1] + x[2] + 3*x[3] + 4*x[4]
    obj : Size=1, Index=None, Active=True
        Key  : Active : Value
        None :   True :   9.0