in nevergrad/optimization/base.py [0:0]
def ask(self) -> p.Parameter:
"""Provides a point to explore.
This function can be called multiple times to explore several points in parallel
Returns
-------
p.Parameter:
The candidate to try on the objective function. :code:`p.Parameter` have field :code:`args` and :code:`kwargs`
which can be directly used on the function (:code:`objective_function(*candidate.args, **candidate.kwargs)`).
"""
# call callbacks for logging etc...
for callback in self._callbacks.get("ask", []):
callback(self)
current_num_ask = self.num_ask
# tentatives if a cheap constraint is available
max_trials = max(1, self._constraints_manager.max_trials // 2)
# half will be used for sub-optimization --- if the optimization method does not need/use a budget.
# TODO(oteytaud): actually we could do this even when the budget is known, if we are sure that
# exceeding the budget is not a problem.
# Very simple constraint solver:
# - we use a simple algorithm.
# - no memory of previous iterations.
# - just projection to constraint satisfaction.
# We try using the normal tool during half constraint budget, in order to reduce the impact on the normal run.
for _ in range(max_trials):
is_suggestion = False
if self._suggestions: # use suggestions if available
is_suggestion = True
candidate = self._suggestions.pop()
else:
try: # Sometimes we have a limited budget so that
candidate = self._internal_ask_candidate()
except AssertionError as e:
assert (
self.parametrization._constraint_checkers
), f"Error: {e}" # This should not happen without constraint issues.
candidate = self.parametrization.spawn_child()
if candidate.satisfies_constraints():
break # good to go!
if self._penalize_cheap_violations or self.no_parallelization:
# Warning! This might be a tell not asked.
self._internal_tell_candidate(candidate, float("Inf")) # DE requires a tell
# updating num_ask is necessary for some algorithms which need new num to ask another point
self._num_ask += 1
satisfies = candidate.satisfies_constraints()
if not satisfies:
# still not solving, let's run sub-optimization
candidate = _constraint_solver(candidate, budget=max_trials)
if not (satisfies or candidate.satisfies_constraints()):
self._warn(
f"Could not bypass the constraint after {max_trials} tentatives, "
"sending candidate anyway.",
errors.FailedConstraintWarning,
)
if not is_suggestion:
if candidate.uid in self._asked:
raise RuntimeError(
"Cannot submit the same candidate twice: please recreate a new candidate from data.\n"
"This is to make sure that stochastic parametrizations are resampled."
)
self._asked.add(candidate.uid)
self._num_ask = current_num_ask + 1
assert (
candidate is not None
), f"{self.__class__.__name__}._internal_ask method returned None instead of a point."
# make sure to call value getter which may update the value, before we freeze the paremeter
candidate.value # pylint: disable=pointless-statement
candidate.freeze() # make sure it is not modified somewhere
return candidate