I know this is a late response, but it may be useful.
I have a model that repeatedly extends an indexing set and various components indexed over that set, and then re-solves. This is the approach I use, which works pretty well.
from pyomo.environ import *
m = AbstractModel() # or m = ConcreteModel()
m.S = Set(initialize=[1, 2])
m.p = Param(m.S, initialize={1: 1, 2: 4}, mutable=True)
m.X = Var(m.S, within=NonNegativeReals)
m.C = Constraint(m.S, rule=lambda m, s: m.X[s] >= m.p[s])
m.E = Expression(m.S, rule=lambda m, s: m.X[s] + 5)
m.objE = Expression(rule=lambda m: sum(m.E[s] for s in m.S))
m.O = Objective(rule=lambda m: m.objE, sense=minimize)
# create a model instance (usually you wouldn't bother with if...:)
if isinstance(m, AbstractModel):
i = m.create_instance()
else:
i = m
# Modify the instance
i.S.add(3)
i.p[3] = 9
i.X.reconstruct()
i.C.reconstruct()
i.E.reconstruct()
i.objE.reconstruct()
# instance is ready for solving...
i.pprint()
All the reconstruct() calls are necessary because (a) this is the only documented way to extend the indexing of each component, and (b) once you reconstruct one component (e.g., m.X), the elements of any other objects that refer to elements of that component become outdated. e.g., m.E[1] refers to a vardata object which used to be m.X[1], but is no longer part of the model. Rebuilding m.E creates a new expression object m.E[1], which refers to the new vardata object at m.X[1], and also adds m.E[3] referring to the newly added m.X[3]. But then you have to rebuild m.objE to refer to these new expression objects.
Note: you can only use reconstruct() this way for objects that have been defined via rules. If you define components (e.g. a constraint) directly via expressions, you may be able to add another term with something like i.C[3]=(m.X[3] >= m.p[3]) instead of i.C.reconstruct(), but then you will run into trouble with m.X. If you previously used m.X.reconstruct() to extend m.X, then i.C[1] will still refer to the old i.X[1] vardata object, which is no longer part of the model. So you'll have to re-create i.C[1] and i.C[2] somehow. Alternatively, you could try to find some way other than i.X.reconstruct() to extend i.X to include i.X[3] before you create i.C[3].
I'm not sure if my approach is the officially recommended way to build these kinds of models, but it seems to work pretty well. I don't use any reserved functions, and I may even have gotten advice on the reconstruct() calls from this list. But some changes in Pyomo 4.2 broke the reconstruct() function for Expressions and Objectives, so I don't think the Pyomo people consider this a mainstream technique. (Oh boy do I wish there were a way to automatically propagate changes like this through a model.)
By the way, you can work around the problem with Objective.reconstruct() by defining a single-valued Expression (as I did here) and then reconstructing that. This works because the Objective only refers to the Expression object, not any indexed sub-elements. The whole component retains its identity during reconstruct(), unlike sub-elements of indexed Expressions, which get discarded during reconstruct().
It's a little harder to work around the Expression.reconstruct() problem in Pyomo 4.2. You can either stick with 4.1, or use a patch like this sometime before you define your model:
from pyomo.environ import *
import pyomo.version
if pyomo.version.version_info >= (4, 2, 0, '', 0):
# Pyomo 4.2 mistakenly discards the original expression or rule during
# Expression.construct(). This makes it impossible to reconstruct expressions
# (e.g., for iterated models). So we patch it.
# Test whether patch is still needed:
test_model = ConcreteModel()
test_model.e = Expression(rule=lambda m: 0)
if hasattr(test_model.e, "_init_rule") and test_model.e._init_rule is None:
print "Patching incompatible version of Pyomo."
old_construct = pyomo.environ.Expression.construct
def new_construct(self, *args, **kwargs):
# save rule and expression, call the function, then restore them
_init_rule = self._init_rule
_init_expr = self._init_expr
old_construct(self, *args, **kwargs)
self._init_rule = _init_rule
self._init_expr = _init_expr
pyomo.environ.Expression.construct = new_construct
else:
print "NOTE: Pyomo no longer removes _init_rule during Expression.construct()."
print " The Pyomo patch for Expression.construct() is probably obsolete."
del test_model
I hope this helps.
Matthias