Search code examples
nonetypepyomo

Why cannot I convert from 'Nonetype' to float?


I am trying to save the solutions of this optimization problem but they are Nonetype. Therefore I want to convert them to float but I get this error:

float() argument must be a string or a number, not 'NoneType'

It is rare due to in the printed solution from results.write() x1 is 6.57142857142857.

from coopr . pyomo import *
from pyomo.opt import SolverFactory

def create_model(N=[], M=[], c={}, a={}, b={}):
    model = ConcreteModel()
    model.x = Var(N, within=NonNegativeReals)
    model.obj = Objective(expr=sum(c[i]*model.x[i] for i in N))
    def con_rule(model, m):
        return sum(a[i,m]*model.x[i] for i in N) >= b[m]
    model.con = Constraint(M, rule=con_rule)
    return model
model = create_model(N = [1,2], M = [1,2], c = {1:1, 2:2},
a = {(1,1):5, (2,1):4, (1,2):7, (2,2):3},
b = {1:11, 2:46})

#model.pprint()

instance = model.create()
#instance.pprint()
opt = SolverFactory("glpk")
results = opt.solve(instance, load_solutions=False)
results.write()

x_1=float( model.x[1].value)
#x_2=float( model.x[2].value or 0)

Solution

  • First, model.create() is deprecated on the most recent version of Pyomo. I believe it is now renamed to model.create_instance.

    Second, you are solving the instance object returned from model.create(), which is a different object from model. Therefore, you should be accessing the .value attribute of variables on the instance object and not the model object.

    Third, you are starting from a ConcreteModel, which means there is no need to call model.create() (or model.create_instance()). This is simply creating an unnecessary copy of what is already a "concrete instance". I.e., you could send the model object to the solver and the code accessing .value would work as is.

    The create_instance method is only necessary when you start from an AbstractModel, where you then typically pass the name of some .dat file to it.