'samples `number` solutions and evaluates them on `func`, where
each solution `s` is resampled until ``func(s) not in (numpy.NaN, None)``.
Arguments
`func`
objective function
`args`
additional parameters for `func`
`number`
number of solutions to be sampled, by default
population size ``popsize`` (AKA lambda)
`xmean`
mean for sampling the solutions, by default ``self.mean``.
`sigma_fac`
multiplier for sampling width, standard deviation, for example
to get a small perturbation of solution `xmean`
`evaluations`
number of evaluations for each sampled solution
`aggregation`
function that aggregates `evaluations` values to
as single value.
Return
``(X, fit)``, where
X -- list of solutions
fit -- list of respective function values
Details
When ``func(x)`` returns `NaN` or `None` a new solution is sampled until
``func(x) not in (numpy.NaN, None)``.  The argument to `func` can be
freely modified within `func`.
Depending on the ``CMA_mirrors`` option, some solutions are not sampled
independently but as mirrors of other bad solutions. This is a simple
derandomization that can save 10-30% of the evaluations in particular
with small populations, for example on the cigar function.
Example
>>> import cma
>>> x0, sigma0 = 8*[10], 1  # 8-D
>>> es = cma.CMAEvolutionStrategy(x0, sigma0)
>>> while not es.stop():
...     X, fit = es.ask_and_eval(cma.fcts.elli)  # handles NaN with resampling
...     es.tell(X, fit)  # pass on fitness values
...     es.disp(20) # print every 20-th iteration
>>> print(\'terminated on \' + str(es.stop()))
<output omitted>
A single iteration step can be expressed in one line, such that
an entire optimization after initialization becomes
while not es.stop():
es.tell(*es.ask_and_eval(cma.fcts.elli))'

def ask_and_eval(self, func, args=(), number=None, xmean=None, sigma_fac=1, evaluations=1, aggregation=np.median):

    popsize = self.sp.popsize
    if (number is not None):
        popsize = number
    selective_mirroring = True
    nmirrors = self.sp.lam_mirr
    if (popsize != self.sp.popsize):
        nmirrors = Mh.sround(((popsize * self.sp.lam_mirr) / self.sp.popsize))
    assert (nmirrors <= (popsize // 2))
    self.mirrors_idx = np.arange(nmirrors)
    self.mirrors_rejected_idx = []
    if (xmean is None):
        xmean = self.mean
    fit = []
    X_first = self.ask(popsize)
    X = []
    for k in xrange(int(popsize)):
        nreject = (-1)
        f = np.NaN
        while (f in (np.NaN, None)):
            nreject += 1
            if ((k < (popsize - nmirrors)) or nreject):
                if nreject:
                    x = self.ask(1, xmean, sigma_fac)[0]
                else:
                    x = X_first.pop(0)
            else:
                if ((k == (popsize - nmirrors)) and selective_mirroring):
                    self.mirrors_idx = np.argsort(fit)[(-1):((-1) - nmirrors):(-1)]
                x = self.get_mirror(X[self.mirrors_idx[((popsize - 1) - k)]])
            if ((nreject == 1) and (k >= (popsize - nmirrors))):
                self.mirrors_rejected_idx.append(k)
            if ((11 < 3) and self.opts['vv'] and (nreject < 2)):
                if (not hasattr(self, 'constraints_paths')):
                    k = 1
                    self.constraints_paths = [np.zeros(self.N) for _i in xrange(k)]
                Izero = np.zeros([self.N, self.N])
                for i in xrange(self.N):
                    if (x[i] < 0):
                        Izero[i][i] = 1
                        self.C -= (self.opts['vv'] * Izero)
                        Izero[i][i] = 0
                if ((1 < 3) and (sum([(((9 + i) + 1) * x[i]) for i in xrange(self.N)]) > 50000.0)):
                    self.constraints_paths[0] = ((0.9 * self.constraints_paths[0]) + ((0.1 * (x - self.mean)) / self.sigma))
                    self.C -= ((self.opts['vv'] / self.N) * np.outer(self.constraints_paths[0], self.constraints_paths[0]))
            f = func(x, *args)
            if ((f not in (np.NaN, None)) and (evaluations > 1)):
                f = aggregation(([f] + [func(x, *args) for _i in xrange(int((evaluations - 1)))]))
            if ((nreject + (1 % 1000)) == 0):
                print(('        %d    solutions    rejected    (f-value    NaN    or    None)    at    iteration    %d' % (nreject, self.countiter)))
        fit.append(f)
        X.append(x)
    self.evaluations_per_f_value = int(evaluations)
    return (X, fit)
