def fmin(objective_function, x0, sigma0,
         options=None,
         args=(),
         gradf=None,
         restarts=0,
         restart_from_best='False',
         incpopsize=2,
         eval_initial_x=False,
         noise_handler=None,
         noise_change_sigma_exponent=1,
         noise_kappa_exponent=0,  # TODO: add max kappa value as parameter
         bipop=False):
    """functional interface to the stochastic optimizer CMA-ES
    for non-convex function minimization.

    Calling Sequences
    =================
        ``fmin(objective_function, x0, sigma0)``
            minimizes `objective_function` starting at `x0` and with standard deviation
            `sigma0` (step-size)
        ``fmin(objective_function, x0, sigma0, options={'ftarget': 1e-5})``
            minimizes `objective_function` up to target function value 1e-5, which
            is typically useful for benchmarking.
        ``fmin(objective_function, x0, sigma0, args=('f',))``
            minimizes `objective_function` called with an additional argument ``'f'``.
        ``fmin(objective_function, x0, sigma0, options={'ftarget':1e-5, 'popsize':40})``
            uses additional options ``ftarget`` and ``popsize``
        ``fmin(objective_function, esobj, None, options={'maxfevals': 1e5})``
            uses the `CMAEvolutionStrategy` object instance `esobj` to optimize
            `objective_function`, similar to `esobj.optimize()`.

    Arguments
    =========
        `objective_function`
            function to be minimized. Called as ``objective_function(x,
            *args)``. `x` is a one-dimensional `numpy.ndarray`.
            `objective_function` can return `numpy.NaN`,
            which is interpreted as outright rejection of solution `x`
            and invokes an immediate resampling and (re-)evaluation
            of a new solution not counting as function evaluation.
        `x0`
            list or `numpy.ndarray`, initial guess of minimum solution
            before the application of the geno-phenotype transformation
            according to the ``transformation`` option.  It can also be
            a string holding a Python expression that is evaluated
            to yield the initial guess - this is important in case
            restarts are performed so that they start from different
            places.  Otherwise `x0` can also be a `cma.CMAEvolutionStrategy`
            object instance, in that case `sigma0` can be ``None``.
        `sigma0`
            scalar, initial standard deviation in each coordinate.
            `sigma0` should be about 1/4th of the search domain width
            (where the optimum is to be expected). The variables in
            `objective_function` should be scaled such that they
            presumably have similar sensitivity.
            See also option `scaling_of_variables`.
        `options`
            a dictionary with additional options passed to the constructor
            of class ``CMAEvolutionStrategy``, see ``cma.CMAOptions()``
            for a list of available options.
        ``args=()``
            arguments to be used to call the `objective_function`
        ``gradf``
            gradient of f, where ``len(gradf(x, *args)) == len(x)``.
            `gradf` is called once in each iteration if
            ``gradf is not None``.
        ``restarts=0``
            number of restarts with increasing population size, see also
            parameter `incpopsize`, implementing the IPOP-CMA-ES restart
            strategy, see also parameter `bipop`; to restart from
            different points (recommended), pass `x0` as a string.
        ``restart_from_best=False``
            which point to restart from
        ``incpopsize=2``
            multiplier for increasing the population size `popsize` before
            each restart
        ``eval_initial_x=None``
            evaluate initial solution, for `None` only with elitist option
        ``noise_handler=None``
            a ``NoiseHandler`` instance or ``None``, a simple usecase is
            ``cma.fmin(f, 6 * [1], 1, noise_handler=cma.NoiseHandler(6))``
            see ``help(cma.NoiseHandler)``.
        ``noise_change_sigma_exponent=1``
            exponent for sigma increment for additional noise treatment
        ``noise_evaluations_as_kappa``
            instead of applying reevaluations, the "number of evaluations"
            is (ab)used as scaling factor kappa (experimental).
        ``bipop``
            if True, run as BIPOP-CMA-ES; BIPOP is a special restart
            strategy switching between two population sizings - small
            (like the default CMA, but with more focused search) and
            large (progressively increased as in IPOP). This makes the
            algorithm perform well both on functions with many regularly
            or irregularly arranged local optima (the latter by frequently
            restarting with small populations).  For the `bipop` parameter
            to actually take effect, also select non-zero number of
            (IPOP) restarts; the recommended setting is ``restarts<=9``
            and `x0` passed as a string.  Note that small-population
            restarts do not count into the total restart count.

    Optional Arguments
    ==================
    All values in the `options` dictionary are evaluated if they are of
    type `str`, besides `verb_filenameprefix`, see class `CMAOptions` for
    details. The full list is available via ``cma.CMAOptions()``.

    >>> import cma
    >>> cma.CMAOptions()

    Subsets of options can be displayed, for example like
    ``cma.CMAOptions('tol')``, or ``cma.CMAOptions('bound')``,
    see also class `CMAOptions`.

    Return
    ======
    Return the list provided by `CMAEvolutionStrategy.result()` appended
    with termination conditions, an `OOOptimizer` and a `BaseDataLogger`::

        res = es.result() + (es.stop(), es, logger)

    where
        - ``res[0]`` (``xopt``) -- best evaluated solution
        - ``res[1]`` (``fopt``) -- respective function value
        - ``res[2]`` (``evalsopt``) -- respective number of function evaluations
        - ``res[3]`` (``evals``) -- number of overall conducted objective function evaluations
        - ``res[4]`` (``iterations``) -- number of overall conducted iterations
        - ``res[5]`` (``xmean``) -- mean of the final sample distribution
        - ``res[6]`` (``stds``) -- effective stds of the final sample distribution
        - ``res[-3]`` (``stop``) -- termination condition(s) in a dictionary
        - ``res[-2]`` (``cmaes``) -- class `CMAEvolutionStrategy` instance
        - ``res[-1]`` (``logger``) -- class `CMADataLogger` instance

    Details
    =======
    This function is an interface to the class `CMAEvolutionStrategy`. The
    latter class should be used when full control over the iteration loop
    of the optimizer is desired.

    Examples
    ========
    The following example calls `fmin` optimizing the Rosenbrock function
    in 10-D with initial solution 0.1 and initial step-size 0.5. The
    options are specified for the usage with the `doctest` module.

    >>> import cma
    >>> # cma.CMAOptions()  # returns all possible options
    >>> options = {'CMA_diagonal':100, 'seed':1234, 'verb_time':0}
    >>>
    >>> res = cma.fmin(cma.fcts.rosen, [0.1] * 10, 0.5, options)
    (5_w,10)-CMA-ES (mu_w=3.2,w_1=45%) in dimension 10 (seed=1234)
       Covariance matrix is diagonal for 10 iterations (1/ccov=29.0)
    Iterat #Fevals   function value     axis ratio  sigma   minstd maxstd min:sec
        1      10 1.264232686260072e+02 1.1e+00 4.40e-01  4e-01  4e-01
        2      20 1.023929748193649e+02 1.1e+00 4.00e-01  4e-01  4e-01
        3      30 1.214724267489674e+02 1.2e+00 3.70e-01  3e-01  4e-01
      100    1000 6.366683525319511e+00 6.2e+00 2.49e-02  9e-03  3e-02
      200    2000 3.347312410388666e+00 1.2e+01 4.52e-02  8e-03  4e-02
      300    3000 1.027509686232270e+00 1.3e+01 2.85e-02  5e-03  2e-02
      400    4000 1.279649321170636e-01 2.3e+01 3.53e-02  3e-03  3e-02
      500    5000 4.302636076186532e-04 4.6e+01 4.78e-03  3e-04  5e-03
      600    6000 6.943669235595049e-11 5.1e+01 5.41e-06  1e-07  4e-06
      650    6500 5.557961334063003e-14 5.4e+01 1.88e-07  4e-09  1e-07
    termination on tolfun : 1e-11
    final/bestever f-value = 5.55796133406e-14 2.62435631419e-14
    mean solution:  [ 1.          1.00000001  1.          1.
        1.          1.00000001  1.00000002  1.00000003 ...]
    std deviation: [ 3.9193387e-09  3.7792732e-09  4.0062285e-09  4.6605925e-09
        5.4966188e-09   7.4377745e-09   1.3797207e-08   2.6020765e-08 ...]
    >>>
    >>> print('best solutions fitness = %f' % (res[1]))
    best solutions fitness = 2.62435631419e-14
    >>> assert res[1] < 1e-12

    The above call is pretty much equivalent with the slightly more
    verbose call::

        es = cma.CMAEvolutionStrategy([0.1] * 10, 0.5,
                    options=options).optimize(cma.fcts.rosen)

    The following example calls `fmin` optimizing the Rastrigin function
    in 3-D with random initial solution in [-2,2], initial step-size 0.5
    and the BIPOP restart strategy (that progressively increases population).
    The options are specified for the usage with the `doctest` module.

    >>> import cma
    >>> # cma.CMAOptions()  # returns all possible options
    >>> options = {'seed':12345, 'verb_time':0, 'ftarget': 1e-8}
    >>>
    >>> res = cma.fmin(cma.fcts.rastrigin, '2. * np.random.rand(3) - 1', 0.5,
    ...                options, restarts=9, bipop=True)
    (3_w,7)-aCMA-ES (mu_w=2.3,w_1=58%) in dimension 3 (seed=12345)
    Iterat #Fevals   function value    axis ratio  sigma  minstd maxstd min:sec
        1       7 1.633489455763566e+01 1.0e+00 4.35e-01  4e-01  4e-01
        2      14 9.762462950258016e+00 1.2e+00 4.12e-01  4e-01  4e-01
        3      21 2.461107851413725e+01 1.4e+00 3.78e-01  3e-01  4e-01
      100     700 9.949590571272680e-01 1.7e+00 5.07e-05  3e-07  5e-07
      123     861 9.949590570932969e-01 1.3e+00 3.93e-06  9e-09  1e-08
    termination on tolfun=1e-11
    final/bestever f-value = 9.949591e-01 9.949591e-01
    mean solution: [  9.94958638e-01  -7.19265205e-10   2.09294450e-10]
    std deviation: [  8.71497860e-09   8.58994807e-09   9.85585654e-09]
    [...]
    (4_w,9)-aCMA-ES (mu_w=2.8,w_1=49%) in dimension 3 (seed=12349)
    Iterat #Fevals   function value    axis ratio  sigma  minstd maxstd min:sec
        1  5342.0 2.114883315350800e+01 1.0e+00 3.42e-02  3e-02  4e-02
        2  5351.0 1.810102940125502e+01 1.4e+00 3.79e-02  3e-02  4e-02
        3  5360.0 1.340222457448063e+01 1.4e+00 4.58e-02  4e-02  6e-02
       50  5783.0 8.631491965616078e-09 1.6e+00 2.01e-04  8e-06  1e-05
    termination on ftarget=1e-08 after 4 restarts
    final/bestever f-value = 8.316963e-09 8.316963e-09
    mean solution: [ -3.10652459e-06   2.77935436e-06  -4.95444519e-06]
    std deviation: [  1.02825265e-05   8.08348144e-06   8.47256408e-06]

    In either case, the method::

        cma.plot();

    (based on `matplotlib.pyplot`) produces a plot of the run and, if
    necessary::

        cma.show()

    shows the plot in a window. Finally::

        cma.savefig('myfirstrun')  # savefig from matplotlib.pyplot

    will save the figure in a png.

    We can use the gradient like

    >>> import cma
    >>> res = cma.fmin(cma.fcts.rosen, np.zeros(10), 0.1,
    ...             options = {'ftarget':1e-8,},
    ...             gradf=cma.fcts.grad_rosen,
    ...         )
    >>> assert cma.fcts.rosen(res[0]) < 1e-8
    >>> assert res[2] < 3600  # 1% are > 3300
    >>> assert res[3] < 3600  # 1% are > 3300

    :See: `CMAEvolutionStrategy`, `OOOptimizer.optimize(), `plot()`,
        `CMAOptions`, `scipy.optimize.fmin()`

    """  # style guides say there should be the above empty line
    if 1 < 3:  # try: # pass on KeyboardInterrupt
        if not objective_function:  # cma.fmin(0, 0, 0)
            return CMAOptions()  # these opts are by definition valid

        fmin_options = locals().copy()  # archive original options
        del fmin_options['objective_function']
        del fmin_options['x0']
        del fmin_options['sigma0']
        del fmin_options['options']
        del fmin_options['args']

        if options is None:
            options = cma_default_options
        CMAOptions().check_attributes(options)  # might modify options
        # checked that no options.ftarget =
        opts = CMAOptions(options.copy()).complement()

        # BIPOP-related variables:
        runs_with_small = 0
        small_i = []
        large_i = []
        popsize0 = None  # to be evaluated after the first iteration
        maxiter0 = None  # to be evaluated after the first iteration
        base_evals = 0

        irun = 0
        best = BestSolution()
        while True:  # restart loop
            sigma_factor = 1

            # Adjust the population according to BIPOP after a restart.
            if not bipop:
                # BIPOP not in use, simply double the previous population
                # on restart.
                if irun > 0:
                    popsize_multiplier = fmin_options['incpopsize'] ** (irun - runs_with_small)
                    opts['popsize'] = popsize0 * popsize_multiplier

            elif irun == 0:
                # Initial run is with "normal" population size; it is
                # the large population before first doubling, but its
                # budget accounting is the same as in case of small
                # population.
                poptype = 'small'

            elif sum(small_i) < sum(large_i):
                # An interweaved run with small population size
                poptype = 'small'
                runs_with_small += 1  # _Before_ it's used in popsize_lastlarge

                sigma_factor = 0.01 ** np.random.uniform()  # Local search
                popsize_multiplier = fmin_options['incpopsize'] ** (irun - runs_with_small)
                opts['popsize'] = np.floor(popsize0 * popsize_multiplier ** (np.random.uniform() ** 2))
                opts['maxiter'] = min(maxiter0, 0.5 * sum(large_i) / opts['popsize'])
                # print('small basemul %s --> %s; maxiter %s' % (popsize_multiplier, opts['popsize'], opts['maxiter']))

            else:
                # A run with large population size; the population
                # doubling is implicit with incpopsize.
                poptype = 'large'

                popsize_multiplier = fmin_options['incpopsize'] ** (irun - runs_with_small)
                opts['popsize'] = popsize0 * popsize_multiplier
                opts['maxiter'] = maxiter0
                # print('large basemul %s --> %s; maxiter %s' % (popsize_multiplier, opts['popsize'], opts['maxiter']))

            # recover from a CMA object
            if irun == 0 and isinstance(x0, CMAEvolutionStrategy):
                es = x0
                x0 = es.inputargs['x0']  # for the next restarts
                if isscalar(sigma0) and isfinite(sigma0) and sigma0 > 0:
                    es.sigma = sigma0
                # debatable whether this makes sense:
                sigma0 = es.inputargs['sigma0']  # for the next restarts
                if options is not None:
                    es.opts.set(options)
                # ignore further input args and keep original options
            else:  # default case
                if irun and eval(str(fmin_options['restart_from_best'])):
                    print_warning('CAVE: restart_from_best is often not useful',
                                  verbose=opts['verbose'])
                    es = CMAEvolutionStrategy(best.x, sigma_factor * sigma0, opts)
                else:
                    es = CMAEvolutionStrategy(x0, sigma_factor * sigma0, opts)
                if eval_initial_x or es.opts['CMA_elitist'] == 'initial' \
                   or (es.opts['CMA_elitist'] and eval_initial_x is None):
                    x = es.gp.pheno(es.mean,
                                    into_bounds=es.boundary_handler.repair,
                                    archive=es.sent_solutions)
                    es.best.update([x], es.sent_solutions,
                                   [objective_function(x, *args)], 1)
                    es.countevals += 1

            opts = es.opts  # processed options, unambiguous
            # a hack:
            fmin_opts = CMAOptions(fmin_options.copy(), unchecked=True)
            for k in fmin_opts:
                # locals() cannot be modified directly, exec won't work
                # in 3.x, therefore
                fmin_opts.eval(k, loc={'N': es.N,
                                       'popsize': opts['popsize']},
                               correct_key=False)

            append = opts['verb_append'] or es.countiter > 0 or irun > 0
            # es.logger is "the same" logger, because the "identity"
            # is only determined by the `filenameprefix`
            logger = CMADataLogger(opts['verb_filenameprefix'],
                                   opts['verb_log'])
            logger.register(es, append).add()  # no fitness values here
            es.logger = logger

            if noise_handler:
                noisehandler = noise_handler
                noise_handling = True
                if fmin_opts['noise_change_sigma_exponent'] > 0:
                    es.opts['tolfacupx'] = inf
            else:
                noisehandler = NoiseHandler(es.N, 0)
                noise_handling = False
            es.noise_handler = noisehandler

            # the problem: this assumes that good solutions cannot take longer than bad ones:
            # with EvalInParallel(objective_function, 2, is_feasible=opts['is_feasible']) as eval_in_parallel:
            if 1 < 3:
                while not es.stop():  # iteration loop
                    # X, fit = eval_in_parallel(lambda: es.ask(1)[0], es.popsize, args, repetitions=noisehandler.evaluations-1)
                    X, fit = es.ask_and_eval(objective_function, args, gradf=gradf,
                                             evaluations=noisehandler.evaluations,
                                             aggregation=np.median)  # treats NaN with resampling
                    # TODO: check args and in case use args=(noisehandler.evaluations, )

                    es.tell(X, fit)  # prepare for next iteration
                    if noise_handling:  # it would be better to also use these f-evaluations in tell
                        es.sigma *= noisehandler(X, fit, objective_function, es.ask,
                                                 args=args)**fmin_opts['noise_change_sigma_exponent']

                        es.countevals += noisehandler.evaluations_just_done  # TODO: this is a hack, not important though
                        # es.more_to_write.append(noisehandler.evaluations_just_done)
                        if noisehandler.maxevals > noisehandler.minevals:
                            es.more_to_write.append(noisehandler.get_evaluations())
                        if 1 < 3:
                            es.sp.cmean *= exp(-noise_kappa_exponent * np.tanh(noisehandler.noiseS))
                            if es.sp.cmean > 1:
                                es.sp.cmean = 1

                    es.disp()
                    logger.add(# more_data=[noisehandler.evaluations, 10**noisehandler.noiseS] if noise_handling else [],
                               modulo=1 if es.stop() and logger.modulo else None)
                    if (opts['verb_log'] and opts['verb_plot'] and
                          (es.countiter % max(opts['verb_plot'], opts['verb_log']) == 0 or es.stop())):
                        logger.plot(324)

            # end while not es.stop
            mean_pheno = es.gp.pheno(es.mean, into_bounds=es.boundary_handler.repair, archive=es.sent_solutions)
            fmean = objective_function(mean_pheno, *args)
            es.countevals += 1

            es.best.update([mean_pheno], es.sent_solutions, [fmean], es.countevals)
            best.update(es.best, es.sent_solutions)  # in restarted case
            # es.best.update(best)

            this_evals = es.countevals - base_evals
            base_evals = es.countevals

            # BIPOP stats update

            if irun == 0:
                popsize0 = opts['popsize']
                maxiter0 = opts['maxiter']
                # XXX: This might be a bug? Reproduced from Matlab
                # small_i.append(this_evals)

            if bipop:
                if poptype == 'small':
                    small_i.append(this_evals)
                else:  # poptype == 'large'
                    large_i.append(this_evals)

            # final message
            if opts['verb_disp']:
                es.result_pretty(irun, time.asctime(time.localtime()),
                                 best.f)

            irun += 1
            # if irun > fmin_opts['restarts'] or 'ftarget' in es.stop() \
            # if irun > restarts or 'ftarget' in es.stop() \
            if irun - runs_with_small > fmin_opts['restarts'] or 'ftarget' in es.stop() \
                    or 'maxfevals' in es.stop(check=False):
                break
            opts['verb_append'] = es.countevals
            opts['popsize'] = fmin_opts['incpopsize'] * es.sp.popsize  # TODO: use rather options?
            opts['seed'] += 1

        # while irun

        # es.out['best'] = best  # TODO: this is a rather suboptimal type for inspection in the shell
        if 1 < 3:
            if irun:
                es.best.update(best)
                # TODO: there should be a better way to communicate the overall best
            return es.result() + (es.stop(), es, logger)

        else:  # previously: to be removed
            return (best.x.copy(), best.f, es.countevals,
                    dict((('stopdict', _CMAStopDict(es._stopdict))
                          , ('mean', es.gp.pheno(es.mean))
                          , ('std', es.sigma * es.sigma_vec * sqrt(es.dC) * es.gp.scales)
                          , ('out', es.out)
                          , ('opts', es.opts)  # last state of options
                          , ('cma', es)
                          , ('inputargs', es.inputargs)
                          ))
                   )
        # TODO refine output, can #args be flexible?
        # is this well usable as it is now?
    else:  # except KeyboardInterrupt:  # Exception, e:
        if eval(str(options['verb_disp'])) > 0:
            print(' in/outcomment ``raise`` in last line of cma.fmin to prevent/restore KeyboardInterrupt exception')
        raise
