Search code examples
linear-programmingpyomo

Pyomo: Implicit conversion of Pyomo numeric value to float is disabled


I am trying to run an optimization model with Pyomo. To build the constraints, it is necessary complext formulation using the decision variable. I am getting the error below.

"Implicit conversion of Pyomo numeric value (730.0*Vol_CT1) to float is disabled. This error is often the result of using Pyomo components as arguments to one of the Python built-in math module functions when defining expressions. Avoid this error by using Pyomo-provided math functions or explicitly resolving the numeric value using the Pyomo value() function."

How to solve this problem?

!pip install -q pyomo
!apt-get install -y -qq glpk-utils

import numpy as np
import pyomo.environ as pyo
from pyomo.environ import *
from pyomo.opt import SolverFactory


# Input data


Consumo_MWm = [3.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000,
               1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000]


PLD = [100.00, 100.00, 100.00, 100.00, 100.00, 100.00, 100.00, 100.00, 100.00, 100.00, 100.00, 100.00, 
       100.00, 100.00, 100.00, 100.00, 100.00, 100.00, 100.00, 100.00, 100.00, 100.00, 100.00, 100.00]


Horas = [730., 730., 730., 730., 730., 730., 730., 730., 730., 730., 730., 730., 
         730., 730., 730., 730., 730., 730., 730., 730., 730., 730., 730., 730.]


# Contrato 1
Inic_vig_CT1 = 1
Fim_vig_CT1 = 12
Preço_CT1 = 200.00

# Contrato 2
Inic_vig_CT2 = 13
Fim_vig_CT2 = 24
Preço_CT2 = 200.00

# Contrato 3
Inic_vig_CT3 = 1
Fim_vig_CT3 = 24
Preço_CT3 = 200.00


# Transformation for np.array

Consumo_MWm = np.array(Consumo_MWm)
PLD = np.array(PLD)
Horas = np.array(Horas)


# Previous Calculation 

Consumo_MWh = Consumo_MWm * Horas


# Creating a model

model = pyo.ConcreteModel()



# Declaring variables

model.Vol_CT1 = pyo.Var(domain=NonNegativeReals) # Volume do Contrato 1 em MWm
model.Vol_CT2 = pyo.Var(domain=NonNegativeReals) # Volume do Contrato 2 em MWm
model.Vol_CT3 = pyo.Var(domain=NonNegativeReals) # Volume do Contrato 3 em MWm



# Making variables use easier

Vol_CT1 = model.Vol_CT1
Vol_CT2 = model.Vol_CT2
Vol_CT3 = model.Vol_CT3



# Constraints

Vol_CT1_MWh = np.zeros(24)
for i in range(24):
    if i + 1 >= Inic_vig_CT1 and i + 1 <= Fim_vig_CT1:
        Vol_CT1_MWh[i] = Vol_CT1 * Horas[i]
Custo_CT1 = Vol_CT1_MWh * PLD

Vol_CT2_MWh = np.zeros(24)
for i in range(24):
    if i + 1 >= Inic_vig_CT2 and i + 1 <= Fim_vig_CT2:
        Vol_CT2_MWh[i] = Vol_CT2 * Horas[i]
Custo_CT2 = Vol_CT2_MWh * PLD

Vol_CT3_MWh = np.zeros(24)
for i in range(24):
    if i + 1 >= Inic_vig_CT3 and i + 1 <= Fim_vig_CT3:
        Vol_CT3_MWh[i] = Vol_CT3 * Horas[i]
Custo_CT3 = Vol_CT3_MWh * PLD

Custo_CT_ALL = sum(Custo_CT1) + sum(Custo_CT2) + sum(Custo_CT3)

Volume_MCP_MWh = Consumo_MWh - Vol_CT1_MWh - Vol_CT2_MWh - Vol_CT3_MWh

Custo_MCP = Volume_MCP_MWh * PLD



# Defining objective function

model.obj = pyo.Objective(expr= Custo_CT_ALL + Custo_MCP, sense=minimize)
model.pprint()
print('=======================================================')


# Solving

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



# Results presentation


Vol_CT1_value = pyo.value(Vol_CT1)
Vol_CT2_value = pyo.value(Vol_CT2)
Vol_CT3_value = pyo.value(Vol_CT3)


print('=======================================================')

print('Volume Contrato 1 = ', Vol_CT1_value)
print('Volume Contrato 2 = ', Vol_CT2_value)
print('Volume Contrato 3 = ', Vol_CT3_value)



Solution

  • The problem is the line:

    Vol_CT1_MWh[i] = Vol_CT1 * Horas[i]
    

    You are declaring Vol_CT1_MWh as a NumPy array with dtype=float64. When you assign things to the NumPy array, NumPy will attempt to convert the value into the dtype (in this case by casting the Pyomo expression Vol_CT1 * Horas[i] to a float, thereby triggering the error).

    Remember that algebraic modeling languages (like Pyomo) construct expression trees to represent the objective and constraints. A better approach is to not use intermediate NumPy objects when constructing the expressions. For example, you could construct Custo_CT1 directly:

    Custo_CT1 = sum(
        Vol_CT1 * Horas[i] 
        for i in range(24) 
        if i + 1 >= Inic_vig_CT1 and i + 1 <= Fim_vig_CT1
    ) * PLD