@@ -1243,8 +1243,83 @@ def reclassify_component_type(
1243
1243
self ._decl_order [idx ] = (obj , tmp )
1244
1244
1245
1245
def clone (self , memo = None ):
1246
- """
1247
- TODO
1246
+ """Make a copy of this block (and all components contained in it).
1247
+
1248
+ Pyomo models use :py:class:`Block` components to define a
1249
+ hierarchical structure and provide model scoping. When modeling
1250
+ :py:class:`~pyomo.core.base.component.Component` objects are
1251
+ assigned to a block, they are automatically added to that block's
1252
+ scope.
1253
+
1254
+ :py:meth:`clone()` implements a specialization of
1255
+ :py:func:`copy.deepcopy` that will deep copy the
1256
+ :py:class:`BlockData` using that block's scope: that is, copy
1257
+ the :py:class:`BlockData` and (recursively) all
1258
+ :py:class:`Component` objects attached to it (including any
1259
+ sub-blocks). Pyomo
1260
+ :py:class:`~pyomo.core.base.component.Component` /
1261
+ :py:class:`~pyomo.core.base.component.ComponentData` objects
1262
+ that are referenced through objects on this block but are not in
1263
+ this block scope (i.e., are not owned by this block or a
1264
+ subblock of this block) are not duplicated.
1265
+
1266
+ Parameters
1267
+ ----------
1268
+ memo : dict
1269
+ A user-defined memo dictionary. The dictionary will be
1270
+ updated by :py:meth:`clone` and :py:func:`copy.deepcopy`.
1271
+ See :py:meth:`object.__deepcopy__` for more information.
1272
+
1273
+ Examples
1274
+ --------
1275
+ Given the following model:
1276
+
1277
+ >>> m = pyo.ConcreteModel()
1278
+ >>> m.I = pyo.RangeSet(3)
1279
+ >>> m.x = pyo.Var()
1280
+ >>> m.b1 = pyo.Block()
1281
+ >>> m.b1.J = pyo.RangeSet(3)
1282
+ >>> m.b1.y = pyo.Var(domain=pyo.Reals)
1283
+ >>> m.b1.z = pyo.Var(m.I)
1284
+ >>> m.b1.c = pyo.Constraint(expr=m.x >= m.b1.y + sum(m.b1.z[:]))
1285
+ >>> m.b1.b2 = pyo.Block()
1286
+ >>> m.b1.b2.w = pyo.Var(m.b1.J)
1287
+ >>> m.b1.d = pyo.Constraint(expr=m.b1.y + sum(m.b1.b2.w[:]) == 5)
1288
+
1289
+ If we clone a block:
1290
+
1291
+ >>> i = m.b1.clone()
1292
+
1293
+ All local components are copied:
1294
+
1295
+ >>> assert m.b1 is not i
1296
+ >>> assert m.b1.J is not i.J
1297
+ >>> assert m.b1.y is not i.y
1298
+ >>> assert m.b1.z is not i.z
1299
+ >>> assert m.b1.b2 is not i.b2
1300
+ >>> assert m.b1.b2.w is not i.b2.w
1301
+
1302
+ References to local components (in this case, Sets) are copied
1303
+ and updated:
1304
+
1305
+ >>> assert m.b1.b2.w.index_set() is not i.b2.w.index_set()
1306
+
1307
+ But references to out-of-scope Sets (either global or in a
1308
+ different block scope) are preserved:
1309
+
1310
+ >>> assert m.b1.y.index_set() is i.y.index_set()
1311
+ >>> assert m.b1.z.index_set() is i.z.index_set()
1312
+ >>> assert m.b1.y.domain is i.y.domain
1313
+
1314
+ Expressions are also updated in a similar manner: the new
1315
+ expression will reference the new (copied) components for any
1316
+ components in scope, but references to out-of-scope components
1317
+ will be preserved:
1318
+
1319
+ >>> from pyomo.core.expr.compare import compare_expressions
1320
+ >>> assert compare_expressions(i.c.expr, m.x >= i.y + sum(i.z[:]))
1321
+ >>> assert compare_expressions(i.d.expr, i.y + sum(i.b2.w[:]) == 5)
1322
+
1248
1323
"""
1249
1324
# FYI: we used to remove all _parent() weakrefs before
1250
1325
# deepcopying and then restore them on the original and cloned
0 commit comments