(self, solutions, function_values, check_points=None, copy=False)
pass objective function values to prepare for next
        iteration. This core procedure of the CMA-ES algorithm updates
        all state variables, in particular the two evolution paths, the
        distribution mean, the covariance matrix and a step-size.

        Arguments
        ---------
            `solutions`
                list or array of candidate solution points (of
                type `numpy.ndarray`), most presumably before
                delivered by method `ask()` or `ask_and_eval()`.
            `function_values`
                list or array of objective function values
                corresponding to the respective points. Beside for termination
                decisions, only the ranking of values in `function_values`
                is used.
            `check_points`
                If ``check_points is None``, only solutions that are not generated
                by `ask()` are possibly clipped (recommended). ``False`` does not clip
                any solution (not recommended).
                If ``True``, clips solutions that realize long steps (i.e. also
                those that are unlikely to be generated with `ask()`). `check_points`
                can be a list of indices to be checked in solutions.
            `copy`
                ``solutions`` can be modified in this routine, if ``copy is False``

        Details
        -------
        `tell()` updates the parameters of the multivariate
        normal search distribution, namely covariance matrix and
        step-size and updates also the attributes `countiter` and
        `countevals`. To check the points for consistency is quadratic
        in the dimension (like sampling points).

        Bugs
        ----
        The effect of changing the solutions delivered by `ask()` depends on whether
        boundary handling is applied. With boundary handling, modifications are
        disregarded. This is necessary to apply the default boundary handling that
        uses unrepaired solutions but might change in future.

        Example
        -------
        ::

            import cma
            func = cma.fcts.elli  # choose objective function
            es = cma.CMAEvolutionStrategy(cma.np.random.rand(10), 1)
            while not es.stop():
               X = es.ask()
               es.tell(X, [func(x) for x in X])
            es.result()  # where the result can be found

        :See: class `CMAEvolutionStrategy`, `ask()`, `ask_and_eval()`, `fmin()`
pass objective function values to prepare for next
        iteration. This core procedure of the CMA-ES algorithm updates
        all state variables, in particular the two evolution paths, the
        distribution mean, the covariance matrix and a step-size.
