I am having a difficult with pyomo's params declaration. I have a np array like I declared bellow, but it appear this error: KeyError: "Index '0' is not valid for indexed component 'c'
.
model = pyo.ConcreteModel()
V = range(20)
model.V = pyo.Set(initialize = V, doc = 'Set: clients and depots', within = pyo.NonNegativeIntegers)
c = np.zeros((len(V), len(V)))
model.c = pyo.Param(V, V, initialize = c, doc = 'Param: distances', within = pyo.NonNegativeReals)
ChatGPT said that I could make this:
c_dict = {(i, j): c[i][j] for i in V for j in V}
model.c = pyo.Param(V, V, initialize=c_dict, doc='Param: distances', within=pyo.NonNegativeReals)
But I don't undestand very well why this. I already readed the documentation, but I didn't undestand why I can't declare in "initialize" key.
The core issue is that multi-indexed things in pyomo
are tuple-indexed like:
x[i, j, k, ...]
and if you have an n-dimensional array in basic python (list of lists) or n-dimensional numpy array, they are "layered" indexed (not sure if that is right term) like:
x[i][j][k]
So in your case, if you have a distance matrix in a matrix format of some kind, which is very natural, you have 2 choices: You can either convert it to a dictionary (which is tuple-indexed) or just use a helper function...something like:
import pyomo.environ as pyo
import numpy as np
model = pyo.ConcreteModel()
V = range(20)
model.V = pyo.Set(initialize = V, doc = 'Set: clients and depots', within = pyo.NonNegativeIntegers)
c = np.zeros((len(V), len(V)))
def helper(model, i, j):
# convert from layered inex to tuple-indexed...
return c[i][j]
model.c = pyo.Param(model.V, model.V, initialize = helper, doc = 'Param: distances', within = pyo.NonNegativeReals)
A couple notes...
If your distances are all zero (or if you have a sparse matrix), you can/should just use a default value in the construct to fill in the missing data or the whole thing (if all zero)
Also, you should use model.V
for the indexing sets instead of just V
. (See the changes I made in that part.)