Skip to content

Commit 821288d

Browse files
committed
Document BlockData.clone
1 parent a9d673d commit 821288d

File tree

1 file changed

+77
-2
lines changed

1 file changed

+77
-2
lines changed

pyomo/core/base/block.py

+77-2
Original file line numberDiff line numberDiff line change
@@ -1243,8 +1243,83 @@ def reclassify_component_type(
12431243
self._decl_order[idx] = (obj, tmp)
12441244

12451245
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+
12481323
"""
12491324
# FYI: we used to remove all _parent() weakrefs before
12501325
# deepcopying and then restore them on the original and cloned

0 commit comments

Comments
 (0)