pass objective function values to prepare for next iteration . This core procedure of the CMA - ES algorithm updates all state variables in particular the two evolution paths the distribution mean the covariance matrix and a step - size .
def tell(self, solutions, function_values, check_points=None, copy=False):
        """pass objective function values to prepare for next
        iteration. This core procedure of the CMA-ES algorithm updates
        all state variables, in particular the two evolution paths, the
        distribution mean, the covariance matrix and a step-size.

        Arguments
        ---------
            `solutions`
                list or array of candidate solution points (of
                type `numpy.ndarray`), most presumably before
                delivered by method `ask()` or `ask_and_eval()`.
            `function_values`
                list or array of objective function values
                corresponding to the respective points. Beside for termination
                decisions, only the ranking of values in `function_values`
                is used.
            `check_points`
                If ``check_points is None``, only solutions that are not generated
                by `ask()` are possibly clipped (recommended). ``False`` does not clip
                any solution (not recommended).
                If ``True``, clips solutions that realize long steps (i.e. also
                those that are unlikely to be generated with `ask()`). `check_points`
                can be a list of indices to be checked in solutions.
            `copy`
                ``solutions`` can be modified in this routine, if ``copy is False``

        Details
        -------
        `tell()` updates the parameters of the multivariate
        normal search distribution, namely covariance matrix and
        step-size and updates also the attributes `countiter` and
        `countevals`. To check the points for consistency is quadratic
        in the dimension (like sampling points).

        Bugs
        ----
        The effect of changing the solutions delivered by `ask()` depends on whether
        boundary handling is applied. With boundary handling, modifications are
        disregarded. This is necessary to apply the default boundary handling that
        uses unrepaired solutions but might change in future.

        Example
        -------
        ::

            import cma
            func = cma.fcts.elli  # choose objective function
            es = cma.CMAEvolutionStrategy(cma.np.random.rand(10), 1)
            while not es.stop():
               X = es.ask()
               es.tell(X, [func(x) for x in X])
            es.result()  # where the result can be found

        :See: class `CMAEvolutionStrategy`, `ask()`, `ask_and_eval()`, `fmin()`

        """
    #____________________________________________________________
    # TODO: consider an input argument that flags injected trust-worthy solutions (which means
    #       that they can be treated "absolut" rather than "relative")
        if self.flgtelldone:
            raise _Error('tell should only be called once per iteration')

        lam = len(solutions)
        if lam != array(function_values).shape[0]:
            raise _Error('for each candidate solution '
                        + 'a function value must be provided')
        if lam + self.sp.lam_mirr < 3:
            raise _Error('population size ' + str(lam) + ' is too small when option CMA_mirrors * popsize < 0.5')

        if not np.isscalar(function_values[0]):
            if np.isscalar(function_values[0][0]):
                if self.countiter <= 1:
                    print('WARNING: function values are not a list of scalars (further warnings are suppressed)')
                function_values = [val[0] for val in function_values]
            else:
                raise _Error('objective function values must be a list of scalars')


        ### prepare
        N = self.N
        sp = self.sp
        if 11 < 3 and lam != sp.popsize:  # turned off, because mu should stay constant, still not desastrous
            print('WARNING: population size has changed, recomputing parameters')
            self.sp.set(self.opts, lam)  # not really tested
        if lam < sp.mu:  # rather decrease cmean instead of having mu > lambda//2
            raise _Error('not enough solutions passed to function tell (mu>lambda)')

        self.countiter += 1  # >= 1 now
        self.countevals += sp.popsize * self.evaluations_per_f_value
        self.best.update(solutions, self.sent_solutions, function_values, self.countevals)

        flgseparable = self.opts['CMA_diagonal'] is True \
                       or self.countiter <= self.opts['CMA_diagonal']
        if not flgseparable and len(self.C.shape) == 1:  # C was diagonal ie 1-D
            # enter non-separable phase (no easy return from here)
            self.B = np.eye(N) # identity(N)
            self.C = np.diag(self.C)
            idx = np.argsort(self.D)
            self.D = self.D[idx]
            self.B = self.B[:,idx]
            self.Zneg = np.zeros((N, N))

        ### manage fitness
        fit = self.fit  # make short cut

        # CPU for N,lam=20,200: this takes 10s vs 7s
        fit.bndpen = self.boundPenalty.update(function_values, self)(solutions, self.sent_solutions, self.gp)
        # for testing:
        # fit.bndpen = self.boundPenalty.update(function_values, self)([s.unrepaired for s in solutions])
        fit.idx = np.argsort(array(fit.bndpen) + array(function_values))
        fit.fit = array(function_values, copy=False)[fit.idx]

        # update output data TODO: this is obsolete!? However: need communicate current best x-value?
        # old: out['recent_x'] = self.gp.pheno(pop[0])
        self.out['recent_x'] = array(solutions[fit.idx[0]])  # TODO: change in a data structure(?) and use current as identify
        self.out['recent_f'] = fit.fit[0]

        # fitness histories
        fit.hist.insert(0, fit.fit[0])
        # if len(self.fit.histbest) < 120+30*N/sp.popsize or  # does not help, as tablet in the beginning is the critical counter-case
        if ((self.countiter % 5) == 0):  # 20 percent of 1e5 gen.
            fit.histbest.insert(0, fit.fit[0])
            fit.histmedian.insert(0, np.median(fit.fit) if len(fit.fit) < 21
                                    else fit.fit[self.popsize // 2])
        if len(fit.histbest) > 2e4: # 10 + 30*N/sp.popsize:
            fit.histbest.pop()
            fit.histmedian.pop()
        if len(fit.hist) > 10 + 30*N/sp.popsize:
            fit.hist.pop()

        if self.opts['CMA_AII']:
            self.aii.tell(solutions, function_values)
            self.flgtelldone = True
            # for output:
            self.mean = self.aii.mean
            self.dC = self.aii.sigmai**2
            self.sigma = self.aii.sigma
            self.D = 1e-11 + (self.aii.r**2)**0.5
            self.more_to_write += [self.aii.sigma_r]
            return

        # TODO: clean up inconsistency when an unrepaired solution is available and used
        pop = []  # create pop from input argument solutions
        for s in solutions:  # use phenotype before Solution.repair()
            if use_sent_solutions:
                x = self.sent_solutions.pop(s, None)  # 12.7s vs 11.3s with N,lambda=20,200
                if x is not None:
                    pop.append(x['geno'])
                    # TODO: keep additional infos or don't pop s from sent_solutions in the first place
                else:
                    # print 'WARNING: solution not found in ``self.sent_solutions`` (is expected for injected solutions)'
                    pop.append(self.gp.geno(s, copy=copy))  # cannot recover the original genotype with boundary handling
                    if check_points in (None, True, 1):
                        self.repair_genotype(pop[-1])  # necessary if pop[-1] was changed or injected by the user.
            else:  # TODO: to be removed?
                # print 'WARNING: ``geno`` mapping depreciated'
                pop.append(self.gp.geno(s, copy=copy))
                if check_points in (None, True, 1):
                    self.repair_genotype(pop[-1])  # necessary or not?
                # print 'repaired'

        mold = self.mean
        sigma_fac = 1

        # check and normalize each x - m
        # check_points is a flag (None is default: check non-known solutions) or an index list
        # should also a number possible (first check_points points)?
        if check_points not in (None, False, 0, [], ()):  # useful in case of injected solutions and/or adaptive encoding, however is automatic with use_sent_solutions
            try:
                if len(check_points):
                    idx = check_points
            except:
                idx = xrange(sp.popsize)

            for k in idx:
                self.repair_genotype(pop[k])

        # sort pop
        if type(pop) is not array: # only arrays can be multiple indexed
            pop = array(pop, copy=False)

        pop = pop[fit.idx]

        if self.opts['CMA_elitist'] and self.best.f < fit.fit[0]:
            if self.best.x_geno is not None:
                xp = [self.best.x_geno]
                # xp = [self.best.xdict['geno']]
                # xp = [self.gp.geno(self.best.x[:])]  # TODO: remove
                # print self.mahalanobisNorm(xp[0]-self.mean)
                self.clip_or_fit_solutions(xp, [0])
                pop = array([xp[0]] + list(pop))
            else:
                print('genotype for elitist not found')

        # compute new mean
        self.mean = mold + self.sp.cmean * \
                    (sum(sp.weights * pop[0:sp.mu].T, 1) - mold)


        # check Delta m (this is not default, but could become at some point)
        # CAVE: upper_length=sqrt(2)+2 is too restrictive, test upper_length = sqrt(2*N) thoroughly.
        # simple test case injecting self.mean:
        # self.mean = 1e-4 * self.sigma * np.random.randn(N)
        if 11 < 3 and self.opts['vv'] and check_points:  # TODO: check_points might be an index-list
            cmean = self.sp.cmean / min(1, (sqrt(self.opts['vv']*N)+2) / ( # abuse of cmean
                (sqrt(self.sp.mueff) / self.sp.cmean) *
                self.mahalanobisNorm(self.mean - mold)))
        else:
            cmean = self.sp.cmean

        if 11 < 3:  # plot length of mean - mold
            self.more_to_write += [sqrt(sp.mueff) *
                sum(((1./self.D) * dot(self.B.T, self.mean - mold))**2)**0.5 /
                       self.sigma / sqrt(N) / cmean]

        # get learning rate constants
        cc, c1, cmu = sp.cc, sp.c1, sp.cmu
        if flgseparable:
            cc, c1, cmu = sp.cc_sep, sp.c1_sep, sp.cmu_sep

        # now the real work can start

        # evolution paths
        self.ps = (1-sp.cs) * self.ps + \
                  (sqrt(sp.cs*(2-sp.cs)*sp.mueff)  / self.sigma / cmean) * \
                  dot(self.B, (1./self.D) * dot(self.B.T, (self.mean - mold) / self.sigma_vec))

        # "hsig", correction with self.countiter seems not necessary, also pc starts with zero
        hsig = sum(self.ps**2) / (1-(1-sp.cs)**(2*self.countiter)) / self.N < 2 + 4./(N+1)
        if 11 < 3:
            # hsig = 1
            # sp.cc = 4 / (N + 4)
            # sp.cs = 4 / (N + 4)
            # sp.cc = 1
            # sp.damps = 2  #
            # sp.CMA_on = False
            # c1 = 0  # 2 / ((N + 1.3)**2 + 0 * sp.mu) # 1 / N**2
            # cmu = min([1 - c1, cmu])
            if self.countiter == 1:
                print('parameters modified')
        # hsig = sum(self.ps**2) / self.N < 2 + 4./(N+1)
        # adjust missing variance due to hsig, in 4-D with damps=1e99 and sig0 small
        #       hsig leads to premature convergence of C otherwise
        #hsiga = (1-hsig**2) * c1 * cc * (2-cc)  # to be removed in future
        c1a = c1 - (1-hsig**2) * c1 * cc * (2-cc)  # adjust for variance loss

        if 11 < 3:  # diagnostic data
            self.out['hsigcount'] += 1 - hsig
            if not hsig:
                self.hsiglist.append(self.countiter)
        if 11 < 3:  # diagnostic message
            if not hsig:
                print(str(self.countiter) + ': hsig-stall')
        if 11 < 3:  # for testing purpose
            hsig = 1 # TODO:
            #       put correction term, but how?
            if self.countiter == 1:
                print('hsig=1')

        self.pc = (1-cc) * self.pc + \
                  hsig * (sqrt(cc*(2-cc)*sp.mueff) / self.sigma / cmean) * \
                  (self.mean - mold)  / self.sigma_vec

        # covariance matrix adaptation/udpate
        if sp.CMA_on:
            # assert sp.c1 + sp.cmu < sp.mueff / N  # ??
            assert c1 + cmu <= 1

            # default full matrix case
            if not flgseparable:
                Z = (pop[0:sp.mu] - mold) / (self.sigma * self.sigma_vec)
                Z = dot((cmu * sp.weights) * Z.T, Z)  # learning rate integrated
                if self.sp.neg.cmuexp:
                    tmp = (pop[-sp.neg.mu:] - mold) / (self.sigma * self.sigma_vec)
                    self.Zneg *= 1 - self.sp.neg.cmuexp  # for some reason necessary?
                    self.Zneg += dot(sp.neg.weights * tmp.T, tmp) - self.C
                    # self.update_exponential(dot(sp.neg.weights * tmp.T, tmp) - 1 * self.C, -1*self.sp.neg.cmuexp)

                if 11 < 3: # ?3 to 5 times slower??
                    Z = np.zeros((N,N))
                    for k in xrange(sp.mu):
                        z = (pop[k]-mold)
                        Z += np.outer((cmu * sp.weights[k] / (self.sigma * self.sigma_vec)**2) * z, z)

                self.C *= 1 - c1a - cmu
                self.C += np.outer(c1 * self.pc, self.pc) + Z
                self.dC = np.diag(self.C)  # for output and termination checking

            else: # separable/diagonal linear case
                assert(c1+cmu <= 1)
                Z = np.zeros(N)
                for k in xrange(sp.mu):
                    z = (pop[k]-mold) / (self.sigma * self.sigma_vec) # TODO see above
                    Z += sp.weights[k] * z * z  # is 1-D
                self.C = (1-c1a-cmu) * self.C + c1 * self.pc * self.pc + cmu * Z
                # TODO: self.C *= exp(cmuneg * (N - dot(sp.neg.weights,  **2)
                self.dC = self.C
                self.D = sqrt(self.C)  # C is a 1-D array
                self.itereigenupdated = self.countiter

                # idx = self.mirror_idx_cov()  # take half of mirrored vectors for negative update

        # qqqqqqqqqqq
        if 1 < 3 and np.isfinite(sp.dampsvec):
            if self.countiter == 1:
                print("WARNING: CMA_dampsvec option is experimental")
            sp.dampsvec *= np.exp(sp.dampsvec_fading/self.N)
            # TODO: rank-lambda update: *= (1 + sum(z[z>1]**2-1) * exp(sum(z[z<1]**2-1))
            self.sigma_vec *= np.exp((sp.cs/sp.dampsvec/2) * (self.ps**2 - 1))
            # self.sigma_vec *= np.exp((sp.cs/sp.dampsvec) * (abs(self.ps) - (2/np.pi)**0.5))
            self.more_to_write += [exp(np.mean((self.ps**2 - 1)**2))]
            # TODO: rank-mu update

        # step-size adaptation, adapt sigma
        if 1 < 3:  #
            self.sigma *= sigma_fac * \
                            np.exp((min((1, (sp.cs/sp.damps) *
                                    (sqrt(sum(self.ps**2))/self.const.chiN - 1)))))
        else:
            self.sigma *= sigma_fac * \
                            np.exp((min((1000, (sp.cs/sp.damps/2) *
                                    (sum(self.ps**2)/N - 1)))))
        if 11 < 3:
            # derandomized MSR = natural gradient descent using mean(z**2) instead of mu*mean(z)**2
            lengths = array([sum(z**2)**0.5 for z in self.arz[fit.idx[:self.sp.mu]]])
            # print lengths[0::int(self.sp.mu/5)]
            self.sigma *= np.exp(self.sp.mueff**0.5 * dot(self.sp.weights, lengths / self.const.chiN - 1))**(2/(N+1))

        if 11 < 3 and self.opts['vv']:
            if self.countiter < 2:
                print('constant sigma applied')
                print(self.opts['vv'])  # N=10,lam=10: 0.8 is optimal
            self.sigma = self.opts['vv'] * self.sp.mueff * sum(self.mean**2)**0.5 / N

        if self.sigma * min(self.dC)**0.5 < self.opts['minstd']:
            self.sigma = self.opts['minstd'] / min(self.dC)**0.5
        # g = self.countiter
        # N = self.N
        mindx = eval(self.opts['mindx']) if type(self.opts['mindx']) == type('') else self.opts['mindx']
        if self.sigma * min(self.D) < mindx:  # TODO: sigma_vec is missing here
            self.sigma = mindx / min(self.D)

        if self.sigma > 1e9 * self.sigma0:
            alpha = self.sigma / max(self.D)
            self.multiplyC(alpha)
            self.sigma /= alpha**0.5
            self.opts['tolupsigma'] /= alpha**0.5  # to be compared with sigma

        # TODO increase sigma in case of a plateau?

        # Uncertainty noise measurement is done on an upper level

        # output, has moved up, e.g. as part of fmin, TODO to be removed
        if 11 < 3 and self.opts['verb_log'] > 0 and (self.countiter < 4 or
                                          self.countiter % self.opts['verb_log'] == 0):
            # this assumes that two logger with the same name access the same data!
            CMADataLogger(self.opts['verb_filenameprefix']).register(self, append=True).add()
            # self.writeOutput(solutions[fit.idx[0]])

        self.flgtelldone = True
def tell ( self , solutions , function_values , check_points = None , copy = False ) : #____________________________________________________________ # TODO: consider an input argument that flags injected trust-worthy solutions (which means #       that they can be treated "absolut" rather than "relative") if self . flgtelldone : raise _Error ( 'tell should only be called once per iteration' ) lam = len ( solutions ) if lam != array ( function_values ) . shape [ 0 ] : raise _Error ( 'for each candidate solution ' + 'a function value must be provided' ) if lam + self . sp . lam_mirr < 3 : raise _Error ( 'population size ' + str ( lam ) + ' is too small when option CMA_mirrors * popsize < 0.5' ) if not np . isscalar ( function_values [ 0 ] ) : if np . isscalar ( function_values [ 0 ] [ 0 ] ) : if self . countiter <= 1 : print ( 'WARNING: function values are not a list of scalars (further warnings are suppressed)' ) function_values = [ val [ 0 ] for val in function_values ] else : raise _Error ( 'objective function values must be a list of scalars' ) ### prepare N = self . N sp = self . sp if 11 < 3 and lam != sp . popsize : # turned off, because mu should stay constant, still not desastrous print ( 'WARNING: population size has changed, recomputing parameters' ) self . sp . set ( self . opts , lam ) # not really tested if lam < sp . mu : # rather decrease cmean instead of having mu > lambda//2 raise _Error ( 'not enough solutions passed to function tell (mu>lambda)' ) self . countiter += 1 # >= 1 now self . countevals += sp . popsize * self . evaluations_per_f_value self . best . update ( solutions , self . sent_solutions , function_values , self . countevals ) flgseparable = self . opts [ 'CMA_diagonal' ] is True or self . countiter <= self . opts [ 'CMA_diagonal' ] if not flgseparable and len ( self . C . shape ) == 1 : # C was diagonal ie 1-D # enter non-separable phase (no easy return from here) self . B = np . eye ( N ) # identity(N) self . C = np . diag ( self . C ) idx = np . argsort ( self . D ) self . D = self . D [ idx ] self . B = self . B [ : , idx ] self . Zneg = np . zeros ( ( N , N ) ) ### manage fitness fit = self . fit # make short cut # CPU for N,lam=20,200: this takes 10s vs 7s fit . bndpen = self . boundPenalty . update ( function_values , self ) ( solutions , self . sent_solutions , self . gp ) # for testing: # fit.bndpen = self.boundPenalty.update(function_values, self)([s.unrepaired for s in solutions]) fit . idx = np . argsort ( array ( fit . bndpen ) + array ( function_values ) ) fit . fit = array ( function_values , copy = False ) [ fit . idx ] # update output data TODO: this is obsolete!? However: need communicate current best x-value? # old: out['recent_x'] = self.gp.pheno(pop[0]) self . out [ 'recent_x' ] = array ( solutions [ fit . idx [ 0 ] ] ) # TODO: change in a data structure(?) and use current as identify self . out [ 'recent_f' ] = fit . fit [ 0 ] # fitness histories fit . hist . insert ( 0 , fit . fit [ 0 ] ) # if len(self.fit.histbest) < 120+30*N/sp.popsize or  # does not help, as tablet in the beginning is the critical counter-case if ( ( self . countiter % 5 ) == 0 ) : # 20 percent of 1e5 gen. fit . histbest . insert ( 0 , fit . fit [ 0 ] ) fit . histmedian . insert ( 0 , np . median ( fit . fit ) if len ( fit . fit ) < 21 else fit . fit [ self . popsize // 2 ] ) if len ( fit . histbest ) > 2e4 : # 10 + 30*N/sp.popsize: fit . histbest . pop ( ) fit . histmedian . pop ( ) if len ( fit . hist ) > 10 + 30 * N / sp . popsize : fit . hist . pop ( ) if self . opts [ 'CMA_AII' ] : self . aii . tell ( solutions , function_values ) self . flgtelldone = True # for output: self . mean = self . aii . mean self . dC = self . aii . sigmai ** 2 self . sigma = self . aii . sigma self . D = 1e-11 + ( self . aii . r ** 2 ) ** 0.5 self . more_to_write += [ self . aii . sigma_r ] return # TODO: clean up inconsistency when an unrepaired solution is available and used pop = [ ] # create pop from input argument solutions for s in solutions : # use phenotype before Solution.repair() if use_sent_solutions : x = self . sent_solutions . pop ( s , None ) # 12.7s vs 11.3s with N,lambda=20,200 if x is not None : pop . append ( x [ 'geno' ] ) # TODO: keep additional infos or don't pop s from sent_solutions in the first place else : # print 'WARNING: solution not found in ``self.sent_solutions`` (is expected for injected solutions)' pop . append ( self . gp . geno ( s , copy = copy ) ) # cannot recover the original genotype with boundary handling if check_points in ( None , True , 1 ) : self . repair_genotype ( pop [ - 1 ] ) # necessary if pop[-1] was changed or injected by the user. else : # TODO: to be removed? # print 'WARNING: ``geno`` mapping depreciated' pop . append ( self . gp . geno ( s , copy = copy ) ) if check_points in ( None , True , 1 ) : self . repair_genotype ( pop [ - 1 ] ) # necessary or not? # print 'repaired' mold = self . mean sigma_fac = 1 # check and normalize each x - m # check_points is a flag (None is default: check non-known solutions) or an index list # should also a number possible (first check_points points)? if check_points not in ( None , False , 0 , [ ] , ( ) ) : # useful in case of injected solutions and/or adaptive encoding, however is automatic with use_sent_solutions try : if len ( check_points ) : idx = check_points except : idx = xrange ( sp . popsize ) for k in idx : self . repair_genotype ( pop [ k ] ) # sort pop if type ( pop ) is not array : # only arrays can be multiple indexed pop = array ( pop , copy = False ) pop = pop [ fit . idx ] if self . opts [ 'CMA_elitist' ] and self . best . f < fit . fit [ 0 ] : if self . best . x_geno is not None : xp = [ self . best . x_geno ] # xp = [self.best.xdict['geno']] # xp = [self.gp.geno(self.best.x[:])]  # TODO: remove # print self.mahalanobisNorm(xp[0]-self.mean) self . clip_or_fit_solutions ( xp , [ 0 ] ) pop = array ( [ xp [ 0 ] ] + list ( pop ) ) else : print ( 'genotype for elitist not found' ) # compute new mean self . mean = mold + self . sp . cmean * ( sum ( sp . weights * pop [ 0 : sp . mu ] . T , 1 ) - mold ) # check Delta m (this is not default, but could become at some point) # CAVE: upper_length=sqrt(2)+2 is too restrictive, test upper_length = sqrt(2*N) thoroughly. # simple test case injecting self.mean: # self.mean = 1e-4 * self.sigma * np.random.randn(N) if 11 < 3 and self . opts [ 'vv' ] and check_points : # TODO: check_points might be an index-list cmean = self . sp . cmean / min ( 1 , ( sqrt ( self . opts [ 'vv' ] * N ) + 2 ) / ( # abuse of cmean ( sqrt ( self . sp . mueff ) / self . sp . cmean ) * self . mahalanobisNorm ( self . mean - mold ) ) ) else : cmean = self . sp . cmean if 11 < 3 : # plot length of mean - mold self . more_to_write += [ sqrt ( sp . mueff ) * sum ( ( ( 1. / self . D ) * dot ( self . B . T , self . mean - mold ) ) ** 2 ) ** 0.5 / self . sigma / sqrt ( N ) / cmean ] # get learning rate constants cc , c1 , cmu = sp . cc , sp . c1 , sp . cmu if flgseparable : cc , c1 , cmu = sp . cc_sep , sp . c1_sep , sp . cmu_sep # now the real work can start # evolution paths self . ps = ( 1 - sp . cs ) * self . ps + ( sqrt ( sp . cs * ( 2 - sp . cs ) * sp . mueff ) / self . sigma / cmean ) * dot ( self . B , ( 1. / self . D ) * dot ( self . B . T , ( self . mean - mold ) / self . sigma_vec ) ) # "hsig", correction with self.countiter seems not necessary, also pc starts with zero hsig = sum ( self . ps ** 2 ) / ( 1 - ( 1 - sp . cs ) ** ( 2 * self . countiter ) ) / self . N < 2 + 4. / ( N + 1 ) if 11 < 3 : # hsig = 1 # sp.cc = 4 / (N + 4) # sp.cs = 4 / (N + 4) # sp.cc = 1 # sp.damps = 2  # # sp.CMA_on = False # c1 = 0  # 2 / ((N + 1.3)**2 + 0 * sp.mu) # 1 / N**2 # cmu = min([1 - c1, cmu]) if self . countiter == 1 : print ( 'parameters modified' ) # hsig = sum(self.ps**2) / self.N < 2 + 4./(N+1) # adjust missing variance due to hsig, in 4-D with damps=1e99 and sig0 small #       hsig leads to premature convergence of C otherwise #hsiga = (1-hsig**2) * c1 * cc * (2-cc)  # to be removed in future c1a = c1 - ( 1 - hsig ** 2 ) * c1 * cc * ( 2 - cc ) # adjust for variance loss if 11 < 3 : # diagnostic data self . out [ 'hsigcount' ] += 1 - hsig if not hsig : self . hsiglist . append ( self . countiter ) if 11 < 3 : # diagnostic message if not hsig : print ( str ( self . countiter ) + ': hsig-stall' ) if 11 < 3 : # for testing purpose hsig = 1 # TODO: #       put correction term, but how? if self . countiter == 1 : print ( 'hsig=1' ) self . pc = ( 1 - cc ) * self . pc + hsig * ( sqrt ( cc * ( 2 - cc ) * sp . mueff ) / self . sigma / cmean ) * ( self . mean - mold ) / self . sigma_vec # covariance matrix adaptation/udpate if sp . CMA_on : # assert sp.c1 + sp.cmu < sp.mueff / N  # ?? assert c1 + cmu <= 1 # default full matrix case if not flgseparable : Z = ( pop [ 0 : sp . mu ] - mold ) / ( self . sigma * self . sigma_vec ) Z = dot ( ( cmu * sp . weights ) * Z . T , Z ) # learning rate integrated if self . sp . neg . cmuexp : tmp = ( pop [ - sp . neg . mu : ] - mold ) / ( self . sigma * self . sigma_vec ) self . Zneg *= 1 - self . sp . neg . cmuexp # for some reason necessary? self . Zneg += dot ( sp . neg . weights * tmp . T , tmp ) - self . C # self.update_exponential(dot(sp.neg.weights * tmp.T, tmp) - 1 * self.C, -1*self.sp.neg.cmuexp) if 11 < 3 : # ?3 to 5 times slower?? Z = np . zeros ( ( N , N ) ) for k in xrange ( sp . mu ) : z = ( pop [ k ] - mold ) Z += np . outer ( ( cmu * sp . weights [ k ] / ( self . sigma * self . sigma_vec ) ** 2 ) * z , z ) self . C *= 1 - c1a - cmu self . C += np . outer ( c1 * self . pc , self . pc ) + Z self . dC = np . diag ( self . C ) # for output and termination checking else : # separable/diagonal linear case assert ( c1 + cmu <= 1 ) Z = np . zeros ( N ) for k in xrange ( sp . mu ) : z = ( pop [ k ] - mold ) / ( self . sigma * self . sigma_vec ) # TODO see above Z += sp . weights [ k ] * z * z # is 1-D self . C = ( 1 - c1a - cmu ) * self . C + c1 * self . pc * self . pc + cmu * Z # TODO: self.C *= exp(cmuneg * (N - dot(sp.neg.weights,  **2) self . dC = self . C self . D = sqrt ( self . C ) # C is a 1-D array self . itereigenupdated = self . countiter # idx = self.mirror_idx_cov()  # take half of mirrored vectors for negative update # qqqqqqqqqqq if 1 < 3 and np . isfinite ( sp . dampsvec ) : if self . countiter == 1 : print ( "WARNING: CMA_dampsvec option is experimental" ) sp . dampsvec *= np . exp ( sp . dampsvec_fading / self . N ) # TODO: rank-lambda update: *= (1 + sum(z[z>1]**2-1) * exp(sum(z[z<1]**2-1)) self . sigma_vec *= np . exp ( ( sp . cs / sp . dampsvec / 2 ) * ( self . ps ** 2 - 1 ) ) # self.sigma_vec *= np.exp((sp.cs/sp.dampsvec) * (abs(self.ps) - (2/np.pi)**0.5)) self . more_to_write += [ exp ( np . mean ( ( self . ps ** 2 - 1 ) ** 2 ) ) ] # TODO: rank-mu update # step-size adaptation, adapt sigma if 1 < 3 : # self . sigma *= sigma_fac * np . exp ( ( min ( ( 1 , ( sp . cs / sp . damps ) * ( sqrt ( sum ( self . ps ** 2 ) ) / self . const . chiN - 1 ) ) ) ) ) else : self . sigma *= sigma_fac * np . exp ( ( min ( ( 1000 , ( sp . cs / sp . damps / 2 ) * ( sum ( self . ps ** 2 ) / N - 1 ) ) ) ) ) if 11 < 3 : # derandomized MSR = natural gradient descent using mean(z**2) instead of mu*mean(z)**2 lengths = array ( [ sum ( z ** 2 ) ** 0.5 for z in self . arz [ fit . idx [ : self . sp . mu ] ] ] ) # print lengths[0::int(self.sp.mu/5)] self . sigma *= np . exp ( self . sp . mueff ** 0.5 * dot ( self . sp . weights , lengths / self . const . chiN - 1 ) ) ** ( 2 / ( N + 1 ) ) if 11 < 3 and self . opts [ 'vv' ] : if self . countiter < 2 : print ( 'constant sigma applied' ) print ( self . opts [ 'vv' ] ) # N=10,lam=10: 0.8 is optimal self . sigma = self . opts [ 'vv' ] * self . sp . mueff * sum ( self . mean ** 2 ) ** 0.5 / N if self . sigma * min ( self . dC ) ** 0.5 < self . opts [ 'minstd' ] : self . sigma = self . opts [ 'minstd' ] / min ( self . dC ) ** 0.5 # g = self.countiter # N = self.N mindx = eval ( self . opts [ 'mindx' ] ) if type ( self . opts [ 'mindx' ] ) == type ( '' ) else self . opts [ 'mindx' ] if self . sigma * min ( self . D ) < mindx : # TODO: sigma_vec is missing here self . sigma = mindx / min ( self . D ) if self . sigma > 1e9 * self . sigma0 : alpha = self . sigma / max ( self . D ) self . multiplyC ( alpha ) self . sigma /= alpha ** 0.5 self . opts [ 'tolupsigma' ] /= alpha ** 0.5 # to be compared with sigma # TODO increase sigma in case of a plateau? # Uncertainty noise measurement is done on an upper level # output, has moved up, e.g. as part of fmin, TODO to be removed if 11 < 3 and self . opts [ 'verb_log' ] > 0 and ( self . countiter < 4 or self . countiter % self . opts [ 'verb_log' ] == 0 ) : # this assumes that two logger with the same name access the same data! CMADataLogger ( self . opts [ 'verb_filenameprefix' ] ) . register ( self , append = True ) . add ( ) # self.writeOutput(solutions[fit.idx[0]]) self . flgtelldone = True