functional interface to the stochastic optimizer CMA-ES
    for non-convex function minimization.

    Calling Sequences
    =================
        ``fmin(objective_function, x0, sigma0)``
            minimizes `objective_function` starting at `x0` and with standard deviation
            `sigma0` (step-size)
        ``fmin(objective_function, x0, sigma0, options={'ftarget': 1e-5})``
            minimizes `objective_function` up to target function value 1e-5, which
            is typically useful for benchmarking.
        ``fmin(objective_function, x0, sigma0, args=('f',))``
            minimizes `objective_function` called with an additional argument ``'f'``.
        ``fmin(objective_function, x0, sigma0, options={'ftarget':1e-5, 'popsize':40})``
            uses additional options ``ftarget`` and ``popsize``
        ``fmin(objective_function, esobj, None, options={'maxfevals': 1e5})``
            uses the `CMAEvolutionStrategy` object instance `esobj` to optimize
            `objective_function`, similar to `esobj.optimize()`.

    Arguments
    =========
        `objective_function`
            function to be minimized. Called as ``objective_function(x,
            *args)``. `x` is a one-dimensional `numpy.ndarray`.
            `objective_function` can return `numpy.NaN`,
            which is interpreted as outright rejection of solution `x`
            and invokes an immediate resampling and (re-)evaluation
            of a new solution not counting as function evaluation.
        `x0`
            list or `numpy.ndarray`, initial guess of minimum solution
            before the application of the geno-phenotype transformation
            according to the ``transformation`` option.  It can also be
            a string holding a Python expression that is evaluated
            to yield the initial guess - this is important in case
            restarts are performed so that they start from different
            places.  Otherwise `x0` can also be a `cma.CMAEvolutionStrategy`
            object instance, in that case `sigma0` can be ``None``.
        `sigma0`
            scalar, initial standard deviation in each coordinate.
            `sigma0` should be about 1/4th of the search domain width
            (where the optimum is to be expected). The variables in
            `objective_function` should be scaled such that they
            presumably have similar sensitivity.
            See also option `scaling_of_variables`.
        `options`
            a dictionary with additional options passed to the constructor
            of class ``CMAEvolutionStrategy``, see ``cma.CMAOptions()``
            for a list of available options.
        ``args=()``
            arguments to be used to call the `objective_function`
        ``gradf``
            gradient of f, where ``len(gradf(x, *args)) == len(x)``.
            `gradf` is called once in each iteration if
            ``gradf is not None``.
        ``restarts=0``
            number of restarts with increasing population size, see also
            parameter `incpopsize`, implementing the IPOP-CMA-ES restart
            strategy, see also parameter `bipop`; to restart from
            different points (recommended), pass `x0` as a string.
        ``restart_from_best=False``
            which point to restart from
        ``incpopsize=2``
            multiplier for increasing the population size `popsize` before
            each restart
        ``eval_initial_x=None``
            evaluate initial solution, for `None` only with elitist option
        ``noise_handler=None``
            a ``NoiseHandler`` instance or ``None``, a simple usecase is
            ``cma.fmin(f, 6 * [1], 1, noise_handler=cma.NoiseHandler(6))``
            see ``help(cma.NoiseHandler)``.
        ``noise_change_sigma_exponent=1``
            exponent for sigma increment for additional noise treatment
        ``noise_evaluations_as_kappa``
            instead of applying reevaluations, the "number of evaluations"
            is (ab)used as scaling factor kappa (experimental).
        ``bipop``
            if True, run as BIPOP-CMA-ES; BIPOP is a special restart
            strategy switching between two population sizings - small
            (like the default CMA, but with more focused search) and
            large (progressively increased as in IPOP). This makes the
            algorithm perform well both on functions with many regularly
            or irregularly arranged local optima (the latter by frequently
            restarting with small populations).  For the `bipop` parameter
            to actually take effect, also select non-zero number of
            (IPOP) restarts; the recommended setting is ``restarts<=9``
            and `x0` passed as a string.  Note that small-population
            restarts do not count into the total restart count.

    Optional Arguments
    ==================
    All values in the `options` dictionary are evaluated if they are of
    type `str`, besides `verb_filenameprefix`, see class `CMAOptions` for
    details. The full list is available via ``cma.CMAOptions()``.

    >>> import cma
    >>> cma.CMAOptions()

    Subsets of options can be displayed, for example like
    ``cma.CMAOptions('tol')``, or ``cma.CMAOptions('bound')``,
    see also class `CMAOptions`.

    Return
    ======
    Return the list provided by `CMAEvolutionStrategy.result()` appended
    with termination conditions, an `OOOptimizer` and a `BaseDataLogger`::

        res = es.result() + (es.stop(), es, logger)

    where
        - ``res[0]`` (``xopt``) -- best evaluated solution
        - ``res[1]`` (``fopt``) -- respective function value
        - ``res[2]`` (``evalsopt``) -- respective number of function evaluations
        - ``res[3]`` (``evals``) -- number of overall conducted objective function evaluations
        - ``res[4]`` (``iterations``) -- number of overall conducted iterations
        - ``res[5]`` (``xmean``) -- mean of the final sample distribution
        - ``res[6]`` (``stds``) -- effective stds of the final sample distribution
        - ``res[-3]`` (``stop``) -- termination condition(s) in a dictionary
        - ``res[-2]`` (``cmaes``) -- class `CMAEvolutionStrategy` instance
        - ``res[-1]`` (``logger``) -- class `CMADataLogger` instance

    Details
    =======
    This function is an interface to the class `CMAEvolutionStrategy`. The
    latter class should be used when full control over the iteration loop
    of the optimizer is desired.

    Examples
    ========
    The following example calls `fmin` optimizing the Rosenbrock function
    in 10-D with initial solution 0.1 and initial step-size 0.5. The
    options are specified for the usage with the `doctest` module.

    >>> import cma
    >>> # cma.CMAOptions()  # returns all possible options
    >>> options = {'CMA_diagonal':100, 'seed':1234, 'verb_time':0}
    >>>
    >>> res = cma.fmin(cma.fcts.rosen, [0.1] * 10, 0.5, options)
    (5_w,10)-CMA-ES (mu_w=3.2,w_1=45%) in dimension 10 (seed=1234)
       Covariance matrix is diagonal for 10 iterations (1/ccov=29.0)
    Iterat #Fevals   function value     axis ratio  sigma   minstd maxstd min:sec
        1      10 1.264232686260072e+02 1.1e+00 4.40e-01  4e-01  4e-01
        2      20 1.023929748193649e+02 1.1e+00 4.00e-01  4e-01  4e-01
        3      30 1.214724267489674e+02 1.2e+00 3.70e-01  3e-01  4e-01
      100    1000 6.366683525319511e+00 6.2e+00 2.49e-02  9e-03  3e-02
      200    2000 3.347312410388666e+00 1.2e+01 4.52e-02  8e-03  4e-02
      300    3000 1.027509686232270e+00 1.3e+01 2.85e-02  5e-03  2e-02
      400    4000 1.279649321170636e-01 2.3e+01 3.53e-02  3e-03  3e-02
      500    5000 4.302636076186532e-04 4.6e+01 4.78e-03  3e-04  5e-03
      600    6000 6.943669235595049e-11 5.1e+01 5.41e-06  1e-07  4e-06
      650    6500 5.557961334063003e-14 5.4e+01 1.88e-07  4e-09  1e-07
    termination on tolfun : 1e-11
    final/bestever f-value = 5.55796133406e-14 2.62435631419e-14
    mean solution:  [ 1.          1.00000001  1.          1.
        1.          1.00000001  1.00000002  1.00000003 ...]
    std deviation: [ 3.9193387e-09  3.7792732e-09  4.0062285e-09  4.6605925e-09
        5.4966188e-09   7.4377745e-09   1.3797207e-08   2.6020765e-08 ...]
    >>>
    >>> print('best solutions fitness = %f' % (res[1]))
    best solutions fitness = 2.62435631419e-14
    >>> assert res[1] < 1e-12

    The above call is pretty much equivalent with the slightly more
    verbose call::

        es = cma.CMAEvolutionStrategy([0.1] * 10, 0.5,
                    options=options).optimize(cma.fcts.rosen)

    The following example calls `fmin` optimizing the Rastrigin function
    in 3-D with random initial solution in [-2,2], initial step-size 0.5
    and the BIPOP restart strategy (that progressively increases population).
    The options are specified for the usage with the `doctest` module.

    >>> import cma
    >>> # cma.CMAOptions()  # returns all possible options
    >>> options = {'seed':12345, 'verb_time':0, 'ftarget': 1e-8}
    >>>
    >>> res = cma.fmin(cma.fcts.rastrigin, '2. * np.random.rand(3) - 1', 0.5,
    ...                options, restarts=9, bipop=True)
    (3_w,7)-aCMA-ES (mu_w=2.3,w_1=58%) in dimension 3 (seed=12345)
    Iterat #Fevals   function value    axis ratio  sigma  minstd maxstd min:sec
        1       7 1.633489455763566e+01 1.0e+00 4.35e-01  4e-01  4e-01
        2      14 9.762462950258016e+00 1.2e+00 4.12e-01  4e-01  4e-01
        3      21 2.461107851413725e+01 1.4e+00 3.78e-01  3e-01  4e-01
      100     700 9.949590571272680e-01 1.7e+00 5.07e-05  3e-07  5e-07
      123     861 9.949590570932969e-01 1.3e+00 3.93e-06  9e-09  1e-08
    termination on tolfun=1e-11
    final/bestever f-value = 9.949591e-01 9.949591e-01
    mean solution: [  9.94958638e-01  -7.19265205e-10   2.09294450e-10]
    std deviation: [  8.71497860e-09   8.58994807e-09   9.85585654e-09]
    [...]
    (4_w,9)-aCMA-ES (mu_w=2.8,w_1=49%) in dimension 3 (seed=12349)
    Iterat #Fevals   function value    axis ratio  sigma  minstd maxstd min:sec
        1  5342.0 2.114883315350800e+01 1.0e+00 3.42e-02  3e-02  4e-02
        2  5351.0 1.810102940125502e+01 1.4e+00 3.79e-02  3e-02  4e-02
        3  5360.0 1.340222457448063e+01 1.4e+00 4.58e-02  4e-02  6e-02
       50  5783.0 8.631491965616078e-09 1.6e+00 2.01e-04  8e-06  1e-05
    termination on ftarget=1e-08 after 4 restarts
    final/bestever f-value = 8.316963e-09 8.316963e-09
    mean solution: [ -3.10652459e-06   2.77935436e-06  -4.95444519e-06]
    std deviation: [  1.02825265e-05   8.08348144e-06   8.47256408e-06]

    In either case, the method::

        cma.plot();

    (based on `matplotlib.pyplot`) produces a plot of the run and, if
    necessary::

        cma.show()

    shows the plot in a window. Finally::

        cma.savefig('myfirstrun')  # savefig from matplotlib.pyplot

    will save the figure in a png.

    We can use the gradient like

    >>> import cma
    >>> res = cma.fmin(cma.fcts.rosen, np.zeros(10), 0.1,
    ...             options = {'ftarget':1e-8,},
    ...             gradf=cma.fcts.grad_rosen,
    ...         )
    >>> assert cma.fcts.rosen(res[0]) < 1e-8
    >>> assert res[2] < 3600  # 1% are > 3300
    >>> assert res[3] < 3600  # 1% are > 3300

    :See: `CMAEvolutionStrategy`, `OOOptimizer.optimize(), `plot()`,
        `CMAOptions`, `scipy.optimize.fmin()`