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"]
code: def __init__(
      self,
      parametrization: IntOrParameter,
      budget: tp.Optional[int] = None,
      num_workers: int = 1,
  ) -> None:
      if self.no_parallelization and num_workers > 1:
          raise ValueError(
              f"{self.__class__.__name__} does not support parallelization"
          )
      # "seedable" random state: externally setting the seed will provide deterministic behavior
      # you can also replace or reinitialize this random state
      self.num_workers = int(num_workers)
      self.budget = budget
      self.optim_curve: tp.List[tp.Any] = []
  
      # How do we deal with cheap constraints i.e. constraints which are fast and use low resources and easy ?
      # True ==> we penalize them (infinite values for candidates which violate the constraint).
      # False ==> we repeat the ask until we solve the problem.
      self._constraints_manager = utils.ConstraintManager()
      self._penalize_cheap_violations = False
  
      self.parametrization = (
          parametrization
          if not isinstance(parametrization, (int, np.int_))
          else p.Array(shape=(parametrization,))
      )
      self.parametrization.freeze()  # avoids issues!
      if not self.dimension:
          raise ValueError(
              "No variable to optimize in this parametrization."
          )
      self.name = self.__class__.__name__  # printed name in repr
      # keep a record of evaluations, and current bests which are updated at each new evaluation
      self.archive: utils.Archive[
          utils.MultiValue
      ] = (
          utils.Archive()
      )  # dict like structure taking np.ndarray as keys and Value as values
      self.current_bests = {
          x: utils.MultiValue(
              self.parametrization,
              np.inf,
              reference=self.parametrization,
          )
          for x in ["optimistic", "pessimistic", "average", "minimum"]
      }
      # pruning function, called at each "tell"
      # this can be desactivated or modified by each implementation
      self.pruning: tp.Optional[
          _PruningCallable
      ] = utils.Pruning.sensible_default(
          num_workers=num_workers,
          dimension=self.parametrization.dimension,
      )
      # multiobjective
      self._MULTIOBJECTIVE_AUTO_BOUND = mobj.AUTO_BOUND
      self._hypervolume_pareto: tp.Optional[
          mobj.HypervolumePareto
      ] = None
      # instance state
      self._asked: tp.Set[str] = set()
      self._num_objectives = 0
      self._suggestions: tp.Deque[p.Parameter] = deque()
      self._num_ask = 0
      self._num_tell = 0  # increases after each successful tell
      self._num_tell_not_asked = 0
      self._callbacks: tp.Dict[str, tp.List[tp.Any]] = {}
      # to make optimize function stoppable halway through
      self._running_jobs: tp.List[
          tp.Tuple[p.Parameter, tp.JobLike[tp.Loss]]
      ] = []
      self._finished_jobs: tp.Deque[
          tp.Tuple[p.Parameter, tp.JobLike[tp.Loss]]
      ] = deque()
      self._sent_warnings: tp.Set[
          tp.Any
      ] = set()  # no use printing several time the same
      # Most optimizers are designed for single objective and use a float loss.
      # To use these in a multi-objective optimization, we provide the negative of
      # the hypervolume of the pareto front as the loss.
      # If not needed, an optimizer can set this to True.
      self._no_hypervolume = False
  
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 1 to create a new Optimizer object  with example: obj = Optimizer(parametrization, budget, num_workers)