class_docstr: Algorithm framework with 3 main functions:
  
  - :code:`ask()` which provides a candidate on which to evaluate the function to optimize.
  - :code:`tell(candidate, loss)` which lets you provide the loss associated to points.
  - :code:`provide_recommendation()` which provides the best final candidate.
  
  Typically, one would call :code:`ask()` num_workers times, evaluate the
  function on these num_workers points in parallel, update with the fitness value when the
  evaluations is finished, and iterate until the budget is over. At the very end,
  one would call provide_recommendation for the estimated optimum.
  
  This class is abstract, it provides internal equivalents for the 3 main functions,
  among which at least :code:`_internal_ask_candidate` has to be overridden.
  
  Each optimizer instance should be used only once, with the initial provided budget
  
  Parameters
  ----------
  parametrization: int or Parameter
      either the dimension of the optimization space, or its parametrization
  budget: int/None
      number of allowed evaluations
  num_workers: int
      number of evaluations which will be run in parallel at once
class_docstr_tok: ["Algorithm","framework","with","3","main","functions",":","-",":","code",":","`","ask","(",")","`","which","provides","a","candidate","on","which","to","evaluate","the","function","to","optimize",".","-",":","code",":","`","tell","(","candidate",",","loss",")","`","which","lets","you","provide","the","loss","associated","to","points",".","-",":","code",":","`","provide_recommendation","(",")","`","which","provides","the","best","final","candidate",".","Typically",",","one","would","call",":","code",":","`","ask","(",")","`","num_workers","times",",","evaluate","the","function","on","these","num_workers","points","in","parallel",",","update","with","the","fitness","value","when","the","evaluations","is","finished",",","and","iterate","until","the","budget","is","over",".","At","the","very","end",",","one","would","call","provide_recommendation","for","the","estimated","optimum",".","This","class","is","abstract",",","it","provides","internal","equivalents","for","the","3","main","functions",",","among","which","at","least",":","code",":","`","_internal_ask_candidate","`","has","to","be","overridden",".","Each","optimizer","instance","should","be","used","only","once",",","with","the","initial","provided","budget","Parameters","--","--","--","--","--","parametrization",":","int","or","Parameter","either","the","dimension","of","the","optimization","space",",","or","its","parametrization","budget",":","int\/None","number","of","allowed","evaluations","num_workers",":","int","number","of","evaluations","which","will","be","run","in","parallel","at","once"]
docstr: 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)`).
docstr_tok: ["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",")","`",")","."]
code: 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.
      self.parametrization.tabu_fails = 0
      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(self.parametrization):
              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(self.parametrization)
      if not satisfies and self.parametrization.tabu_length == 0:
          # still not solving, let's run sub-optimization
          candidate = _constraint_solver(candidate, budget=max_trials)
      if not (
          satisfies
          or candidate.satisfies_constraints(
              self.parametrization, no_tabu=True
          )
      ):
          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
  
imports: import pickle
  import warnings
  from pathlib import Path
  from numbers import Real
  from collections import deque
  import numpy
  import nevergrad.common.typing
  from nevergrad.parametrization import parameter
  from nevergrad.common import tools
  from nevergrad.common import errors
  from nevergrad.common.decorators import Registry
  from .None import utils
  from .None import multiobjective
label_desc: Use image node_id 21 for calling the Optimizer obj's underlying member method code with example usage: obj.ask() and returns: candidate