def test_restricted_mating_selection(ref_dirs, evaluator): np.random.seed(200) selection = RestrictedMating(func_comp=comp_by_cv_dom_then_random) problem = C3DTLZ4(n_var=12, n_obj=3) ca_x = np.loadtxt(path_to_test_resource('ctaea', 'c3dtlz4', 'case2', 'preCA.x')) CA = Population.create(ca_x) evaluator.eval(problem, CA) da_x = np.loadtxt(path_to_test_resource('ctaea', 'c3dtlz4', 'case2', 'preDA.x')) DA = Population.create(da_x) evaluator.eval(problem, DA) Hm = Population.merge(CA, DA) n_pop = len(CA) _, rank = NonDominatedSorting().do(Hm.get('F'), return_rank=True) Pc = (rank[:n_pop] == 0).sum() / len(Hm) Pd = (rank[n_pop:] == 0).sum() / len(Hm) P = selection.do(Hm, len(CA)) assert P.shape == (91, 2) if Pc > Pd: assert (P[:, 0] < n_pop).all() else: assert (P[:, 0] >= n_pop).all() assert (P[:, 1] >= n_pop).any() assert (P[:, 1] < n_pop).any()
def test_association(ref_dirs, evaluator): problem = C1DTLZ3(n_var=12, n_obj=3) ca_x = np.loadtxt(path_to_test_resource('ctaea', 'c1dtlz3', 'case3', 'preCA.x')) CA = Population.create(ca_x) evaluator.eval(problem, CA) da_x = np.loadtxt(path_to_test_resource('ctaea', 'c1dtlz3', 'case3', 'preDA.x')) DA = Population.create(da_x) evaluator.eval(problem, DA) off_x = np.loadtxt(path_to_test_resource('ctaea', 'c1dtlz3', 'case3', 'offspring.x')) off = Population.create(off_x) evaluator.eval(problem, off) true_assoc = np.loadtxt(path_to_test_resource('ctaea', 'c1dtlz3', 'case3', 'feasible_rank0.txt')) true_niche = true_assoc[:, 1] true_id = true_assoc[:, 0] sorted_id = np.argsort(true_id) survival = CADASurvival(ref_dirs) mixed = Population.merge(CA, off) survival.ideal_point = np.min(np.vstack((DA.get("F"), mixed.get("F"))), axis=0) fronts = NonDominatedSorting().do(mixed.get("F"), n_stop_if_ranked=len(ref_dirs)) I = np.concatenate(fronts) niche, _ = survival._associate(mixed[I]) sorted_I = np.argsort(I) assert (niche[sorted_I] == true_niche[sorted_id]).all()
def do(self, problem, pop, off, return_indices=False, inplace=False, **kwargs): # this makes it usable as a traditional survival if isinstance(off, int): k = off off = pop[k:] pop = pop[:k] # if the offsprings are simply empty don't do anything if len(off) == 0: return pop assert len(pop) == len(off), "For the replacement pop and off must have the same number of individuals." pop = Population.create(pop) if isinstance(pop, Individual) else pop off = Population.create(off) if isinstance(off, Individual) else off I = self._do(problem, pop, off, **kwargs) if return_indices: return I else: if not inplace: pop = pop.copy() pop[I] = off[I] return pop
def _next(self): sol = self.opt[0] x = sol.get("X") jac, hess = self.gradient_and_hessian(sol) method = "cholesky" func = direction_cholesky if method == "cholesky" else direction_inv direction, decrement, adapted, success = func(jac, hess) # in case we can not calculate the newton direction fall back to the gradient approach if not success: direction = -jac decrement = np.linalg.norm(direction) ** 2 if self.damped: line = LineSearchProblem(self.problem, sol, direction) _next = WolfeSearch().setup(line, evaluator=self.evaluator).run() # _next = wolfe_line_search(self.problem, sol, direction, evaluator=self.evaluator) # if the newton step was not successful, then try the gradient if adapted and (sol.F[0] - _next.F[0]) < 1e-16: _next = inexact_line_search(self.problem, sol, -jac, evaluator=self.evaluator) else: _x = x + direction _next = Solution(X=_x) if isinstance(_next, Individual): _next = Population.create(_next) self.pop = Population.merge(self.opt, _next) if decrement / 2 <= self.eps: self.termination.force_termination = True
def _initialize_infill(self): self.step_size = self.alpha if self.point is None: return Population.new(X=np.copy(self.problem.xl[None, :])) else: return Population.create(self.point)
def _advance(self, **kwargs): # all the elements in the interval a, c, d, b = self.pop # the golden ratio (precomputed constant) R = self.R # if the left solution is better than the right if c.F[0] < d.F[0]: # make the right to be the new right bound and the left becomes the right a, b = a, d d = c # create a new left individual and evaluate c = Individual(X=b.X - R * (b.X - a.X)) self.evaluator.eval(self.problem, c, algorithm=self) self.infills = c # if the right solution is better than the left else: # make the left to be the new left bound and the right becomes the left a, b = c, b c = d # create a new right individual and evaluate d = Individual(X=a.X + R * (b.X - a.X)) self.evaluator.eval(self.problem, d, algorithm=self) self.infills = d # update the population with all the four individuals self.pop = Population.create(a, c, d, b)
def test_update_da(ref_dirs, evaluator): problem = C1DTLZ3(n_var=12, n_obj=3) for i in range(2): ca_x = np.loadtxt(path_to_test_resource('ctaea', 'c1dtlz3', f'case{i + 1}', 'preCA.x')) CA = Population.create(ca_x) evaluator.eval(problem, CA) da_x = np.loadtxt(path_to_test_resource('ctaea', 'c1dtlz3', f'case{i + 1}', 'preDA.x')) DA = Population.create(da_x) evaluator.eval(problem, DA) off_x = np.loadtxt(path_to_test_resource('ctaea', 'c1dtlz3', f'case{i + 1}', 'offspring.x')) off = Population.create(off_x) evaluator.eval(problem, off) survival = CADASurvival(ref_dirs) mixed = Population.merge(CA, off) survival.ideal_point = np.min(np.vstack((DA.get("F"), mixed.get("F"))), axis=0) post_ca_x = np.loadtxt(path_to_test_resource('ctaea', 'c1dtlz3', f'case{i + 1}', 'postCA.x')) CA = Population.create(post_ca_x) evaluator.eval(problem, CA) Hd = Population.merge(DA, off) pDA = survival._updateDA(CA, Hd, 91) true_S1 = [151, 35, 6, 63, 67, 24, 178, 106, 134, 172, 148, 159, 41, 173, 145, 77, 62, 40, 127, 61, 130, 27, 171, 115, 52, 176, 22, 75, 55, 87, 36, 149, 154, 47, 78, 170, 90, 15, 53, 175, 179, 165, 56, 89, 132, 82, 141, 39, 32, 25, 131, 14, 72, 65, 177, 140, 66, 143, 34, 81, 103, 99, 147, 168, 51, 26, 70, 94, 54, 97, 158, 107, 29, 120, 50, 108, 157, 11, 85, 174, 80, 0, 95, 13, 142, 101, 156, 19, 8, 98, 20] true_S2 = [78, 173, 59, 21, 101, 52, 36, 94, 17, 20, 37, 96, 90, 129, 150, 136, 162, 70, 146, 75, 138, 154, 65, 179, 98, 32, 97, 11, 26, 107, 12, 128, 95, 170, 24, 171, 40, 180, 14, 44, 49, 43, 130, 23, 60, 79, 148, 62, 87, 56, 157, 73, 104, 45, 177, 74, 15, 152, 164, 28, 80, 113, 41, 33, 158, 57, 77, 34, 114, 118, 18, 54, 53, 145, 93, 115, 121, 174, 142, 39, 13, 105, 10, 69, 120, 55, 6, 153, 91, 137, 46] if i == 0: assert np.all(pDA == Hd[true_S1]) else: assert np.all(pDA == Hd[true_S2])
def _initialize_infill(self): super()._initialize_infill() a, b = self.a, self.b # set c to be directly in the middle between the two brackets c = Individual(X=(b.X - a.X) / 2) # create a population with all three individuals pop = Population.create(a, b, c) return pop
def test_update(ref_dirs, evaluator): problem = C3DTLZ4(n_var=12, n_obj=3) ca_x = np.loadtxt(path_to_test_resource('ctaea', 'c3dtlz4', 'case2', 'preCA.x')) CA = Population.create(ca_x) evaluator.eval(problem, CA) da_x = np.loadtxt(path_to_test_resource('ctaea', 'c3dtlz4', 'case2', 'preDA.x')) DA = Population.create(da_x) evaluator.eval(problem, DA) off_x = np.loadtxt(path_to_test_resource('ctaea', 'c3dtlz4', 'case2', 'offspring.x')) off = Population.create(off_x) evaluator.eval(problem, off) post_ca_x = np.loadtxt(path_to_test_resource('ctaea', 'c3dtlz4', 'case2', 'postCA.x')) true_pCA = Population.create(post_ca_x) evaluator.eval(problem, true_pCA) post_da_x = np.loadtxt(path_to_test_resource('ctaea', 'c3dtlz4', 'case2', 'postDA.x')) true_pDA = Population.create(post_da_x) evaluator.eval(problem, true_pDA) survival = CADASurvival(ref_dirs) mixed = Population.merge(CA, off) survival.ideal_point = np.array([0., 0., 0.]) pCA, pDA = survival.do(problem, mixed, DA, len(ref_dirs)) pCA_X = set([tuple(x) for x in pCA.get("X")]) tpCA_X = set([tuple(x) for x in true_pCA.get("X")]) pDA_X = set([tuple(x) for x in pDA.get("X")]) tpDA_X = set([tuple(x) for x in true_pDA.get("X")]) assert pCA_X == tpCA_X assert pDA_X == tpDA_X
def _initialize_infill(self): super()._initialize_infill() a, b = self.a, self.b # the golden ratio (precomputed constant) R = self.R # create the left and right in the interval itself c, d = Individual(X=b.X - R * (b.X - a.X)), Individual(X=a.X + R * (b.X - a.X)) # create a population with all four individuals pop = Population.create(a, c, d, b) self.pop, self.infills = pop, pop return pop
def _infill(self): # the offspring population to finally evaluate and attach to the population infills = Population() # find the potential optimal solution in the current population potential_optimal = self._potential_optimal() # for each of those solutions execute the division move for current in potential_optimal: # find the largest dimension the solution has not been evaluated yet nxl, nxu = norm_bounds(current, self.problem) k = np.argmax(nxu - nxl) # the delta value to be used to get left and right - this is one sixth of the range xl, xu = current.get("xl"), current.get("xu") delta = (xu[k] - xl[k]) / 6 # create the left individual left_x = np.copy(current.X) left_x[k] = xl[k] + delta left = Individual(X=left_x) # create the right individual right_x = np.copy(current.X) right_x[k] = xu[k] - delta right = Individual(X=right_x) # update the boundaries for all the points accordingly for ind in [current, left, right]: update_bounds(ind, xl, xu, k, delta) # create the offspring population, evaluate and attach to current population _infill = Population.create(left, right) _infill.set("depth", current.get("depth") + 1) infills = Population.merge(infills, _infill) return infills
def _infill(self): pop_size, cross_parents, cross_off = self.pop_size, self.mating.crossover.n_parents, self.mating.crossover.n_offsprings # do the mating in a random order I = np.random.permutation(len(self.pop))[:self.n_offsprings] # get the parents using the neighborhood selection P = self.selection.do(self.pop, self.n_offsprings, cross_parents, k=I) # do not any duplicates elimination - thus this results in exactly pop_size * n_offsprings offsprings off = self.mating.do(self.problem, self.pop, np.inf, parents=P) # select a random offspring from each mating off = Population.create(*[ np.random.choice(pool) for pool in np.reshape(off, (self.n_offsprings, -1)) ]) # store the indices because of the neighborhood matching in advance self.indices = I return off
def _local_advance(self, **kwargs): # this happens only in the first iteration if self._explr is None: self._explr = self._exploration_move(self._center) else: # whether the last iteration has resulted in a new optimum has_improved = is_better(self._explr, self._center, eps=0.0) # that means that the exploration did not found any new point and was thus unsuccessful if not has_improved: # keep track of the rho values in the normalized space self._rho = self._rho * self.rho # explore around the current center to try finding a suitable direction self._explr = self._exploration_move(self._center) # if we have found a direction in the last iteration to be worth following else: # get the direction which was successful in the last move self._direction = (self._explr.X - self._center.X) # declare the exploration point the new center self._center = self._explr # use the pattern move to get a new trial vector along that given direction self._trial = self._pattern_move(self._center, self._direction) # get the delta sign adjusted for the exploration self._sign = calc_sign(self._direction) # explore around the current center to try finding a suitable direction self._explr = self._exploration_move(self._trial) self.pop = Population.create(self._center, self._explr)
def _advance(self, **kwargs): # all the elements in the interval a, b, c = self.pop # if this is the case then the function is not convex (which means U shaped) if c.F[0] >= a.F[0] or c.F[0] >= b.F[0]: # choose the left side if a smaller than b, or the right side otherwise if a.F[0] <= b.F[0]: a = c else: b = c c = Individual(X=(b.X - a.X) / 2) self.evaluator.eval(self.problem, c, algorithm=self) self.infills = c else: d = quadr_interp(a, b, c) self.evaluator.eval(self.problem, d, algorithm=self) self.infills = d # swap c and d -> make sure d is always on the right of c -> a, c, d, b if c.X[0] > d.X[0]: c, d = d, c # if c is better than d, then d becomes the new right bound if c.F[0] <= d.F[0]: b = d # if d is better than c, then c becomes the new left bound and d the new right bound else: a, c = c, d self.pop = Population.create(a, b, c)
def _advance(self, infills=None, **kwargs): assert infills is not None, "This algorithms uses the AskAndTell interface thus 'infills' must to be provided." # the indices for the creating of offsprings considered in the last generation I = infills.get("index") # the individuals that are considered for the survival later and final survive survivors = [] # now for each of the infill solutions for k, i in enumerate(I): # get the offspring an the parent it is coming from off, parent = infills[k], self.pop[i] # check whether the new solution dominates the parent or not rel = get_relation(parent, off) # if indifferent we add both if rel == 0: survivors.extend([parent, off]) # if offspring dominates parent elif rel == -1: survivors.append(off) # if parent dominates offspring else: survivors.append(parent) # create the population survivors = Population.create(*survivors) # perform a survival to reduce to pop size self.pop[I] = RankAndCrowdingSurvival().do(self.problem, survivors, n_survive=len(I))
def _social_best(self): return Population.create(*[self.opt] * len(self.pop))
def step(self): # initialize all ants to be used in this iteration ants = [] for k in range(self.n_ants): ant = self.ant() ant._initialize(self.problem, self.pheromones) ants.append(ant) active = list(range(self.n_ants)) while len(active) > 0: for k in active: ant = ants[k] if ant.has_next(): ant.next() if self.local_update: e = ant.last() if e is None or e.pheromone is None: raise Exception( "For a local update the ant has to set the pheromones when notified." ) else: self.pheromones.set( e.key, self.pheromones.get(e.key) * ant.alpha + e.pheromone * ant.alpha) # self.pheromones.update(e.key, e.pheromone * ant.alpha) else: ant.finalize() active = [i for i in active if i != k] colony = Population.create(*ants) # this evaluation can be disabled or faked if evaluate_each_ant is false - then the finalize method of the # ant has to set the objective and/or constraint values accordingly self.evaluator.eval(self.problem, colony) set_cv(colony) set_feasibility(colony) # set the current best including the new colony opt = FitnessSurvival().do(problem, Population.merge(colony, self.opt), 1) # do the evaporation after this iteration self.pheromones.evaporate() # select the ants to be used for the global pheromone update if self.global_update == "all": ants_to_update = colony elif self.global_update == "it-best": ants_to_update = FitnessSurvival().do(problem, colony, 1) elif self.global_update == "best": ants_to_update = self.opt else: raise Exception( "Unknown value for global updating the pheromones!") # now spread the pheromones for each ant depending on performance for ant in ants_to_update: for e in ant.path: if e.pheromone is None: raise Exception( "The ant has to set the pheromone of each entry in the path." ) else: self.pheromones.update(e.key, e.pheromone * pheromones.rho) self.pop, self.off = colony, colony self.opt = opt
def _initialize_infill(self, **kwargs): return Population.create(self.x0)
def test_update_ca(ref_dirs, evaluator): problem = C1DTLZ3(n_var=12, n_obj=3) ca_x = np.loadtxt(path_to_test_resource('ctaea', 'c1dtlz3', 'case3', 'preCA.x')) CA = Population.create(ca_x) evaluator.eval(problem, CA) da_x = np.loadtxt(path_to_test_resource('ctaea', 'c1dtlz3', 'case3', 'preDA.x')) DA = Population.create(da_x) evaluator.eval(problem, DA) off_x = np.loadtxt(path_to_test_resource('ctaea', 'c1dtlz3', 'case3', 'offspring.x')) off = Population.create(off_x) evaluator.eval(problem, off) post_ca_x = np.loadtxt(path_to_test_resource('ctaea', 'c1dtlz3', 'case3', 'postCA.x')) true_pCA = Population.create(post_ca_x) evaluator.eval(problem, true_pCA) survival = CADASurvival(ref_dirs) mixed = Population.merge(CA, off) survival.ideal_point = np.min(np.vstack((DA.get("F"), mixed.get("F"))), axis=0) pCA = survival._updateCA(mixed, len(ref_dirs)) pX = set([tuple(x) for x in pCA.get("X")]) tpX = set([tuple(x) for x in true_pCA.get("X")]) assert pX == tpX problem = C1DTLZ1(n_var=9, n_obj=3) ca_x = np.loadtxt(path_to_test_resource('ctaea', 'c1dtlz1', 'preCA.x')) CA = Population.create(ca_x) evaluator.eval(problem, CA) da_x = np.loadtxt(path_to_test_resource('ctaea', 'c1dtlz1', 'preDA.x')) DA = Population.create(da_x) evaluator.eval(problem, DA) off_x = np.loadtxt(path_to_test_resource('ctaea', 'c1dtlz1', 'offspring.x')) off = Population.create(off_x) evaluator.eval(problem, off) post_ca_x = np.loadtxt(path_to_test_resource('ctaea', 'c1dtlz1', 'postCA.x')) true_pCA = Population.create(post_ca_x) evaluator.eval(problem, true_pCA) survival = CADASurvival(ref_dirs) mixed = Population.merge(CA, off) survival.ideal_point = np.min(np.vstack((DA.get("F"), mixed.get("F"))), axis=0) pCA = survival._updateCA(mixed, len(ref_dirs)) pX = set([tuple(x) for x in pCA.get("X")]) tpX = set([tuple(x) for x in true_pCA.get("X")]) assert pX == tpX problem = C3DTLZ4(n_var=12, n_obj=3) ca_x = np.loadtxt(path_to_test_resource('ctaea', 'c3dtlz4', 'case1', 'preCA.x')) CA = Population.create(ca_x) evaluator.eval(problem, CA) da_x = np.loadtxt(path_to_test_resource('ctaea', 'c3dtlz4', 'case1', 'preDA.x')) DA = Population.create(da_x) evaluator.eval(problem, DA) off_x = np.loadtxt(path_to_test_resource('ctaea', 'c3dtlz4', 'case1', 'offspring.x')) off = Population.create(off_x) evaluator.eval(problem, off) post_ca_x = np.loadtxt(path_to_test_resource('ctaea', 'c3dtlz4', 'case1', 'postCA.x')) true_pCA = Population.create(post_ca_x) evaluator.eval(problem, true_pCA) survival = CADASurvival(ref_dirs) mixed = Population.merge(CA, off) survival.ideal_point = np.min(np.vstack((DA.get("F"), mixed.get("F"))), axis=0) pCA = survival._updateCA(mixed, len(ref_dirs)) pX = set([tuple(x) for x in pCA.get("X")]) tpX = set([tuple(x) for x in true_pCA.get("X")]) assert pX == tpX
def _advance(self, **kwargs): repair, crossover, mutation = self.repair, self.mating.crossover, self.mating.mutation pc_pop = self.pc_pop.copy(deep=True) npc_pop = self.npc_pop.copy(deep=True) ############################################################## # PC evolving ############################################################## # Normalise both poulations according to the PC individuals pc_pop, npc_pop = normalize_bothpop(pc_pop, npc_pop) PCObj = pc_pop.get("F") NPCObj = npc_pop.get("F") pc_size = PCObj.shape[0] npc_size = NPCObj.shape[0] ###################################################### # Calculate the Euclidean distance among individuals ###################################################### d = np.zeros((pc_size, pc_size)) d = cdist(PCObj, PCObj, 'euclidean') d[d == 0] = np.inf # Determine the size of the niche if pc_size == 1: radius = 0 else: radius = determine_radius(d, pc_size, self.pc_capacity) # calculate the radius for individual exploration r = pc_size / self.pc_capacity * radius ######################################################## # find the promising individuals in PC for exploration ######################################################## # promising_num: record how many promising individuals in PC promising_num = 0 # count: record how many NPC individuals are located in each PC individual's niche count = np.array([]) d2 = np.zeros((pc_size, npc_size)) d2 = cdist(PCObj, NPCObj, 'euclidean') # Count of True elements in each row (each individual in PC) of 2D Numpy Array count = np.count_nonzero(d2 <= r, axis=1) # Check if the niche has no NPC individual or has only one NPC individual # Record the indices of promising individuals. # Since np.nonzero() returns a tuple of arrays, we change the type of promising_index to a numpy.ndarray. promising_index = np.nonzero(count <= 1) promising_index = np.asarray(promising_index).flatten() # Record total number of promising individuals in PC for exploration promising_num = len(promising_index) ######################################## # explore these promising individuals ######################################## original_size = pc_size off = Individual() if promising_num > 0: for i in range(promising_num): if original_size > 1: parents = Population.new(2) # The explored individual is considered as one parent parents[0] = pc_pop[promising_index[i]] # The remaining parent will be selected randomly from the PC population rnd = np.random.permutation(pc_size) for j in rnd: if j != promising_index[i]: parents[1] = pc_pop[j] break index = np.array([0, 1]) parents_shape = index[None, :] # do recombination and create an offspring off = crossover.do(self.problem, parents, parents_shape)[0] else: off = pc_pop[0] # mutation off = Population.create(off) off = mutation.do(self.problem, off) # evaluate the offspring self.evaluator.eval(self.problem, off) # update the PC population by the offspring self.pc_pop = update_PCpop(self.pc_pop, off) # update the ideal point self.ideal = np.min(np.vstack([self.ideal, off.get("F")]), axis=0) # update at most one solution in NPC population self.npc_pop = update_NPCpop(self.npc_pop, off, self.ideal, self.ref_dirs, self.decomp) ######################################################## # NPC evolution based on MOEA/D ######################################################## # iterate for each member of the population in random order for i in np.random.permutation(len(self.npc_pop)): # get the parents using the neighborhood selection P = self.selection.do(self.npc_pop, 1, self.mating.crossover.n_parents, k=[i]) # perform a mating using the default operators (recombination & mutation) - if more than one offspring just pick the first off = self.mating.do(self.problem, self.npc_pop, 1, parents=P)[0] off = Population.create(off) # evaluate the offspring self.evaluator.eval(self.problem, off, algorithm=self) # update the PC population by the offspring self.pc_pop = update_PCpop(self.pc_pop, off) # update the ideal point self.ideal = np.min(np.vstack([self.ideal, off.get("F")]), axis=0) # now actually do the replacement of the individual is better self.npc_pop = self._replace(i, off) ######################################################## # population maintenance operation in the PC evolution ######################################################## current_pop = Population.merge(self.pc_pop, self.npc_pop) current_pop = Population.merge(current_pop, self.pop) # filter duplicate in the population pc_pop = self.eliminate_duplicates.do(current_pop) pc_size = len(pc_pop) if (pc_size > self.pc_capacity): # get the objective space values and objects pc_objs = pc_pop.get("F") fronts, rank = NonDominatedSorting().do(pc_objs, return_rank=True) front_0_index = fronts[0] # put the nondominated individuals of the NPC population into the PC population self.pc_pop = pc_pop[front_0_index] if len(self.pc_pop) > self.pc_capacity: self.pc_pop = maintain_PCpop(self.pc_pop, self.pc_capacity) self.pop = self.pc_pop.copy(deep=True)
def _advance(self, **kwargs): problem, evaluator = self.problem, self.evaluator # add the box constraints defined in the problem bounds = None if self.use_bounds: xl, xu = self.problem.bounds() if self.with_bounds: bounds = np.column_stack([xl, xu]) else: if xl is not None or xu is not None: raise Exception( f"Error: Boundary constraints can not be handled by {self.method}" ) # define the actual constraints if supported by the algorithm constr = [] if self.use_constr: constr = [LinearConstraint(np.eye(self.problem.n_var), xl, xu)] if problem.has_constraints(): if self.with_constr: def fun_constr(x): g, cv = problem.evaluate(x, return_values_of=["G", "CV"]) return cv[0] non_lin_constr = NonlinearConstraint( fun_constr, -float("inf"), 0) constr.append(non_lin_constr) else: raise Exception( f"Error: Constraint handling is not supported by {self.method}" ) # the objective function to be optimized and add gradients if available if self.estm_gradients: jac = None def fun_obj(x): f = problem.evaluate(x, return_values_of=["F"])[0] evaluator.n_eval += 1 return f else: jac = True def fun_obj(x): f, df = problem.evaluate(x, return_values_of=["F", "dF"]) if df is None: raise Exception( "If the gradient shall not be estimate, please set out['dF'] in _evaluate. " ) evaluator.n_eval += 1 return f[0], df[0] # the arguments to be used kwargs = dict(args=(), method=self.method, bounds=bounds, constraints=constr, jac=jac, options=self.options) # the starting solution found by sampling beforehand x0 = self.opt[0].X # actually run the optimization if not self.show_warnings: warnings.simplefilter("ignore") res = scipy_minimize(fun_obj, x0, **kwargs) opt = Population.create(Individual(X=res.x)) self.evaluator.eval(self.problem, opt, algorithm=self) self.pop, self.off = opt, opt self.termination.force_termination = True if hasattr("res", "nit"): self.n_gen = res.nit + 1
def do(self, problem, *args, **kwargs): pop = Population.create(*args) parents = np.arange(len(args))[None, :] return self.crossover.do(problem, pop, parents, **kwargs)