text: #!/usr/bin/env python
  # -*- coding: utf-8 -*-
  
  """BBOB noiseless testbed.
  
  The optimisation test functions are represented as classes `F1` to
  `F24` (and `F101` to `F130`).
  
  This module implements the class :py:class:`BBOBFunction` and
  sub-classes:
  
  * :py:class:`BBOBNfreeFunction` which have all the methods common to the
    classes :py:class:`F1` to :py:class:`F24`
  * :py:class:`BBOBGaussFunction`, :py:class:`BBOBCauchyFunction`,
    :py:class:`BBOBUniformFunction` which have methods in classes from
    :py:class:`F101` to :py:class:`F130`
  
  Module attributes:
  
  * :py:data:`dictbbob` is a dictionary such that dictbbob[2] contains
    the test function class F2 and f2 = dictbbob[2]() returns
    the instance 0 of the test function that can be
    called as f2([1,2,3]).
  * :py:data:`nfreeIDs` == range(1,25) indices for the noiseless functions that can be
    found in dictbbob
  * :py:data:`noisyIDs` == range(101, 131) indices for the noisy functions that can be
    found in dictbbob. We have nfreeIDs + noisyIDs == sorted(dictbbob.keys())
  * :py:data:`nfreeinfos` function infos
  
  Examples:
  
  >>> import bbobbenchmarks as bn
  >>> for s in bn.nfreeinfos:
  ...    print s
  1: Noise-free Sphere function
  2: Separable ellipsoid with monotone transformation
  <BLANKLINE>
      Parameter: condition number (default 1e6)
  <BLANKLINE>
  <BLANKLINE>
  3: Rastrigin with monotone transformation separable "condition" 10
  4: skew Rastrigin-Bueche, condition 10, skew-"condition" 100
  5: Linear slope
  6: Attractive sector function
  7: Step-ellipsoid, condition 100, noise-free
  8: Rosenbrock noise-free
  9: Rosenbrock, rotated
  10: Ellipsoid with monotone transformation, condition 1e6
  11: Discus (tablet) with monotone transformation, condition 1e6
  12: Bent cigar with asymmetric space distortion, condition 1e6
  13: Sharp ridge
  14: Sum of different powers, between x^2 and x^6, noise-free
  15: Rastrigin with asymmetric non-linear distortion, "condition" 10
  16: Weierstrass, condition 100
  17: Schaffers F7 with asymmetric non-linear transformation, condition 10
  18: Schaffers F7 with asymmetric non-linear transformation, condition 1000
  19: F8F2 sum of Griewank-Rosenbrock 2-D blocks, noise-free
  20: Schwefel with tridiagonal variable transformation
  21: Gallagher with 101 Gaussian peaks, condition up to 1000, one global rotation, noise-free
  22: Gallagher with 21 Gaussian peaks, condition up to 1000, one global rotation
  23: Katsuura function
  24: Lunacek bi-Rastrigin, condition 100
  <BLANKLINE>
      in PPSN 2008, Rastrigin part rotated and scaled
  <BLANKLINE>
  <BLANKLINE>
  >>> f3 = bn.F3(13)  # instantiate instance 13 of function f3
  >>> f3([0, 1, 2]) # short-cut for f3.evaluate([0, 1, 2])
  59.87335291
  >>> print bn.instantiate(5)[1]  # returns function instance and optimal f-value
  51.53
  >>> print bn.nfreeIDs # list noise-free functions
  [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]
  >>> for i in bn.nfreeIDs: # evaluate all noiseless functions once
  ...    print bn.instantiate(i)[0]([0., 0., 0., 0.]),
  -77.27454592 6180022.82173 92.9877507529 92.9877507529 140.510117618 70877.9554128 -72.5505202195 33355.7924722 -339.94 4374717.49343 15631566.3487 4715481.0865 550.599783901 -17.2991756229 27.3633128519 -227.827833529 -24.3305918781 131.420159348 40.7103737427 6160.81782924 376.746889545 107.830426761 220.482266557 106.094767386
  
  """
  
  # TODO: define interface for this module.
  # TODO: funId is expected to be a number since it is used as rseed.
  
  import warnings
  from pdb import set_trace
  import numpy as np
  from math import floor as floor
  from numpy import dot, linspace, diag, tile, zeros, sign, resize
  from numpy.random import standard_normal as _randn  # TODO: may bring confusion
  from numpy.random import random as _rand  # TODO: may bring confusion
  
  """
  % VAL = BENCHMARKS(X, FUNCID)
  % VAL = BENCHMARKS(X, STRFUNC)
  %    Input:
  %       X -- solution column vector or matrix of column vectors
  %       FUNCID -- number of function to be executed with X as input,
  %                 by default 8.
  %       STRFUNC -- function as string to be executed with X as input
  %    Output: function value(s) of solution(s)
  %    Examples:
  %      F = BENCHMARKS([1 2 3]', 17);
  %      F = BENCHMARKS([1 2 3]', 'f1');
  %
  % NBS = BENCHMARKS()
  % NBS = BENCHMARKS('FunctionIndices')
  %    Output:
  %      NBS -- array of valid benchmark function numbers,
  %             presumably 1:24
  %
  % FHS = BENCHMARKS('handles')
  %    Output:
  %      FHS -- cell array of function handles
  %    Examples:
  %      FHS = BENCHMARKS('handles');
  %      f = FHS{1}(x);  % evaluates x on the sphere function f1
  %      f = feval(FHS{1}, x);  % ditto
  %
  % see also: functions FGENERIC, BENCHMARKINFOS, BENCHMARKSNOISY
  
  % Authors (copyright 2009): Nikolaus Hansen, Raymond Ros, Steffen Finck
  %    Version = 'Revision: $Revision: 1115 $'
  %    Last Modified: $Date: 2009-02-09 19:22:42 +0100 (Mon, 09 Feb 2009) $
  
  % INTERFACE OF BENCHMARK FUNCTIONS
  % FHS = BENCHMARKS('handles');
  % FUNC = FHS{1};
  %
  % [FVALUE, FTRUE] = FUNC(X)
  % [FVALUE, FTRUE] = FUNC(X, [], IINSTANCE)
  %   Input: X -- matrix of column vectors
  %          IINSTANCE -- instance number of the function, sets function
  %             instance (XOPT, FOPT, rotation matrices,...)
  %             up until a new number is set, or the function is
  %             cleared. Default is zero.
  %   Output: row vectors with function value for each input column
  %     FVALUE -- function value
  %     FTRUE -- noise-less, deterministic function value
  % [FOPT STRFUNCTION] = FUNC('any_even_empty_string', ...)
  %   Output:
  %     FOPT -- function value at optimum
  %     STRFUNCTION -- not yet implemented: function description string, ID before first whitespace
  % [FOPT STRFUNCTION] = FUNC('any_even_empty_string', DIM, NTRIAL)
  %   Sets rotation matrices and xopt depending on NTRIAL (by changing the random seed).
  %   Output:
  %     FOPT -- function value at optimum
  %     STRFUNCTION -- not yet implemented: function description string, ID before first whitespace
  % [FOPT, XOPT] = FUNC('xopt', DIM)
  %   Output:
  %     FOPT -- function value at optimum XOPT
  %     XOPT -- optimal solution vector in DIM-D
  % [FOPT, MATRIX] = FUNC('linearTF', DIM)  % might vanish in future
  %   Output:
  %     FOPT -- function value at optimum XOPT
  %     MATRIX -- used transformation matrix
  
  """
  
  ### FUNCTION DEFINITION ###
  
  
  def compute_xopt(rseed, dim):
      """Generate a random vector used as optimum argument.
  
      Rounded by four digits, but never to zero.
  
      """
      xopt = 8 * np.floor(1e4 * unif(dim, rseed)) / 1e4 - 4
      idx = xopt == 0
      xopt[idx] = -1e-5
      return xopt
  
  
  def compute_rotation(seed, dim):
      """Returns an orthogonal basis."""
  
      B = np.reshape(gauss(dim * dim, seed), (dim, dim))
      for i in range(dim):
          for j in range(0, i):
              B[i] = B[i] - dot(B[i], B[j]) * B[j]
          B[i] = B[i] / (np.sum(B[i] ** 2) ** 0.5)
      return B
  
  
  def monotoneTFosc(f):
      """Maps [-inf,inf] to [-inf,inf] with different constants
      for positive and negative part.
  
      """
      if np.isscalar(f):
          if f > 0.0:
              f = np.log(f) / 0.1
              f = np.exp(f + 0.49 * (np.sin(f) + np.sin(0.79 * f))) ** 0.1
          elif f < 0.0:
              f = np.log(-f) / 0.1
              f = -np.exp(f + 0.49 * (np.sin(0.55 * f) + np.sin(0.31 * f))) ** 0.1
          return f
      else:
          f = np.asarray(f)
          g = f.copy()
          idx = f > 0
          g[idx] = np.log(f[idx]) / 0.1
          g[idx] = np.exp(g[idx] + 0.49 * (np.sin(g[idx]) + np.sin(0.79 * g[idx]))) ** 0.1
          idx = f < 0
          g[idx] = np.log(-f[idx]) / 0.1
          g[idx] = -np.exp(g[idx] + 0.49 * (np.sin(0.55 * g[idx]) + np.sin(0.31 * g[idx]))) ** 0.1
          return g
  
  
  def defaultboundaryhandling(x, fac):
      """Returns a float penalty for being outside of boundaries [-5, 5]"""
      xoutside = np.maximum(0.0, np.abs(x) - 5) * sign(x)
      fpen = fac * np.sum(xoutside ** 2, -1)  # penalty
      return fpen
  
  
  def gauss(N, seed):
      """Samples N standard normally distributed numbers
      being the same for a given seed
  
      """
      r = unif(2 * N, seed)
      g = np.sqrt(-2 * np.log(r[:N])) * np.cos(2 * np.pi * r[N : 2 * N])
      if np.any(g == 0.0):
          g[g == 0] = 1e-99
      return g
  
  
  def unif(N, inseed):
      """Generates N uniform numbers with starting seed."""
  
      # initialization
      inseed = np.abs(inseed)
      if inseed < 1.0:
          inseed = 1.0
  
      rgrand = 32 * [0.0]
      aktseed = inseed
      for i in range(39, -1, -1):
          tmp = floor(aktseed / 127773.0)
          aktseed = 16807.0 * (aktseed - tmp * 127773.0) - 2836.0 * tmp
          if aktseed < 0:
              aktseed = aktseed + 2147483647.0
          if i < 32:
              rgrand[i] = aktseed
      aktrand = rgrand[0]
  
      # sample numbers
      r = int(N) * [0.0]
      for i in range(int(N)):
          tmp = floor(aktseed / 127773.0)
          aktseed = 16807.0 * (aktseed - tmp * 127773.0) - 2836.0 * tmp
          if aktseed < 0:
              aktseed = aktseed + 2147483647.0
          tmp = int(floor(aktrand / 67108865.0))
          aktrand = rgrand[tmp]
          rgrand[tmp] = aktseed
          r[i] = aktrand / 2.147483647e9
      r = np.asarray(r)
      if (r == 0).any():
          warnings.warn("zero sampled(?), set to 1e-99")
          r[r == 0] = 1e-99
      return r
  
  
  # for testing and comparing to other implementations,
  #   myrand and myrandn are used only for sampling the noise
  #   Rename to myrand and myrandn to rand and randn and
  #   comment lines 24 and 25.
  
  _randomnseed = 30.0  # warning this is a global variable...
  
  
  def _myrandn(size):
      """Normal random distribution sampling.
  
      For testing and comparing purpose.
  
      """
  
      global _randomnseed
      _randomnseed = _randomnseed + 1.0
      if _randomnseed > 1e9:
          _randomnseed = 1.0
      res = np.reshape(gauss(np.prod(size), _randomnseed), size)
      return res
  
  
  _randomseed = 30.0  # warning this is a global variable...
  
  
  def _myrand(size):
      """Uniform random distribution sampling.
  
      For testing and comparing purpose.
  
      """
  
      global _randomseed
      _randomseed = _randomseed + 1
      if _randomseed > 1e9:
          _randomseed = 1
      res = np.reshape(unif(np.prod(size), _randomseed), size)
      return res
  
  
  def fGauss(ftrue, beta):
      """Returns Gaussian model noisy value."""
      # expects ftrue to be a np.array
      popsi = np.shape(ftrue)
      fval = ftrue * np.exp(beta * _randn(popsi))  # with gauss noise
      tol = 1e-8
      fval = fval + 1.01 * tol
      idx = ftrue < tol
      try:
          fval[idx] = ftrue[idx]
      except IndexError:  # fval is a scalar
          if idx:
              fval = ftrue
      return fval
  
  
  def fUniform(ftrue, alpha, beta):
      """Returns uniform model noisy value."""
      # expects ftrue to be a np.array
      popsi = np.shape(ftrue)
      fval = (
          _rand(popsi) ** beta
          * ftrue
          * np.maximum(1.0, (1e9 / (ftrue + 1e-99)) ** (alpha * _rand(popsi)))
      )
      tol = 1e-8
      fval = fval + 1.01 * tol
      idx = ftrue < tol
      try:
          fval[idx] = ftrue[idx]
      except IndexError:  # fval is a scalar
          if idx:
              fval = ftrue
      return fval
  
  
  def fCauchy(ftrue, alpha, p):
      """Returns Cauchy model noisy value
  
      Cauchy with median 1e3*alpha and with p=0.2, zero otherwise
  
      P(Cauchy > 1,10,100,1000) = 0.25, 0.032, 0.0032, 0.00032
  
      """
      # expects ftrue to be a np.array
      popsi = np.shape(ftrue)
      fval = ftrue + alpha * np.maximum(
          0.0, 1e3 + (_rand(popsi) < p) * _randn(popsi) / (np.abs(_randn(popsi)) + 1e-199)
      )
      tol = 1e-8
      fval = fval + 1.01 * tol
      idx = ftrue < tol
      try:
          fval[idx] = ftrue[idx]
      except IndexError:  # fval is a scalar
          if idx:
              fval = ftrue
      return fval
  
  
  ### CLASS DEFINITION ###
  
  
  class AbstractTestFunction(object):
      """Abstract class for test functions.
  
      Defines methods to be implemented in test functions which are to be
      provided to method setfun of class Logger.
      In particular, (a) the attribute fopt and (b) the method _evalfull.
  
      The _evalfull method returns two values, the possibly noisy value and
      the noise-free value. The latter is only meant to be for recording purpose.
  
      """
  
      def __call__(self, x):  # makes the instances callable
          """Returns the objective function value of argument x.
  
          Example:
  
              >>> import bbobbenchmarks as bn
              >>> f3 = bn.F3(13) # instantiate function 3 on instance 13
              >>> f3([0, 1, 2])  # call f3, same as f3.evaluate([0, 1, 2])
              59.87335291
  
          """
          return self.evaluate(x)
  
      def evaluate(self, x):
          """Returns the objective function value (in case noisy)."""
          return self._evalfull(x)[0]
  
      # TODO: is it better to leave evaluate out and check for hasattr('evaluate') in ExpLogger?
  
      def _evalfull(self, x):
          """return noisy and noise-free value, the latter for recording purpose."""
          raise NotImplementedError
  
      def getfopt(self):
          """Returns the best function value of this instance of the function."""
          # TODO: getfopt error:
          # import bbobbenchmarks as bb
          # bb.instantiate(1)[0].getfopt()
          # AttributeError: F1 instance has no attribute '_fopt'
  
          if not hasattr(self, "iinstance"):
              raise Exception("This function class has not been instantiated yet.")
          return self._fopt
  
      def setfopt(self, fopt):
          try:
              self._fopt = float(fopt)
          except ValueError:
              raise Exception("Optimal function value must be cast-able to a float.")
  
      fopt = property(getfopt, setfopt)
  
  
  class BBOBFunction(AbstractTestFunction):
      """Abstract class of BBOB test functions.
  
      Implements some base functions that are used by the test functions
      of BBOB such as initialisations of class attributes.
  
      """
  
      def __init__(self, iinstance=0, zerox=False, zerof=False, param=None, **kwargs):
          """Common initialisation.
  
          Keyword arguments:
          iinstance -- instance of the function (int)
          zerox -- sets xopt to [0, ..., 0]
          zerof -- sets fopt to 0
          param -- parameter of the function (if applicable)
          kwargs -- additional attributes
  
          """
          # Either self.rrseed or self.funId have to be defined for BBOBFunctions
          # TODO: enforce
          try:
              rrseed = self.rrseed
          except AttributeError:
              rrseed = self.funId
  
          try:
              self.rseed = rrseed + 1e4 * iinstance
          except TypeError:
              # rrseed AND iinstance have to be float
              warnings.warn("self.rseed could not be set, reset to 1 instead.")
              self.rseed = 1
  
          self.zerox = zerox
          if zerof:
              self.fopt = 0.0
          else:
              self.fopt = min(
                  1000,
                  max(
                      -1000,
                      (
                          np.round(100 * 100 * gauss(1, self.rseed)[0] / gauss(1, self.rseed + 1)[0])
                          / 100
                      ),
                  ),
              )
          self.iinstance = iinstance
          self.dim = None
          self.lastshape = None
          self.param = param
          for i, v in kwargs.items():
              setattr(self, i, v)
          self._xopt = None
  
      def shape_(self, x):
          # this part is common to all evaluate function
          # it is assumed x are row vectors
          curshape = np.shape(x)
          dim = np.shape(x)[-1]
          return curshape, dim
  
      def getiinstance(self):
          """Designates the instance of the function class.
  
          An instance in this case means a given target function value, a
          given optimal argument x, and given transformations for the
          function. It needs to have a string representation. Preferably
          it should be a number or a string.
  
          """
          return self._iinstance
  
      def setiinstance(self, iinstance):
          self._iinstance = iinstance
  
      iinstance = property(getiinstance, setiinstance)
  
      def shortstr(self):
          """Gives a short string self representation (shorter than str(self))."""
  
          res = "F%s" % str(self.funId)
          if hasattr(self, "param"):
              res += "_p%s" % str(self.param)  # NH param -> self.param
          return res
  
      def __eq__(self, obj):
          return self.funId == obj.funId and (not hasattr(self, "param") or self.param == obj.param)
          # TODO: make this test on other attributes than param?
  
      #    def dimensionality(self, dim):
      #        """Return the availability of dimensionality dim."""
      #        return True
  
      # GETTERS
      #    def getfopt(self):
      #        """Optimal Function Value."""
      #        return self._fopt
  
      #    fopt = property(getfopt)
  
      def _setxopt(self, xopt):
          """Return the argument of the optimum of the function."""
          self._xopt = xopt
  
      def _getxopt(self):
          """Return the argument of the optimum of the function."""
          if self._xopt is None:
              warnings.warn("You need to evaluate object to set dimension first.")
          return self._xopt
  
      xopt = property(_getxopt, _setxopt)
  
  
  #    def getrange(self):
  #        """Return the domain of the function."""
  #        #TODO: could depend on the dimension
  #        # TODO: return exception NotImplemented yet
  #        pass
  
  #    range = property(getrange)
  
  #    def getparam(self):
  #        """Optional parameter value."""
  #        return self._param
  
  #    param = property(getparam)
  
  #    def getitrial(self):
  #        """Instance id number."""
  #        return self._itrial
  
  #    itrial = property(getitrial)
  
  #    def getlinearTf(self):
  #        return self._linearTf
  
  #    linearTf = property(getlinearTf)
  
  #    def getrotation(self):
  #        return self._rotation
  
  #    rotation = property(getrotation)
  
  
  class BBOBNfreeFunction(BBOBFunction):
      """Class of the noise-free functions of BBOB."""
  
      def noise(self, ftrue):
          """Returns the noise-free function values."""
  
          return ftrue.copy()
  
  
  class BBOBGaussFunction(BBOBFunction):
      """Class of the Gauss noise functions of BBOB.
  
      Attribute gaussbeta needs to be defined by inheriting classes.
  
      """
  
      # gaussbeta = None
  
      def noise(self, ftrue):
          """Returns the noisy function values."""
  
          return fGauss(ftrue, self.gaussbeta)
  
      def boundaryhandling(self, x):
          return defaultboundaryhandling(x, 100.0)
  
  
  class BBOBUniformFunction(BBOBFunction, object):
      """Class of the uniform noise functions of BBOB.
  
      Attributes unifalphafac and unifbeta need to be defined by inheriting
      classes.
  
      """
  
      # unifalphafac = None
      # unifbeta = None
  
      def noise(self, ftrue):
          """Returns the noisy function values."""
  
          return fUniform(ftrue, self.unifalphafac * (0.49 + 1.0 / self.dim), self.unifbeta)
  
      def boundaryhandling(self, x):
          return defaultboundaryhandling(x, 100.0)
  
  
  class BBOBCauchyFunction(BBOBFunction):
      """Class of the Cauchy noise functions of BBOB.
  
      Attributes cauchyalpha and cauchyp need to be defined by inheriting
      classes.
  
      """
  
      # cauchyalpha = None
      # cauchyp = None
  
      def noise(self, ftrue):
          """Returns the noisy function values."""
  
          return fCauchy(ftrue, self.cauchyalpha, self.cauchyp)
  
      def boundaryhandling(self, x):
          return defaultboundaryhandling(x, 100.0)
  
  
  class _FSphere(BBOBFunction):
      """Abstract Sphere function.
  
      Method boundaryhandling needs to be defined.
  
      """
  
      rrseed = 1
  
      def initwithsize(self, curshape, dim):
          # DIM-dependent initialization
          if self.dim != dim:
              if self.zerox:
                  self.xopt = zeros(dim)
              else:
                  self.xopt = compute_xopt(self.rseed, dim)
  
          # DIM- and POPSI-dependent initialisations of DIM*POPSI matrices
          if self.lastshape != curshape:
              self.dim = dim
              self.lastshape = curshape
              self.arrxopt = resize(self.xopt, curshape)
  
      def _evalfull(self, x):
          fadd = self.fopt
          curshape, dim = self.shape_(x)
          # it is assumed x are row vectors
  
          if self.lastshape != curshape:
              self.initwithsize(curshape, dim)
  
          # BOUNDARY HANDLING
          fadd = fadd + self.boundaryhandling(x)
  
          # TRANSFORMATION IN SEARCH SPACE
          x = x - self.arrxopt  # cannot be replaced with x -= arrxopt!
  
          # COMPUTATION core
          ftrue = np.sum(x ** 2, -1)
          fval = self.noise(ftrue)
  
          # FINALIZE
          ftrue += fadd
          fval += fadd
          return fval, ftrue
  
  
  class F1(_FSphere, BBOBNfreeFunction):
      """Noise-free Sphere function"""
  
      funId = 1
  
      def boundaryhandling(self, x):
          return 0.0
  
  
  class F101(_FSphere, BBOBGaussFunction):
      """Sphere with moderate Gauss noise"""
  
      funId = 101
      gaussbeta = 0.01
  
  
  class F102(_FSphere, BBOBUniformFunction):
      """Sphere with moderate uniform noise"""
  
      funId = 102
      unifalphafac = 0.01
      unifbeta = 0.01
  
  
  class F103(_FSphere, BBOBCauchyFunction):
      """Sphere with moderate Cauchy noise"""
  
      funId = 103
      cauchyalpha = 0.01
      cauchyp = 0.05
  
  
  class F107(_FSphere, BBOBGaussFunction):
      """Sphere with  Gauss noise"""
  
      funId = 107
      gaussbeta = 1.0
  
  
  class F108(_FSphere, BBOBUniformFunction):
      """Sphere with uniform noise"""
  
      funId = 108
      unifalphafac = 1.0
      unifbeta = 1.0
  
  
  class F109(_FSphere, BBOBCauchyFunction):
      """Sphere with Cauchy noise"""
  
      funId = 109
      cauchyalpha = 1.0
      cauchyp = 0.2
  
  
  class F2(BBOBNfreeFunction):
      """Separable ellipsoid with monotone transformation
  
      Parameter: condition number (default 1e6)
  
      """
  
      funId = 2
      paramValues = (1e0, 1e6)
      condition = 1e6
  
      def initwithsize(self, curshape, dim):
          # DIM-dependent initialization
          if self.dim != dim:
              if self.zerox:
                  self.xopt = zeros(dim)
              else:
                  self.xopt = compute_xopt(self.rseed, dim)
              if hasattr(self, "param") and self.param:  # not self.param is None
                  tmp = self.param
              else:
                  tmp = self.condition
              self.scales = tmp ** linspace(0, 1, dim)
  
          # DIM- and POPSI-dependent initialisations of DIM*POPSI matrices
          if self.lastshape != curshape:
              self.dim = dim
              self.lastshape = curshape
              self.arrxopt = resize(self.xopt, curshape)
  
      def _evalfull(self, x):
          fadd = self.fopt
          curshape, dim = self.shape_(x)
          # it is assumed x are row vectors
  
          if self.lastshape != curshape:
              self.initwithsize(curshape, dim)
  
          # TRANSFORMATION IN SEARCH SPACE
          x = x - self.arrxopt  # cannot be replaced with x -= arrxopt!
  
          # COMPUTATION core
          ftrue = dot(monotoneTFosc(x) ** 2, self.scales)
          fval = self.noise(ftrue)  # without noise
  
          # FINALIZE
          ftrue += fadd
          fval += fadd
          return fval, ftrue
  
  
  class F3(BBOBNfreeFunction):
      """Rastrigin with monotone transformation separable "condition" 10"""
  
      funId = 3
      condition = 10.0
      beta = 0.2
  
      def initwithsize(self, curshape, dim):
          # DIM-dependent initialisation
          if self.dim != dim:
              if self.zerox:
                  self.xopt = zeros(dim)
              else:
                  self.xopt = compute_xopt(self.rseed, dim)
              self.scales = (self.condition ** 0.5) ** linspace(0, 1, dim)
  
          # DIM- and POPSI-dependent initialisations of DIM*POPSI matrices
          if self.lastshape != curshape:
              self.dim = dim
              self.lastshape = curshape
              self.arrxopt = resize(self.xopt, curshape)
              self.arrscales = resize(self.scales, curshape)
              self.arrexpo = resize(self.beta * linspace(0, 1, dim), curshape)
  
      def _evalfull(self, x):
          fadd = self.fopt
          curshape, dim = self.shape_(x)
          # it is assumed x are row vectors
  
          if self.lastshape != curshape:
              self.initwithsize(curshape, dim)
  
          # BOUNDARY HANDLING
  
          # TRANSFORMATION IN SEARCH SPACE
          x = x - self.arrxopt
          x = monotoneTFosc(x)
          idx = x > 0
          x[idx] = x[idx] ** (1 + self.arrexpo[idx] * np.sqrt(x[idx]))
          x = self.arrscales * x
  
          # COMPUTATION core
          ftrue = 10 * (self.dim - np.sum(np.cos(2 * np.pi * x), -1)) + np.sum(x ** 2, -1)
          fval = self.noise(ftrue)  # without noise
  
          # FINALIZE
          ftrue += fadd
          fval += fadd
          return fval, ftrue
  
  
  class F4(BBOBNfreeFunction):
      """skew Rastrigin-Bueche, condition 10, skew-"condition" 100"""
  
      funId = 4
      condition = 10.0
      alpha = 100.0
      maxindex = np.inf  # 1:2:min(DIM,maxindex) are the skew variables
      rrseed = 3
  
      def initwithsize(self, curshape, dim):
          # DIM-dependent initialization
          if self.dim != dim:
              if self.zerox:
                  self.xopt = zeros(dim)
              else:
                  self.xopt = compute_xopt(self.rseed, dim)
              self.xopt[: min(dim, self.maxindex) : 2] = abs(
                  self.xopt[: min(dim, self.maxindex) : 2]
              )
              self.scales = (self.condition ** 0.5) ** linspace(0, 1, dim)
  
          # DIM- and POPSI-dependent initialisations of DIM*POPSI matrices
          if self.lastshape != curshape:
              self.dim = dim
              self.lastshape = curshape
              self.arrxopt = resize(self.xopt, curshape)
              self.arrscales = resize(self.scales, curshape)
  
      def _evalfull(self, x):
          fadd = self.fopt
          curshape, dim = self.shape_(x)
          # it is assumed x are row vectors
  
          if self.lastshape != curshape:
              self.initwithsize(curshape, dim)
  
          # BOUNDARY HANDLING
          xoutside = np.maximum(0.0, np.abs(x) - 5) * sign(x)
          fpen = 1e2 * np.sum(xoutside ** 2, -1)  # penalty
          fadd = fadd + fpen  # self.fadd becomes an array
  
          # TRANSFORMATION IN SEARCH SPACE
          x = x - self.arrxopt  # shift optimum to zero
          x = monotoneTFosc(x)
          try:
              tmpx = x[:, : min(self.dim, self.maxindex) : 2]  # tmpx is a reference to a part of x
          except IndexError:
              tmpx = x[: min(self.dim, self.maxindex) : 2]  # tmpx is a reference to a part of x
          tmpx[tmpx > 0] = self.alpha ** 0.5 * tmpx[tmpx > 0]  # this modifies x
          x = self.arrscales * x  # scale while assuming that Xopt == 0
  
          # COMPUTATION core
          ftrue = 10 * (self.dim - np.sum(np.cos(2 * np.pi * x), -1)) + np.sum(x ** 2, -1)
          fval = self.noise(ftrue)
  
          # FINALIZE
          ftrue += fadd
          fval += fadd
          return fval, ftrue
  
  
  class F5(BBOBNfreeFunction):
      """Linear slope"""
  
      funId = 5
      alpha = 100.0
  
      def initwithsize(self, curshape, dim):
          # DIM-dependent initialization
          if self.dim != dim:
              if self.zerox:
                  self.xopt = zeros(dim)  # TODO: what happens here?
              else:
                  self.xopt = 5 * sign(compute_xopt(self.rseed, dim))
              self.scales = -sign(self.xopt) * (self.alpha ** 0.5) ** linspace(0, 1, dim)
  
          # DIM- and POPSI-dependent initialisations of DIM*POPSI matrices
          if self.lastshape != curshape:
              self.dim = dim
              self.lastshape = curshape
              self.arrxopt = resize(self.xopt, curshape)
  
      def _evalfull(self, x):
          fadd = self.fopt
          curshape, dim = self.shape_(x)
          # it is assumed x are row vectors
  
          if self.lastshape != curshape:
              self.initwithsize(curshape, dim)
          fadd = fadd + 5 * np.sum(np.abs(self.scales))
  
          # BOUNDARY HANDLING
          # move "too" good coordinates back into domain
          x = np.array(x)  # convert x and make a copy of x.
          # The following may modify x directly.
          idx_out_of_bounds = (x * self.arrxopt) > 25  # 25 == 5 * 5
          x[idx_out_of_bounds] = sign(x[idx_out_of_bounds]) * 5
  
          # TRANSFORMATION IN SEARCH SPACE
  
          # COMPUTATION core
          ftrue = dot(x, self.scales)
          fval = self.noise(ftrue)
  
          # FINALIZE
          ftrue += fadd
          fval += fadd
          return fval, ftrue
  
  
  class F6(BBOBNfreeFunction):
      """Attractive sector function"""
  
      funId = 6
      condition = 10.0
      alpha = 100.0
  
      def initwithsize(self, curshape, dim):
          # DIM-dependent initialization
          if self.dim != dim:
              if self.zerox:
                  self.xopt = zeros(dim)
              else:
                  self.xopt = compute_xopt(self.rseed, dim)
              self.rotation = compute_rotation(self.rseed + 1e6, dim)
              self.scales = (self.condition ** 0.5) ** linspace(0, 1, dim)
              self.linearTF = dot(compute_rotation(self.rseed, dim), diag(self.scales))
              # decouple scaling from function definition
              self.linearTF = dot(self.linearTF, self.rotation)
  
          # DIM- and POPSI-dependent initialisations of DIM*POPSI matrices
          if self.lastshape != curshape:
              self.dim = dim
              self.lastshape = curshape
              self.arrxopt = resize(self.xopt, curshape)
  
      def _evalfull(self, x):
          fadd = self.fopt
          curshape, dim = self.shape_(x)
          # it is assumed x are row vectors
  
          if self.lastshape != curshape:
              self.initwithsize(curshape, dim)
  
          # TRANSFORMATION IN SEARCH SPACE
          x = x - self.arrxopt  # cannot be replaced with x -= arrxopt!
          x = dot(x, self.linearTF)  # TODO: check
  
          # COMPUTATION core
          idx = (x * self.arrxopt) > 0
          x[idx] = self.alpha * x[idx]
          ftrue = monotoneTFosc(np.sum(x ** 2, -1)) ** 0.9
          fval = self.noise(ftrue)
  
          # FINALIZE
          ftrue += fadd
          fval += fadd
          return fval, ftrue
  
  
  class _FStepEllipsoid(BBOBFunction):
      """Abstract Step-ellipsoid, condition 100
  
      Method boundaryhandling needs to be defined.
  
      """
  
      rrseed = 7
      condition = 100.0
      alpha = 10.0
  
      def initwithsize(self, curshape, dim):
          # DIM-dependent initialization
          if self.dim != dim:
              if self.zerox:
                  self.xopt = zeros(dim)
              else:
                  self.xopt = compute_xopt(self.rseed, dim)
              self.rotation = compute_rotation(self.rseed + 1e6, dim)
              self.scales = self.condition ** linspace(0, 1, dim)
              self.linearTF = dot(
                  compute_rotation(self.rseed, dim),
                  diag(((self.condition / 10.0) ** 0.5) ** linspace(0, 1, dim)),
              )
  
          # DIM- and POPSI-dependent initialisations of DIM*POPSI matrices
          if self.lastshape != curshape:
              self.dim = dim
              self.lastshape = curshape
              self.arrxopt = resize(self.xopt, curshape)
  
      def _evalfull(self, x):
          fadd = self.fopt
          curshape, dim = self.shape_(x)
          # it is assumed x are row vectors
  
          if self.lastshape != curshape:
              self.initwithsize(curshape, dim)
  
          # BOUNDARY HANDLING
          fadd = fadd + self.boundaryhandling(x)
  
          # TRANSFORMATION IN SEARCH SPACE
          x = x - self.arrxopt  # cannot be replaced with x -= arrxopt!
          x = dot(x, self.linearTF)
          try:
              x1 = x[:, 0]
          except IndexError:
              x1 = x[0]
          idx = np.abs(x) > 0.5
          x[idx] = np.round(x[idx])
          x[~idx] = np.round(self.alpha * x[~idx]) / self.alpha
          x = dot(x, self.rotation)
  
          # COMPUTATION core
          ftrue = 0.1 * np.maximum(1e-4 * np.abs(x1), dot(x ** 2, self.scales))
          fval = self.noise(ftrue)
  
          # FINALIZE
          ftrue += fadd
          fval += fadd
          return fval, ftrue
  
  
  class F7(_FStepEllipsoid, BBOBNfreeFunction):
      """Step-ellipsoid, condition 100, noise-free"""
  
      funId = 7
  
      def boundaryhandling(self, x):
          return defaultboundaryhandling(x, 1.0)
  
  
  class F113(_FStepEllipsoid, BBOBGaussFunction):
      """Step-ellipsoid with gauss noise, condition 100"""
  
      funId = 113
      gaussbeta = 1.0
  
  
  class F114(_FStepEllipsoid, BBOBUniformFunction):
      """Step-ellipsoid with uniform noise, condition 100"""
  
      funId = 114
      unifalphafac = 1.0
      unifbeta = 1.0
  
  
  class F115(_FStepEllipsoid, BBOBCauchyFunction):
      """Step-ellipsoid with Cauchy noise, condition 100"""
  
      funId = 115
      cauchyalpha = 1.0
      cauchyp = 0.2
  
  
  class _FRosenbrock(BBOBFunction):
      """Abstract Rosenbrock, non-rotated
  
      Method boundaryhandling needs to be defined.
  
      """
  
      rrseed = 8
  
      def initwithsize(self, curshape, dim):
          # DIM-dependent initialization
          if self.dim != dim:
              if self.zerox:
                  self.xopt = zeros(dim)
              else:
                  self.xopt = 0.75 * compute_xopt(self.rseed, dim)  # different from all others
              self.scales = max(1, dim ** 0.5 / 8.0)
  
          # DIM- and POPSI-dependent initialisations of DIM*POPSI matrices
          if self.lastshape != curshape:
              self.dim = dim
              self.lastshape = curshape
              self.arrxopt = resize(self.xopt, curshape)
  
      def _evalfull(self, x):
          fadd = self.fopt
          curshape, dim = self.shape_(x)
          # it is assumed x are row vectors
  
          if self.lastshape != curshape:
              self.initwithsize(curshape, dim)
  
          # BOUNDARY HANDLING
          fadd = fadd + self.boundaryhandling(x)
  
          # TRANSFORMATION IN SEARCH SPACE
          x = x - self.arrxopt  # cannot be replaced with x -= self.arrxopt!
          x = self.scales * x
          x = x + 1  # shift zero to factual optimum 1
  
          # COMPUTATION core
          try:
              ftrue = 1e2 * np.sum((x[:, :-1] ** 2 - x[:, 1:]) ** 2, -1) + np.sum(
                  (x[:, :-1] - 1.0) ** 2, -1
              )
          except IndexError:
              ftrue = 1e2 * np.sum((x[:-1] ** 2 - x[1:]) ** 2) + np.sum((x[:-1] - 1.0) ** 2)
          fval = self.noise(ftrue)
  
          # FINALIZE
          ftrue += fadd
          fval += fadd
          return fval, ftrue
  
  
  class F8(_FRosenbrock, BBOBNfreeFunction):
      """Rosenbrock noise-free"""
  
      funId = 8
  
      def boundaryhandling(self, x):
          return 0.0
  
  
  class F104(_FRosenbrock, BBOBGaussFunction):
      """Rosenbrock non-rotated with moderate Gauss noise"""
  
      funId = 104
      gaussbeta = 0.01
  
  
  class F105(_FRosenbrock, BBOBUniformFunction):
      """Rosenbrock non-rotated with moderate uniform noise"""
  
      funId = 105
      unifalphafac = 0.01
      unifbeta = 0.01
  
  
  class F106(_FRosenbrock, BBOBCauchyFunction):
      """Rosenbrock non-rotated with moderate Cauchy noise"""
  
      funId = 106
      cauchyalpha = 0.01
      cauchyp = 0.05
  
  
  class F110(_FRosenbrock, BBOBGaussFunction):
      """Rosenbrock non-rotated with Gauss noise"""
  
      funId = 110
      gaussbeta = 1.0
  
  
  class F111(_FRosenbrock, BBOBUniformFunction):
      """Rosenbrock non-rotated with uniform noise"""
  
      funId = 111
      unifalphafac = 1.0
      unifbeta = 1.0
  
  
  class F112(_FRosenbrock, BBOBCauchyFunction):
      """Rosenbrock non-rotated with Cauchy noise"""
  
      funId = 112
      cauchyalpha = 1.0
      cauchyp = 0.2
  
  
  class F9(BBOBNfreeFunction):
      """Rosenbrock, rotated"""
  
      funId = 9
  
      def initwithsize(self, curshape, dim):
          # DIM-dependent initialization
          if self.dim != dim:
              if self.zerox:
                  self.xopt = zeros(dim)
              else:
                  self.xopt = compute_xopt(self.rseed, dim)
              scale = max(1, dim ** 0.5 / 8.0)  # nota: different from scales in F8
              self.linearTF = scale * compute_rotation(self.rseed, dim)
              self.xopt = np.hstack(dot(0.5 * np.ones((1, dim)), self.linearTF.T)) / scale ** 2
  
          # DIM- and POPSI-dependent initialisations of DIM*POPSI matrices
          if self.lastshape != curshape:
              self.dim = dim
              self.lastshape = curshape
              self.arrxopt = resize(self.xopt, curshape)
  
      def _evalfull(self, x):
          fadd = self.fopt
          curshape, dim = self.shape_(x)
          # it is assumed x are row vectors
  
          if self.lastshape != curshape:
              self.initwithsize(curshape, dim)
  
          # BOUNDARY HANDLING
  
          # TRANSFORMATION IN SEARCH SPACE
          x = dot(x, self.linearTF) + 0.5  # different from F8
  
          # COMPUTATION core
          try:
              ftrue = 1e2 * np.sum((x[:, :-1] ** 2 - x[:, 1:]) ** 2, -1) + np.sum(
                  (x[:, :-1] - 1.0) ** 2, -1
              )
          except IndexError:
              ftrue = 1e2 * np.sum((x[:-1] ** 2 - x[1:]) ** 2) + np.sum((x[:-1] - 1.0) ** 2)
          fval = self.noise(ftrue)
  
          # FINALIZE
          ftrue += fadd
          fval += fadd
          return fval, ftrue
  
  
  class _FEllipsoid(BBOBFunction):
      """Abstract Ellipsoid with monotone transformation.
  
      Method boundaryhandling needs to be defined.
  
      """
  
      rrseed = 10
      condition = 1e6
  
      def initwithsize(self, curshape, dim):
          # DIM-dependent initialization
          if self.dim != dim:
              if self.zerox:
                  self.xopt = zeros(dim)
              else:
                  self.xopt = compute_xopt(self.rseed, dim)
              self.rotation = compute_rotation(self.rseed + 1e6, dim)
              self.scales = self.condition ** linspace(0, 1, dim)
  
          # DIM- and POPSI-dependent initialisations of DIM*POPSI matrices
          if self.lastshape != curshape:
              self.dim = dim
              self.lastshape = curshape
              self.arrxopt = resize(self.xopt, curshape)
  
      def _evalfull(self, x):
          fadd = self.fopt
          curshape, dim = self.shape_(x)
          # it is assumed x are row vectors
  
          if self.lastshape != curshape:
              self.initwithsize(curshape, dim)
  
          # BOUNDARY HANDLING
          fadd = fadd + self.boundaryhandling(x)
  
          # TRANSFORMATION IN SEARCH SPACE
          x = x - self.arrxopt  # cannot be replaced with x -= arrxopt!
          x = dot(x, self.rotation)
          x = monotoneTFosc(x)
  
          # COMPUTATION core
          ftrue = dot(x ** 2, self.scales)
          try:
              ftrue = np.hstack(ftrue)
          except TypeError:  # argument 2 to map() must support iteration
              pass
          fval = self.noise(ftrue)
  
          # FINALIZE
          ftrue += fadd
          fval += fadd
          return fval, ftrue
  
  
  class F10(_FEllipsoid, BBOBNfreeFunction):
      """Ellipsoid with monotone transformation, condition 1e6"""
  
      funId = 10
      condition = 1e6
  
      def boundaryhandling(self, x):
          return 0.0
  
  
  class F116(_FEllipsoid, BBOBGaussFunction):
      """Ellipsoid with Gauss noise, monotone x-transformation, condition 1e4"""
  
      funId = 116
      condition = 1e4
      gaussbeta = 1.0
  
  
  class F117(_FEllipsoid, BBOBUniformFunction):
      """Ellipsoid with uniform noise, monotone x-transformation, condition 1e4"""
  
      funId = 117
      condition = 1e4
      unifalphafac = 1.0
      unifbeta = 1.0
  
  
  class F118(_FEllipsoid, BBOBCauchyFunction):
      """Ellipsoid with Cauchy noise, monotone x-transformation, condition 1e4"""
  
      funId = 118
      condition = 1e4
      cauchyalpha = 1.0
      cauchyp = 0.2
  
  
  class F11(BBOBNfreeFunction):
      """Discus (tablet) with monotone transformation, condition 1e6"""
  
      funId = 11
      condition = 1e6
  
      def initwithsize(self, curshape, dim):
          # DIM-dependent initialization
          if self.dim != dim:
              if self.zerox:
                  self.xopt = zeros(dim)
              else:
                  self.xopt = compute_xopt(self.rseed, dim)
              self.rotation = compute_rotation(self.rseed + 1e6, dim)
  
          # DIM- and POPSI-dependent initialisations of DIM*POPSI matrices
          if self.lastshape != curshape:
              self.dim = dim
              self.lastshape = curshape
              self.arrxopt = resize(self.xopt, curshape)
  
      def _evalfull(self, x):
          fadd = self.fopt
          curshape, dim = self.shape_(x)
          # it is assumed x are row vectors
  
          if self.lastshape != curshape:
              self.initwithsize(curshape, dim)
  
          # BOUNDARY HANDLING
  
          # TRANSFORMATION IN SEARCH SPACE
          x = x - self.arrxopt  # cannot be replaced with x -= arrxopt!
          x = dot(x, self.rotation)
          x = monotoneTFosc(x)
  
          # COMPUTATION core
          try:
              ftrue = np.sum(x ** 2, -1) + (self.condition - 1.0) * x[:, 0] ** 2
          except IndexError:
              ftrue = np.sum(x ** 2) + (self.condition - 1.0) * x[0] ** 2
          fval = self.noise(ftrue)
  
          # FINALIZE
          ftrue += fadd
          fval += fadd
          return fval, ftrue
  
  
  class F12(BBOBNfreeFunction):
      """Bent cigar with asymmetric space distortion, condition 1e6"""
  
      funId = 12
      condition = 1e6
      beta = 0.5
  
      def initwithsize(self, curshape, dim):
          # DIM-dependent initialization
          if self.dim != dim:
              if self.zerox:
                  self.xopt = zeros(dim)
              else:
                  self.xopt = compute_xopt(self.rseed + 1e6, dim)  # different from others
              self.rotation = compute_rotation(self.rseed + 1e6, dim)
  
          # DIM- and POPSI-dependent initialisations of DIM*POPSI matrices
          if self.lastshape != curshape:
              self.dim = dim
              self.lastshape = curshape
              self.arrxopt = resize(self.xopt, curshape)
              self.arrexpo = resize(self.beta * linspace(0, 1, dim), curshape)
  
      def _evalfull(self, x):
          fadd = self.fopt
          curshape, dim = self.shape_(x)
          # it is assumed x are row vectors
  
          if self.lastshape != curshape:
              self.initwithsize(curshape, dim)
  
          # BOUNDARY HANDLING
  
          # TRANSFORMATION IN SEARCH SPACE
          x = x - self.arrxopt  # cannot be replaced with x -= arrxopt!
          x = dot(x, self.rotation)  # no scaling here, because it would go to the arrExpo
          idx = x > 0
          x[idx] = x[idx] ** (1 + self.arrexpo[idx] * np.sqrt(x[idx]))
          x = dot(x, self.rotation)
  
          # COMPUTATION core
          try:
              ftrue = self.condition * np.sum(x ** 2, -1) + (1 - self.condition) * x[:, 0] ** 2
          except IndexError:
              ftrue = self.condition * np.sum(x ** 2) + (1 - self.condition) * x[0] ** 2
          fval = self.noise(ftrue)
  
          # FINALIZE
          ftrue += fadd
          fval += fadd
          return fval, ftrue
  
  
  class F13(BBOBNfreeFunction):
      """Sharp ridge"""
  
      funId = 13
      condition = 10.0
      alpha = 100.0  # slope
  
      def initwithsize(self, curshape, dim):
          # DIM-dependent initialization
          if self.dim != dim:
              if self.zerox:
                  self.xopt = zeros(dim)
              else:
                  self.xopt = compute_xopt(self.rseed, dim)
              self.rotation = compute_rotation(self.rseed + 1e6, dim)
              self.scales = (self.condition ** 0.5) ** linspace(0, 1, dim)
              self.linearTF = dot(compute_rotation(self.rseed, dim), diag(self.scales))
              self.linearTF = dot(self.linearTF, self.rotation)
  
          # DIM- and POPSI-dependent initialisations of DIM*POPSI matrices
          if self.lastshape != curshape:
              self.dim = dim
              self.lastshape = curshape
              self.arrxopt = resize(self.xopt, curshape)
  
      def _evalfull(self, x):
          fadd = self.fopt
          curshape, dim = self.shape_(x)
          # it is assumed x are row vectors
  
          if self.lastshape != curshape:
              self.initwithsize(curshape, dim)
  
          # BOUNDARY HANDLING
  
          # TRANSFORMATION IN SEARCH SPACE
          x = x - self.arrxopt  # cannot be replaced with x -= arrxopt!
          x = dot(x, self.linearTF)
  
          # COMPUTATION core
          try:
              ftrue = x[:, 0] ** 2 + self.alpha * np.sqrt(np.sum(x[:, 1:] ** 2, -1))
          except IndexError:
              ftrue = x[0] ** 2 + self.alpha * np.sqrt(np.sum(x[1:] ** 2, -1))
          fval = self.noise(ftrue)
  
          # FINALIZE
          ftrue += fadd
          fval += fadd
          return fval, ftrue
  
  
  class _FDiffPow(BBOBFunction):
      """Abstract Sum of different powers, between x^2 and x^6.
  
      Method boundaryhandling needs to be defined.
  
      """
  
      alpha = 4.0
      rrseed = 14
  
      def initwithsize(self, curshape, dim):
          # DIM-dependent initialization
          if self.dim != dim:
              if self.zerox:
                  self.xopt = zeros(dim)
              else:
                  self.xopt = compute_xopt(self.rseed, dim)
              self.rotation = compute_rotation(self.rseed + 1e6, dim)
  
          # DIM- and POPSI-dependent initialisations of DIM*POPSI matrices
          if self.lastshape != curshape:
              self.dim = dim
              self.lastshape = curshape
              self.arrxopt = resize(self.xopt, curshape)
              self.arrexpo = resize(2.0 + self.alpha * linspace(0, 1, dim), curshape)
  
      def _evalfull(self, x):
          fadd = self.fopt
          curshape, dim = self.shape_(x)
          # it is assumed x are row vectors
  
          if self.lastshape != curshape:
              self.initwithsize(curshape, dim)
  
          # BOUNDARY HANDLING
          fadd = fadd + self.boundaryhandling(x)
  
          # TRANSFORMATION IN SEARCH SPACE
          x = x - self.arrxopt  # cannot be replaced with x -= arrxopt!
          x = dot(x, self.rotation)
  
          # COMPUTATION core
          ftrue = np.sqrt(np.sum(np.abs(x) ** self.arrexpo, -1))
          fval = self.noise(ftrue)
  
          # FINALIZE
          ftrue += fadd
          fval += fadd
          return fval, ftrue
  
  
  class F14(_FDiffPow, BBOBNfreeFunction):
      """Sum of different powers, between x^2 and x^6, noise-free"""
  
      funId = 14
  
      def boundaryhandling(self, x):
          return 0.0
  
  
  class F119(_FDiffPow, BBOBGaussFunction):
      """Sum of different powers with Gauss noise, between x^2 and x^6"""
  
      funId = 119
      gaussbeta = 1.0
  
  
  class F120(_FDiffPow, BBOBUniformFunction):
      """Sum of different powers with uniform noise, between x^2 and x^6"""
  
      funId = 120
      unifalphafac = 1.0
      unifbeta = 1.0
  
  
  class F121(_FDiffPow, BBOBCauchyFunction):
      """Sum of different powers with seldom Cauchy noise, between x^2 and x^6"""
  
      funId = 121
      cauchyalpha = 1.0
      cauchyp = 0.2
  
  
  class F15(BBOBNfreeFunction):
      """Rastrigin with asymmetric non-linear distortion, "condition" 10"""
  
      funId = 15
      condition = 10.0
      beta = 0.2
  
      def initwithsize(self, curshape, dim):
          # DIM-dependent initialization
          if self.dim != dim:
              if self.zerox:
                  self.xopt = zeros(dim)
              else:
                  self.xopt = compute_xopt(self.rseed, dim)
              self.rotation = compute_rotation(self.rseed + 1e6, dim)
              self.scales = (self.condition ** 0.5) ** linspace(0, 1, dim)
              self.linearTF = dot(compute_rotation(self.rseed, dim), diag(self.scales))
              # decouple scaling from function definition
              self.linearTF = dot(self.linearTF, self.rotation)
  
          # DIM- and POPSI-dependent initialisations of DIM*POPSI matrices
          if self.lastshape != curshape:
              self.dim = dim
              self.lastshape = curshape
              self.arrxopt = resize(self.xopt, curshape)
              self.arrexpo = resize(self.beta * linspace(0, 1, dim), curshape)
  
      def _evalfull(self, x):
          fadd = self.fopt
          curshape, dim = self.shape_(x)
          # it is assumed x are row vectors
  
          if self.lastshape != curshape:
              self.initwithsize(curshape, dim)
  
          # BOUNDARY HANDLING
  
          # TRANSFORMATION IN SEARCH SPACE
          x = x - self.arrxopt  # cannot be replaced with x -= arrxopt!
          x = dot(x, self.rotation)  # no scaling here, because it would go to the arrexpo
          x = monotoneTFosc(x)
          idx = x > 0.0
          x[idx] = x[idx] ** (1.0 + self.arrexpo[idx] * np.sqrt(x[idx]))  # smooth in zero
          x = dot(x, self.linearTF)
  
          # COMPUTATION core
          ftrue = 10.0 * (dim - np.sum(np.cos(2 * np.pi * x), -1)) + np.sum(x ** 2, -1)
          fval = self.noise(ftrue)
  
          # FINALIZE
          ftrue += fadd
          fval += fadd
          return fval, ftrue
  
  
  class F16(BBOBNfreeFunction):
      """Weierstrass, condition 100"""
  
      funId = 16
      condition = 100.0
  
      def initwithsize(self, curshape, dim):
          # DIM-dependent initialization
          if self.dim != dim:
              if self.zerox:
                  self.xopt = zeros(dim)
              else:
                  self.xopt = compute_xopt(self.rseed, dim)
              self.rotation = compute_rotation(self.rseed + 1e6, dim)
              self.scales = (1.0 / self.condition ** 0.5) ** linspace(0, 1, dim)  # CAVE?
              self.linearTF = dot(compute_rotation(self.rseed, dim), diag(self.scales))
              # decouple scaling from function definition
              self.linearTF = dot(self.linearTF, self.rotation)
              K = np.arange(0, 12)
              self.aK = np.reshape(0.5 ** K, (1, 12))
              self.bK = np.reshape(3.0 ** K, (1, 12))
              self.f0 = np.sum(self.aK * np.cos(2 * np.pi * self.bK * 0.5))  # optimal value
  
          # DIM- and POPSI-dependent initialisations of DIM*POPSI matrices
          if self.lastshape != curshape:
              self.dim = dim
              self.lastshape = curshape
              self.arrxopt = resize(self.xopt, curshape)
  
      def _evalfull(self, x):
          fadd = self.fopt
          curshape, dim = self.shape_(x)
          # it is assumed x are row vectors
  
          if self.lastshape != curshape:
              self.initwithsize(curshape, dim)
  
          # BOUNDARY HANDLING
          xoutside = np.maximum(0, np.abs(x) - 5.0) * sign(x)
          fpen = (10.0 / dim) * np.sum(xoutside ** 2, -1)
          fadd = fadd + fpen
  
          # TRANSFORMATION IN SEARCH SPACE
          x = x - self.arrxopt  # cannot be replaced with x -= arrxopt!
          x = dot(x, self.rotation)
          x = monotoneTFosc(x)
          x = dot(x, self.linearTF)
  
          # COMPUTATION core
          if len(curshape) < 2:  # popsize is one
              ftrue = np.sum(
                  dot(
                      self.aK, np.cos(dot(self.bK.T, 2 * np.pi * (np.reshape(x, (1, len(x))) + 0.5)))
                  )
              )
          else:
              ftrue = np.zeros(curshape[0])  # curshape[0] is popsize
              for k, i in enumerate(x):
                  # TODO: simplify next line
                  ftrue[k] = np.sum(
                      dot(
                          self.aK,
                          np.cos(dot(self.bK.T, 2 * np.pi * (np.reshape(i, (1, len(i))) + 0.5))),
                      )
                  )
          ftrue = 10.0 * (ftrue / dim - self.f0) ** 3
          try:
              ftrue = np.hstack(ftrue)
          except TypeError:
              pass
          fval = self.noise(ftrue)
  
          # FINALIZE
          ftrue += fadd
          fval += fadd
          return fval, ftrue
  
  
  class _FSchaffersF7(BBOBFunction):
      """Abstract Schaffers F7 with asymmetric non-linear transformation, condition 10
  
      Class attribute condition and method boundaryhandling need to be defined.
  
      """
  
      rrseed = 17
      condition = None
      beta = 0.5
  
      def initwithsize(self, curshape, dim):
          # DIM-dependent initialization
          if self.dim != dim:
              if self.zerox:
                  self.xopt = zeros(dim)
              else:
                  self.xopt = compute_xopt(self.rseed, dim)
              self.rotation = compute_rotation(self.rseed + 1e6, dim)
              self.scales = (self.condition ** 0.5) ** linspace(0, 1, dim)
              self.linearTF = dot(compute_rotation(self.rseed, dim), diag(self.scales))
  
          # DIM- and POPSI-dependent initialisations of DIM*POPSI matrices
          if self.lastshape != curshape:
              self.dim = dim
              self.lastshape = curshape
              self.arrxopt = resize(self.xopt, curshape)
              self.arrexpo = resize(self.beta * linspace(0, 1, dim), curshape)
  
      def _evalfull(self, x):
          fadd = self.fopt
          curshape, dim = self.shape_(x)
          # it is assumed x are row vectors
  
          if self.lastshape != curshape:
              self.initwithsize(curshape, dim)
  
          # BOUNDARY HANDLING
          fadd = fadd + self.boundaryhandling(x)
  
          # TRANSFORMATION IN SEARCH SPACE
          x = x - self.arrxopt  # cannot be replaced with x -= arrxopt!
          x = dot(x, self.rotation)
          idx = x > 0
          x[idx] = x[idx] ** (1 + self.arrexpo[idx] * np.sqrt(x[idx]))
          x = dot(x, self.linearTF)
  
          # COMPUTATION core
          try:
              s = x[:, :-1] ** 2 + x[:, 1:] ** 2
          except IndexError:
              s = x[:-1] ** 2 + x[1:] ** 2
          ftrue = np.mean(s ** 0.25 * (np.sin(50 * s ** 0.1) ** 2 + 1), -1) ** 2
          fval = self.noise(ftrue)
  
          # FINALIZE
          ftrue += fadd
          fval += fadd
          return fval, ftrue
  
  
  class F17(_FSchaffersF7, BBOBNfreeFunction):
      """Schaffers F7 with asymmetric non-linear transformation, condition 10"""
  
      funId = 17
      condition = 10.0
  
      def boundaryhandling(self, x):
          return defaultboundaryhandling(x, 10.0)
  
  
  class F18(_FSchaffersF7, BBOBNfreeFunction):
      """Schaffers F7 with asymmetric non-linear transformation, condition 1000"""
  
      funId = 18
      condition = 1000.0
  
      def boundaryhandling(self, x):
          return defaultboundaryhandling(x, 10.0)
  
  
  class F122(_FSchaffersF7, BBOBGaussFunction):
      """Schaffers F7 with Gauss noise, with asymmetric non-linear transformation, condition 10"""
  
      funId = 122
      condition = 10.0
      gaussbeta = 1.0
  
  
  class F123(_FSchaffersF7, BBOBUniformFunction):
      """Schaffers F7 with uniform noise, asymmetric non-linear transformation, condition 10"""
  
      funId = 123
      condition = 10.0
      unifalphafac = 1.0
      unifbeta = 1.0
  
  
  class F124(_FSchaffersF7, BBOBCauchyFunction):  # TODO: check boundary handling
      """Schaffers F7 with seldom Cauchy noise, asymmetric non-linear transformation, condition 10"""
  
      funId = 124
      condition = 10.0
      cauchyalpha = 1.0
      cauchyp = 0.2
  
  
  class _F8F2(BBOBFunction):
      """Abstract F8F2 sum of Griewank-Rosenbrock 2-D blocks
  
      Class attribute facftrue and method boundaryhandling need to be defined.
  
      """
  
      facftrue = None
      rrseed = 19
  
      def initwithsize(self, curshape, dim):
          # DIM-dependent initialization
          if self.dim != dim:
              scale = max(1, dim ** 0.5 / 8.0)
              self.linearTF = scale * compute_rotation(self.rseed, dim)
              # if self.zerox:
              #    self.xopt = zeros(dim) # does not work here
              # else:
              # TODO: clean this line
              self.xopt = np.hstack(dot(self.linearTF, 0.5 * np.ones((dim, 1)) / scale ** 2))
  
          # DIM- and POPSI-dependent initialisations of DIM*POPSI matrices
          if self.lastshape != curshape:
              self.dim = dim
              self.lastshape = curshape
              self.arrxopt = resize(self.xopt, curshape)
  
      def _evalfull(self, x):
          fadd = self.fopt
          curshape, dim = self.shape_(x)
          # it is assumed x are row vectors
  
          if self.lastshape != curshape:
              self.initwithsize(curshape, dim)
  
          # BOUNDARY HANDLING
          fadd = fadd + self.boundaryhandling(x)
  
          # TRANSFORMATION IN SEARCH SPACE
          x = dot(x, self.linearTF) + 0.5  # cannot be replaced with x -= arrxopt!
  
          # COMPUTATION core
          try:
              f2 = 100.0 * (x[:, :-1] ** 2 - x[:, 1:]) ** 2 + (1.0 - x[:, :-1]) ** 2
          except IndexError:
              f2 = 100.0 * (x[:-1] ** 2 - x[1:]) ** 2 + (1.0 - x[:-1]) ** 2
          ftrue = self.facftrue + self.facftrue * np.sum(f2 / 4000.0 - np.cos(f2), -1) / (dim - 1.0)
          fval = self.noise(ftrue)
  
          # FINALIZE
          ftrue += fadd
          fval += fadd
          return fval, ftrue
  
  
  class F19(_F8F2, BBOBNfreeFunction):
      """F8F2 sum of Griewank-Rosenbrock 2-D blocks, noise-free"""
  
      funId = 19
      facftrue = 10.0
  
      def boundaryhandling(self, x):
          return 0.0
  
  
  class F125(_F8F2, BBOBGaussFunction):
      """F8F2 sum of Griewank-Rosenbrock 2-D blocks with Gauss noise"""
  
      funId = 125
      facftrue = 1.0
      gaussbeta = 1.0
  
  
  class F126(_F8F2, BBOBUniformFunction):
      """F8F2 sum of Griewank-Rosenbrock 2-D blocks with uniform noise"""
  
      funId = 126
      facftrue = 1.0
      unifalphafac = 1.0
      unifbeta = 1.0
  
  
  class F127(_F8F2, BBOBCauchyFunction):
      """F8F2 sum of Griewank-Rosenbrock 2-D blocks with seldom Cauchy noise"""
  
      funId = 127
      facftrue = 1.0
      cauchyalpha = 1.0
      cauchyp = 0.2
  
  
  class F20(BBOBNfreeFunction):
      """Schwefel with tridiagonal variable transformation"""
  
      funId = 20
      condition = 10.0
  
      def initwithsize(self, curshape, dim):
          # DIM-dependent initialization
          if self.dim != dim:
              if self.zerox:
                  self.xopt = zeros(dim)
              else:
                  self.xopt = 0.5 * sign(unif(dim, self.rseed) - 0.5) * 4.2096874633
              self.scales = (self.condition ** 0.5) ** np.linspace(0, 1, dim)
  
          # DIM- and POPSI-dependent initialisations of DIM*POPSI matrices
          if self.lastshape != curshape:
              self.dim = dim
              self.lastshape = curshape
              self.arrxopt = resize(2 * np.abs(self.xopt), curshape)
              self.arrscales = resize(self.scales, curshape)
              self.arrsigns = resize(sign(self.xopt), curshape)
  
      def _evalfull(self, x):
          fadd = self.fopt
          curshape, dim = self.shape_(x)
          # it is assumed x are row vectors
  
          if self.lastshape != curshape:
              self.initwithsize(curshape, dim)
  
          # TRANSFORMATION IN SEARCH SPACE
          x = 2 * self.arrsigns * x  # makes the below boundary handling effective for coordinates
          try:
              x[:, 1:] = x[:, 1:] + 0.25 * (x[:, :-1] - self.arrxopt[:, :-1])
          except IndexError:
              x[1:] = x[1:] + 0.25 * (x[:-1] - self.arrxopt[:-1])
          x = 100.0 * (self.arrscales * (x - self.arrxopt) + self.arrxopt)
  
          # BOUNDARY HANDLING
          xoutside = np.maximum(0.0, np.abs(x) - 500.0) * sign(x)  # in [-500, 500]
          fpen = 0.01 * np.sum(xoutside ** 2, -1)
          fadd = fadd + fpen
  
          # COMPUTATION core
          ftrue = 0.01 * ((418.9828872724339) - np.mean(x * np.sin(np.sqrt(np.abs(x))), -1))
          fval = self.noise(ftrue)
  
          # FINALIZE
          ftrue += fadd
          fval += fadd
          return fval, ftrue
  
  
  class _FGallagher(BBOBFunction):
      """Abstract Gallagher with nhighpeaks Gaussian peaks, condition up to 1000, one global rotation
  
      Attribute fac2, nhighpeaks, highpeakcond and method boundary
      handling need to be defined.
  
      """
  
      rrseed = 21
      maxcondition = 1000.0
      fitvalues = (1.1, 9.1)
      fac2 = None  # added: factor for xopt not too close to boundaries, used by F22
      nhighpeaks = None
      highpeakcond = None
  
      def initwithsize(self, curshape, dim):
          # DIM-dependent initialization
          if self.dim != dim:
              self.rotation = compute_rotation(self.rseed, dim)
              arrcondition = self.maxcondition ** linspace(0, 1, self.nhighpeaks - 1)
              idx = np.argsort(unif(self.nhighpeaks - 1, self.rseed))  # random permutation
              arrcondition = np.insert(arrcondition[idx], 0, self.highpeakcond)
              self.arrscales = []
              for i, e in enumerate(arrcondition):
                  s = e ** linspace(-0.5, 0.5, dim)
                  idx = np.argsort(
                      unif(dim, self.rseed + 1e3 * i)
                  )  # permutation instead of rotation
                  self.arrscales.append(s[idx])  # this is inverse Cov
              self.arrscales = np.vstack(self.arrscales)
              # compute peak values, 10 is global optimum
              self.peakvalues = np.insert(
                  linspace(self.fitvalues[0], self.fitvalues[1], self.nhighpeaks - 1), 0, 10.0
              )
  
          # DIM- and POPSI-dependent initialisations of DIM*POPSI matrices
          if self.lastshape != curshape:
              self.dim = dim
              self.lastshape = curshape
              self.xlocal = dot(
                  self.fac2
                  * np.reshape(
                      10.0 * unif(dim * self.nhighpeaks, self.rseed) - 5.0, (self.nhighpeaks, dim)
                  ),
                  self.rotation,
              )
              if self.zerox:
                  self.xlocal[0, :] = zeros(dim)
              else:
                  # global optimum not too close to boundary
                  self.xlocal[0, :] = 0.8 * self.xlocal[0, :]
              self.xopt = dot(self.xlocal[0, :], self.rotation.T)
  
      def _evalfull(self, x):
          fadd = self.fopt
          curshape, dim = self.shape_(x)
          # it is assumed x are row vectors
  
          if self.lastshape != curshape:
              self.initwithsize(curshape, dim)
  
          # BOUNDARY HANDLING
          fadd = fadd + self.boundaryhandling(x)
  
          # TRANSFORMATION IN SEARCH SPACE
          x = dot(x, self.rotation)
  
          # COMPUTATION core
          fac = -0.5 / dim
          # f = NaN(nhighpeaks, popsi)
          # TODO: optimize
          if len(curshape) < 2:  # popsize is 1 in this case
              f = np.zeros(self.nhighpeaks)
              xx = tile(x, (self.nhighpeaks, 1)) - self.xlocal
              f[:] = self.peakvalues * np.exp(fac * np.sum(self.arrscales * xx ** 2, 1))
          elif curshape[0] < 0.5 * self.nhighpeaks:
              f = np.zeros((curshape[0], self.nhighpeaks))
              for k, e in enumerate(x):
                  xx = tile(e, (self.nhighpeaks, 1)) - self.xlocal
                  f[k, :] = self.peakvalues * np.exp(fac * np.sum(self.arrscales * xx ** 2, 1))
          else:
              f = np.zeros((curshape[0], self.nhighpeaks))
              for i in range(self.nhighpeaks):
                  xx = x - tile(self.xlocal[i, :], (curshape[0], 1))
                  f[:, i] = self.peakvalues[i] * np.exp(fac * (dot(xx ** 2, self.arrscales[i, :])))
          ftrue = monotoneTFosc(10 - np.max(f, -1)) ** 2
          fval = self.noise(ftrue)
  
          # FINALIZE
          ftrue += fadd
          fval += fadd
          return fval, ftrue
  
  
  class F21(_FGallagher, BBOBNfreeFunction):
      """Gallagher with 101 Gaussian peaks, condition up to 1000, one global rotation, noise-free"""
  
      funId = 21
      nhighpeaks = 101
      fac2 = 1.0
      highpeakcond = 1000.0 ** 0.5
  
      def boundaryhandling(self, x):
          return defaultboundaryhandling(x, 1.0)
  
  
  class F22(_FGallagher, BBOBNfreeFunction):
      """Gallagher with 21 Gaussian peaks, condition up to 1000, one global rotation"""
  
      funId = 22
      rrseed = 22
      nhighpeaks = 21
      fac2 = 0.98
      highpeakcond = 1000.0
  
      def boundaryhandling(self, x):
          return defaultboundaryhandling(x, 1.0)
  
  
  class F128(_FGallagher, BBOBGaussFunction):  # TODO: check boundary handling
      """Gallagher with 101 Gaussian peaks with Gauss noise, condition up to 1000, one global rotation"""
  
      funId = 128
      nhighpeaks = 101
      fac2 = 1.0
      highpeakcond = 1000.0 ** 0.5
      gaussbeta = 1.0
  
  
  class F129(_FGallagher, BBOBUniformFunction):
      """Gallagher with 101 Gaussian peaks with uniform noise, condition up to 1000, one global rotation"""
  
      funId = 129
      nhighpeaks = 101
      fac2 = 1.0
      highpeakcond = 1000.0 ** 0.5
      unifalphafac = 1.0
      unifbeta = 1.0
  
  
  class F130(_FGallagher, BBOBCauchyFunction):
      """Gallagher with 101 Gaussian peaks with seldom Cauchy noise, condition up to 1000, one global rotation"""
  
      funId = 130
      nhighpeaks = 101
      fac2 = 1.0
      highpeakcond = 1000.0 ** 0.5
      cauchyalpha = 1.0
      cauchyp = 0.2
  
  
  class F23(BBOBNfreeFunction):
      """Katsuura function"""
  
      funId = 23
      condition = 100.0
      arr2k = np.reshape(
          2.0 ** (np.arange(1, 33)), (1, 32)
      )  # bug-fix for 32-bit (NH): 2 -> 2. (relevance is minor)
  
      def initwithsize(self, curshape, dim):
          # DIM-dependent initialization
          if self.dim != dim:
              if self.zerox:
                  self.xopt = zeros(dim)
              else:
                  self.xopt = compute_xopt(self.rseed, dim)
              self.rotation = compute_rotation(self.rseed + 1e6, dim)
              self.scales = (self.condition ** 0.5) ** linspace(0, 1, dim)
              self.linearTF = dot(compute_rotation(self.rseed, dim), diag(self.scales))
              # decouple scaling from function definition
              self.linearTF = dot(self.linearTF, self.rotation)
  
          # DIM- and POPSI-dependent initialisations of DIM*POPSI matrices
          if self.lastshape != curshape:
              self.dim = dim
              self.lastshape = curshape
              self.arrxopt = resize(self.xopt, curshape)
  
      def _evalfull(self, x):
          fadd = self.fopt
          curshape, dim = self.shape_(x)
          # it is assumed x are row vectors
  
          if self.lastshape != curshape:
              self.initwithsize(curshape, dim)
  
          # BOUNDARY HANDLING
          xoutside = np.maximum(0, np.abs(x) - 5.0) * sign(x)
          fpen = np.sum(xoutside ** 2, -1)
          fadd = fadd + fpen
  
          # TRANSFORMATION IN SEARCH SPACE
          x = x - self.arrxopt  # cannot be replaced with x -= arrxopt!
          x = dot(x, self.linearTF)
  
          # COMPUTATION core
          if len(curshape) < 2:  # popsize is 1 in this case
              arr = dot(np.reshape(x, (dim, 1)), self.arr2k)  # dim times d array
              ftrue = -10.0 / dim ** 2.0 + 10.0 / dim ** 2.0 * np.prod(
                  1
                  + np.arange(1, dim + 1)
                  * np.dot(np.abs(arr - np.round(arr)), self.arr2k.T ** -1.0).T
              ) ** (10.0 / dim ** 1.2)
          else:
              ftrue = zeros(curshape[0])
              for k, e in enumerate(x):
                  arr = dot(np.reshape(e, (dim, 1)), self.arr2k)  # dim times d array
                  ftrue[k] = -10.0 / dim ** 2.0 + 10.0 / dim ** 2.0 * np.prod(
                      1
                      + np.arange(1, dim + 1)
                      * np.dot(np.abs(arr - np.round(arr)), self.arr2k.T ** -1.0).T
                  ) ** (10.0 / dim ** 1.2)
          fval = self.noise(ftrue)
  
          # FINALIZE
          ftrue += fadd
          fval += fadd
          return fval, ftrue
  
  
  class F24(BBOBNfreeFunction):
      """Lunacek bi-Rastrigin, condition 100
  
      in PPSN 2008, Rastrigin part rotated and scaled
  
      """
  
      funId = 24
      condition = 100.0
      _mu1 = 2.5
  
      def initwithsize(self, curshape, dim):
          # DIM-dependent initialization
          if self.dim != dim:
              if self.zerox:
                  self.xopt = zeros(dim)
              else:
                  self.xopt = 0.5 * self._mu1 * sign(gauss(dim, self.rseed))
              self.rotation = compute_rotation(self.rseed + 1e6, dim)
              self.scales = (self.condition ** 0.5) ** linspace(0, 1, dim)
              self.linearTF = dot(compute_rotation(self.rseed, dim), diag(self.scales))
              # decouple scaling from function definition
              self.linearTF = dot(self.linearTF, self.rotation)
  
          # DIM- and POPSI-dependent initialisations of DIM*POPSI matrices
          if self.lastshape != curshape:
              self.dim = dim
              self.lastshape = curshape
              # self.arrxopt = resize(self.xopt, curshape)
              self.arrscales = resize(2.0 * sign(self.xopt), curshape)  # makes up for xopt
  
      def _evalfull(self, x):
          fadd = self.fopt
          curshape, dim = self.shape_(x)
          # it is assumed x are row vectors
  
          if self.lastshape != curshape:
              self.initwithsize(curshape, dim)
  
          # BOUNDARY HANDLING
          xoutside = np.maximum(0, np.abs(x) - 5.0) * sign(x)
          fpen = 1e4 * np.sum(xoutside ** 2, -1)
          fadd = fadd + fpen
  
          # TRANSFORMATION IN SEARCH SPACE
          x = self.arrscales * x
  
          # COMPUTATION core
          s = 1 - 0.5 / ((dim + 20) ** 0.5 - 4.1)  # tested up to DIM = 160 p in [0.25,0.33]
          d = 1  # shift [1,3], smaller is more difficult
          mu2 = -(((self._mu1 ** 2 - d) / s) ** 0.5)
          ftrue = np.minimum(
              np.sum((x - self._mu1) ** 2, -1), d * dim + s * np.sum((x - mu2) ** 2, -1)
          )
          ftrue = ftrue + 10 * (
              dim - np.sum(np.cos(2 * np.pi * dot(x - self._mu1, self.linearTF)), -1)
          )
          fval = self.noise(ftrue)
  
          # FINALIZE
          ftrue += fadd
          fval += fadd
          return fval, ftrue
  
  
  # dictbbob = {'sphere': F1, 'ellipsoid': F2, 'Rastrigin': F3}
  nfreefunclasses = (
      F1,
      F2,
      F3,
      F4,
      F5,
      F6,
      F7,
      F8,
      F9,
      F10,
      F11,
      F12,
      F13,
      F14,
      F15,
      F16,
      F17,
      F18,
      F19,
      F20,
      F21,
      F22,
      F23,
      F24,
  )  # hard coded
  noisyfunclasses = (
      F101,
      F102,
      F103,
      F104,
      F105,
      F106,
      F107,
      F108,
      F109,
      F110,
      F111,
      F112,
      F113,
      F114,
      F115,
      F116,
      F117,
      F118,
      F119,
      F120,
      F121,
      F122,
      F123,
      F124,
      F125,
      F126,
      F127,
      F128,
      F129,
      F130,
  )
  dictbbobnfree = dict((i.funId, i) for i in nfreefunclasses)
  nfreeIDs = sorted(dictbbobnfree.keys())  # was: "nfreenames"
  nfreeinfos = [str(i) + ": " + dictbbobnfree[i].__doc__ for i in nfreeIDs]
  
  dictbbobnoisy = dict((i.funId, i) for i in noisyfunclasses)
  noisyIDs = sorted(dictbbobnoisy.keys())  # was noisynames
  
  funclasses = list(nfreefunclasses) + list(noisyfunclasses)
  dictbbob = dict((i.funId, i) for i in funclasses)
  
  # TODO: pb xopt f9, 21, 22
  class _FTemplate(BBOBNfreeFunction):
      """Template based on F1"""
  
      funId = 421337
  
      def initwithsize(self, curshape, dim):
          # DIM-dependent initialization
          if self.dim != dim:
              if self.zerox:
                  self.xopt = zeros(dim)
              else:
                  self.xopt = compute_xopt(self.rseed, dim)
  
          # DIM- and POPSI-dependent initialisations of DIM*POPSI matrices
          if self.lastshape != curshape:
              self.dim = dim
              self.lastshape = curshape
              self.arrxopt = resize(self.xopt, curshape)
  
          self.linearTf = None
          self.rotation = None
  
      def _evalfull(self, x):
          fadd = self.fopt
          curshape, dim = self.shape_(x)
          # it is assumed x are row vectors
  
          if self.lastshape != curshape:
              self.initwithsize(curshape, dim)
  
          # BOUNDARY HANDLING
  
          # TRANSFORMATION IN SEARCH SPACE
          x = x - self.arrxopt  # cannot be replaced with x -= arrxopt!
  
          # COMPUTATION core
          ftrue = np.sum(x ** 2, 1)
          fval = self.noise(ftrue)
  
          # FINALIZE
          ftrue += fadd
          fval += fadd
          return fval, ftrue
  
  
  def instantiate(ifun, iinstance=0, param=None, **kwargs):
      """Returns test function ifun, by default instance 0,
      and its optimal f-value."""
      res = dictbbob[ifun](
          iinstance=iinstance, param=param, **kwargs
      )  # calling BBOBFunction.__init__(iinstance, param,...)
      return res, res.fopt
  
  
  def get_param(ifun):
      """Returns the parameter values of the function ifun."""
      try:
          return dictbbob[ifun].paramValues
      except AttributeError:
          return (None,)
  
  
  if __name__ == "__main__":
      import doctest
  
      doctest.testmod()  # run all doctests in this module
  