TypeError for indexed Param

636 views
Skip to first unread message

Mario Krapp

unread,
Feb 9, 2016, 1:12:26 AM2/9/16
to Pyomo Forum
Hi,

I would like to evaluate a function f(x,y), which takes two iterables as arguments (e.g., a list)  for a Pyomo model (see code below). The code below returns a TypeError if I directly reference to the indexed parameters model.x and model.y as in f(model.x, model.y). If I don't use an indexed parameter and instead define each member of the index as single parameter, it works fine. To me that seems like Pyomo treats Param() objects (as well as Var() objects) differently (IndexedParam vs SimpleParam; IndexedVar vs. SimpleVar), which is inconsistent, in my opinion.

Is there a way to access promo indexed parameters that they can be used in a "pythonic way"? To be able to use features like list comprehensions, map, filter, reduce...?  

example.py
import sys, traceback
from pyomo.environ import ConcreteModel, Set, Param, Var, value

def f(x,y):
return sum([i+j for i, j in zip(x,y)])

x = [1,2]
y = [3,4]

model = ConcreteModel()

model.s = Set(initialize=['1st','2nd'])
model.x = Var(model.s,initialize={'1st': x[0], '2nd': x[1]})
model.y = Var(model.s,initialize={'1st': y[0], '2nd': y[1]})
model.x1 = Var(initialize=x[0])
model.x2 = Var(initialize=x[1])
model.y1 = Var(initialize=y[0])
model.y2 = Var(initialize=y[1])

print 'from function f(x,y): %d' %f(x,y)

print 'As Var():'
print f(model.x.values(),model.y.values())
print f([model.x1, model.x2],[model.y1, model.y2])
print f([value(model.x['1st']),value(model.x['2nd'])],[value(model.y['1st']),value(model.y['2nd'])])

print 'As Param():'

model.v = Param(model.s,initialize={'1st': x[0], '2nd': x[1]})
model.w = Param(model.s,initialize={'1st': y[0], '2nd': y[1]})
model.v1 = Param(initialize=x[0])
model.v2 = Param(initialize=x[1])
model.w1 = Param(initialize=y[0])
model.w2 = Param(initialize=y[1])
try:
print f(model.x,model.y)
except TypeError:
print 'Cannot compute f(model.x,model.y)'
exc_type, exc_value, exc_traceback = sys.exc_info()
traceback.print_exception(exc_type, exc_value, exc_traceback, file=sys.stdout)

print f(model.v.values(),model.w.values())
print f([model.v1, model.v2],[model.w1, model.w2])
print f([value(model.v['1st']),value(model.v['2nd'])],[value(model.w['1st']),value(model.w['2nd'])])
try:
print f(model.v,model.w)
except TypeError:
print 'Cannot compute f(model.x,model.y)'
exc_type, exc_value, exc_traceback = sys.exc_info()
traceback.print_exception(exc_type, exc_value, exc_traceback, file=sys.stdout)

Output:
from function f(x,y): 10
As Var():
x[2nd] + y[2nd] + x[1st] + y[1st]
x1 + y1 + x2 + y2
10
As Param():
Cannot compute f(model.x,model.y)
Traceback (most recent call last):
  File "example.py", line 36, in <module>
    print f(model.x,model.y)
  File "example.py", line 5, in f
    return sum([i+j for i, j in zip(x,y)])
TypeError: unsupported operand type(s) for +: 'int' and 'str'
10
10
10
Cannot compute f(model.x,model.y)
Traceback (most recent call last):
  File "example.py", line 46, in <module>
    print f(model.v,model.w)
  File "example.py", line 5, in f
    return sum([i+j for i, j in zip(x,y)])
TypeError: unsupported operand type(s) for +: 'int' and 'str'

Gabriel Hackebeil

unread,
Feb 9, 2016, 12:08:18 PM2/9/16
to Pyomo Forum
The interface for Pyomo components is somewhat like a dict. The __iter__ method returns an iterator over the keys (the index), not the values. You can reproduce this error with pure python objects:

>>> d = {}
>>> d[‘a’] = 1
>>> d[‘b’] = 2
>>> sum(d)
Traceback (most recent call last):
  File "jjjjj.py", line 23, in <module>
    sum(d)

TypeError: unsupported operand type(s) for +: 'int' and 'str'

This error makes sense because the __iter__ method for a dict returns [‘a’, ‘b’], and the sum method tries to add the implicit zero it starts out with to ‘a’.

Note that singleton objects (Var(), Param(), etc.) retain this same interface. Their implicit index set is always set([None]). 

Is there a way to access promo indexed parameters that they can be used in a "pythonic way"? To be able to use features like list comprehensions, map, filter, reduce...?  

So I guess the answer to this is to call values() when you want to use components in this way.

I would like to evaluate a function f(x,y), which takes two iterables as arguments (e.g., a list)  for a Pyomo model (see code below). The code below returns a TypeError if I directly reference to the indexed parameters model.x and model.y as in f(model.x, model.y). If I don't use an indexed parameter and instead define each member of the index as single parameter, it works fine. To me that seems like Pyomo treats Param() objects (as well as Var() objects) differently (IndexedParam vs SimpleParam; IndexedVar vs. SimpleVar), which is inconsistent, in my opinion.

I agree that there is some inconsistency here. It can be difficult to figure out what kind of interface to expect because we currently take some shortcuts to speed up certain operations, and the behavior is not the same across the different component types.

The difference in behavior you see with IndexedParam vs SimpleParam is that we return the value (a number) rather than a Param object when you access a particular index of an IndexedParam (to save memory and speed up expression generation). If you add the keyword 'mutable=True' to the argument list when you create an IndexedParam, it switches this behavior to look like Var, and allows you to update the value of that Param at a later time (thereby updating any expressions where it is referenced). Note this behavior is not duplicated with SimpleParam, because there is no way to not return the original Param object (because you don’t call __getitem__ when using it in an expression).

Gabe

--
You received this message because you are subscribed to the Google Groups "Pyomo Forum" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-forum...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages