diff --git a/nevergrad/parametrization/choice.py b/nevergrad/parametrization/choice.py index 3009f0dd5..f37cd736c 100644 --- a/nevergrad/parametrization/choice.py +++ b/nevergrad/parametrization/choice.py @@ -228,15 +228,6 @@ def mutate(self) -> None: for ind in indices: self.choices[ind].mutate() - def _internal_spawn_child(self: C) -> C: - child = self.__class__( - choices=self.choices.spawn_child(), - deterministic=self._deterministic, - repetitions=self._repetitions, - ) - child._content["weights"] = self.weights.spawn_child() - return child - class TransitionChoice(BaseChoice): """Ordered categorical parameter, choosing one of the provided choice options as a value, with continuous transitions. @@ -325,9 +316,3 @@ def mutate(self) -> None: indices = set(self.indices) for ind in indices: self.choices[ind].mutate() - - def _internal_spawn_child(self: T) -> T: - child = self.__class__(choices=self.choices.spawn_child(), repetitions=self._repetitions) - child._content["positions"] = self.positions.spawn_child() - child._content["transitions"] = self.transitions.spawn_child() - return child diff --git a/nevergrad/parametrization/core.py b/nevergrad/parametrization/core.py index edeeac2c5..623ae93c8 100644 --- a/nevergrad/parametrization/core.py +++ b/nevergrad/parametrization/core.py @@ -4,6 +4,7 @@ # LICENSE file in the root directory of this source tree. import uuid +import copy import warnings import operator import functools @@ -358,14 +359,25 @@ def spawn_child(self: P, new_value: tp.Optional[tp.Any] = None) -> P: Optionally, a new value will be set after creation """ rng = self.random_state # make sure to create one before spawning - child = self._internal_spawn_child() - child._set_random_state(rng) - child._constraint_checkers = list(self._constraint_checkers) - child._generation = self.generation + 1 - child._descriptors = self._descriptors - child._name = self._name - child.parents_uids.append(self.uid) + child = copy.copy(self) + child.uid = uuid.uuid4().hex + child._frozen = False + child._generation += 1 + child.parents_uids = [self.uid] child.heritage = dict(self.heritage) + child._treecall = self._treecall.new(child) + child._meta = {} + child.loss = None + child._losses = None + child._constraint_checkers = list(self._constraint_checkers) + attribute = self._treecall.attribute + container = getattr(child, self._treecall.attribute) + if attribute != "__dict__": # make a copy of the container if different from __dict__ + container = dict(container) if isinstance(container, dict) else list(container) + setattr(child, attribute, container) + for key, val in self._treecall._subitems(): + container[key] = val.spawn_child() + child._set_random_state(rng) if new_value is not None: child.value = new_value return child @@ -397,7 +409,6 @@ def copy(self: P) -> P: # TODO test (see former instrumentation_copy test) This is used to run multiple experiments """ child = self.spawn_child() - child._name = self._name child.random_state = None return child @@ -581,11 +592,6 @@ def sample(self: D) -> D: child.heritage["lineage"] = child.uid return child - def _internal_spawn_child(self: D) -> D: - child = self.__class__() - child._content = {k: v.spawn_child() for k, v in self._content.items()} - return child - class Dict(Container): """Dictionary-valued parameter. This Parameter can contain other Parameters, diff --git a/nevergrad/parametrization/data.py b/nevergrad/parametrization/data.py index 296990b6a..e27eb490c 100644 --- a/nevergrad/parametrization/data.py +++ b/nevergrad/parametrization/data.py @@ -341,16 +341,6 @@ def _internal_set_standardized_data( if reference.bound_transform is not None: self._value = reference.bound_transform.forward(self._value) - def _internal_spawn_child(self: D) -> D: - child = self.__class__(init=self.value) - child.parameters._content = { - k: v.spawn_child() if isinstance(v, core.Parameter) else v - for k, v in self.parameters._content.items() - } - for name in ["integer", "exponent", "bounds", "bound_transform", "full_range_sampling"]: - setattr(child, name, getattr(self, name)) - return child - def _internal_get_standardized_data(self: D, reference: D) -> np.ndarray: return reference._to_reduced_space(self._value) - reference._get_ref_data() # type: ignore @@ -388,6 +378,13 @@ def recombine(self: D, *others: D) -> None: else: raise ValueError(f'Unknown recombination "{recomb}"') + def spawn_child(self: D, new_value: tp.Optional[tp.Any] = None) -> D: + child = super().spawn_child() # dont forward the value + child._value = np.array(self._value, copy=True) + if new_value is not None: + child.value = new_value + return child + class Array(Data): @@ -428,7 +425,7 @@ class Scalar(Data): upper: optional float maximum value if any mutable_sigma: bool - whether the mutation standard deviation must mutate as well (for mutation based algorithms) + wheter the mutation standard deviation must mutate as well (for mutation based algorithms) Notes ----- diff --git a/nevergrad/parametrization/helpers.py b/nevergrad/parametrization/helpers.py index 16df4680d..a65205b08 100644 --- a/nevergrad/parametrization/helpers.py +++ b/nevergrad/parametrization/helpers.py @@ -111,6 +111,7 @@ def split_as_data_parameters( # analyze results data = copied.get_standardized_data(reference=ref) order: tp.List[int] = [] + print(data) for val, _ in itertools.groupby(data): num = int(np.round(val)) if num in order: diff --git a/nevergrad/parametrization/utils.py b/nevergrad/parametrization/utils.py index eb32dc3e7..56b1bb4ba 100644 --- a/nevergrad/parametrization/utils.py +++ b/nevergrad/parametrization/utils.py @@ -232,6 +232,9 @@ def __init__(self, obj: tp.Any, cls: tp.Type[tp.Any], attribute: str = "__dict__ self.cls = cls self.attribute = attribute + def new(self, obj: tp.Any) -> "Treecall": + return Treecall(obj, cls=self.cls, attribute=self.attribute) + def _subitems(self) -> tp.Iterator[tp.Tuple[tp.Any, tp.Any]]: container = getattr(self.obj, self.attribute) if not isinstance(container, (list, dict)):