You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/howto.rst
+53Lines changed: 53 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -167,6 +167,59 @@ The ``RandObj`` class accepts an instance of the ``random.Random`` class in its
167
167
# Using a different seed produces different results.
168
168
my_function(1, "third call:")
169
169
170
+
Copying and repeatability
171
+
_________________________
172
+
173
+
``RandObj`` supports Python's ``copy.deepcopy``. However, there is a caveat that users should be aware of.
174
+
175
+
A ``RandObj`` that is seeded with the object-based approach above is guaranteed to be repeatable from the point where it is copied.
176
+
177
+
E.g. the following code will run fine with no assertion error:
178
+
179
+
.. code-block:: python
180
+
181
+
import copy
182
+
import random
183
+
184
+
from constrainedrandom import RandObj
185
+
186
+
randobj = RandObj(random.Random(0))
187
+
randobj.add_rand_var('x', domain=range(100))
188
+
randobj_copy = copy.deepcopy(randobj)
189
+
randobj.randomize()
190
+
randobj_copy.randomize()
191
+
# The results of both will be the same.
192
+
assert randobj.get_results() == randobj_copy.get_results(), "this should be true!"
193
+
194
+
However, a ``RandObj`` that is globally seeded is not suitable to be deep copied. A strange interaction between ``deepcopy`` and ``functools.partial`` that depend on the globally-scoped ``random`` module means that state is unintentionally shared between the original ``RandObj`` and its copy.
195
+
196
+
E.g. the following code will *NOT* give reproducible results between the original object and its copy.
197
+
198
+
.. code-block:: python
199
+
200
+
import copy
201
+
import random
202
+
203
+
from constrainedrandom import RandObj
204
+
205
+
random.seed(0)
206
+
randobj = RandObj()
207
+
randobj.add_rand_var('x', domain=range(100))
208
+
# Take a copy
209
+
randobj_copy = copy.deepcopy(randobj)
210
+
randobj.randomize()
211
+
# re-seed global random to try to make it reproducible
212
+
random.seed(0)
213
+
randobj_copy.randomize()
214
+
# The following will fail for many RandObj instances:
215
+
assert randobj.get_results() == randobj_copy.get_results(), "this will fail!"
216
+
217
+
There is another issue where constraints added to the original may affect the copy, and vice versa. This is obviously not a good thing.
218
+
219
+
Therefore, **the user is recommended not to use ``copy.deepcopy`` with globally-seeded instances of ``RandObj``**.
220
+
221
+
To fix this issue, ``RandObj`` would need to implement its own ``__deepcopy__`` method. This can be done as and when this behaviour is required by users and the workaround of using object-based seeding is not acceptable.
0 commit comments