def shaking(self, par: Any, result: Result): """Scheduler method that performs shaking by randomly assigning a different color to 'par' many random vertices that are involved in conflicts. """ under_conflict = [] result.changed = False for u in range(len(self.x)): for v in self.inst.graph.adj[u]: if self.x[u] == self.x[v]: # Conflict found under_conflict.append(u) break for _ in range(par): if len(under_conflict) == 0: return u = np.random.choice(under_conflict) # Pick random color (different from current) rand_col = np.random.randint(0, self.inst.colors - 1) if rand_col >= self.x[u]: rand_col += 1 self.x[u] = rand_col self.invalidate() result.changed = True # Prevent this vertex from getting changed again under_conflict.remove(u)
def local_improve(self, _par: Any, result: Result): """Scheduler method that performs one iteration of a local search following a first improvement strategy. The neighborhood used is defined by all solutions that can be created by changing the color of a vertex involved in a conflict. """ n = len(self.x) order = np.arange(n) np.random.shuffle(order) for p in order: nbh_col = {} for col in range(self.inst.colors): nbh_col[col] = 0 for adj in self.inst.graph.adj[p]: nbh_col[self.x[adj]] += 1 old_col = self.x[p] if nbh_col[old_col] > 0: # violation found for new_col in range(self.inst.colors): if nbh_col[new_col] < nbh_col[old_col]: # Possible improvement found self.x[p] = new_col self.obj_val -= nbh_col[old_col] self.obj_val += nbh_col[new_col] result.changed = True return result.changed = False
def __new__(cls, sol: Solution, meths_ch: List[Method], own_settings: dict = None): """Create population of mh_pop_size solutions using the list of construction heuristics if given. If sol is None or no constructors are given, the population is initialized empty. sol itself is just used as template for obtaining further solutions. """ own_settings = OwnSettings(own_settings) if own_settings else settings size = own_settings.mh_pop_size obj = super(Population, cls).__new__(cls, size, Solution) obj.own_settings = own_settings if sol is not None and meths_ch: # cycle through construction heuristics to generate population # perform all construction heuristics, take best solution meths_cycle = cycle(meths_ch) idx = 0 while idx < size: m = next(meths_cycle) sol = sol.copy() res = Result() m.func(sol, m.par, res) if own_settings.mh_pop_dupelim and obj.duplicates_of( sol) != []: continue # do not add this duplicate obj[idx] = sol if res.terminate: break idx += 1 return obj
def perform_method_pair_in_worker(params: Tuple[Method, Method, Solution])\ -> Tuple[Method, Method, Solution, Result, TObj, float, float]: """Performs the given destroy and repair operator pair on the given solution in a worker process.""" destroy, repair, sol = params res = Result() obj_old = sol.obj() t_start = time.process_time() destroy.func(sol, destroy.par, res) t_destroyed = time.process_time() repair.func(sol, repair.par, res) t_end = time.process_time() return destroy, repair, sol, res, obj_old, t_destroyed - t_start, t_end - t_destroyed
def local_improve(self, _par: Any, result: Result): """Scheduler method that performs one iteration of the exchange neighborhood.""" if not self.two_exchange_random_fill_neighborhood_search(False): result.changed = False