def localsearch(self): ''' ''' swapping = True swap_iteration = 0 total_moves = 0 sln = self.solncolumn ids = np.arange(len(sln)) k = int(self.nregions) changed_regions = [1] * k nr = range(k) while swapping: moves_made = 0 regionIds = [r+1 for r in nr if changed_regions[r]] shuffle(regionIds) changed_regions = [0] * k for seed in regionIds: local_swapping = True local_attempts = 0 while local_swapping: local_moves = 0 members = ids[sln == seed].tolist() neighbors = set() for member in members: neighbors |= set(self.w.neighbors[member]) neighbors -= set(members) candidates = [] for neighbor in neighbors: rid = sln[neighbor] block = ids[sln == rid].tolist() if len(block) <= self.floor: continue if check_contiguity(self.w, block, neighbor): candidates.append(neighbor) if not candidates: local_swapping = False else: nc = len(candidates) best = None cv = 0.0 #TODO Needs to be a high positive number with an aspiration func for area in candidates: current_internal = members rid = sln[area] current_outter = ids[sln == rid].tolist() currentwss = self.objective_func([current_internal, current_outter]) new_internal = copy.copy(current_internal) new_outter = copy.copy(current_outter) new_internal.append(area) new_outter.remove(area) newwss = self.objective_func([new_internal, new_outter]) change = newwss - currentwss old_region = int(sln[area]) if (area, old_region) in self.tabulist: continue elif change < cv: best = area cv = change else: pass #Aspiration function here if best: area = best moves_made += 1 old_region = int(sln[area]) #changed_regions is 0 based changed_regions[seed - 1] = 1 changed_regions[old_region - 1] = 1 #print "Moving area: {} from {} to {}".format(area, old_region, seed) sln[area] = seed self.tabulist.appendleft((area, old_region)) self.failures = 0 else: self.failures += 1 local_swapping = False #swapping = False if self.failures >= self.maxfailures: swapping = False if moves_made == 0: swapping = False new_obj = self.objective_func(sln=sln) diversify = False #print sln.reshape(8,8), globalobj with self.lock: current_obj_vector = self.solnspace[:,0] if new_obj < current_obj_vector.all(): sortedidx = np.argsort(current_obj_vector)[::-1] idx = sortedidx[0:self.intensificationsize] for i in idx: self.solnspace[i][1:] = sln self.solnspace[i][0] = new_obj elif new_obj < current_obj_vector[self.index]: self.solnspace[self.index][1:] = sln self.solnspace[self.index][0] = new_obj else: diversify = True if diversify: pass #Manual 1 iteration breaker #self.maxiterations = 0 return
def build_contig_regions(self, num_regions, cardinality, w, maxiter, compact, max_swaps): if compact: grow_region = self.grow_compact else: grow_region = self.grow_free iter = 0 while iter < maxiter: # regionalization setup regions = [] size_pre = 0 counter = -1 area2region = {} self.feasible = False swap_count = 0 cards = copy.copy(cardinality) cards.sort() # try to build largest regions first (pop from end of list) candidates = copy.copy(self.ids) # these are already shuffled # begin building regions while candidates and swap_count < max_swaps: # setup test to determine if swapping is needed if size_pre == len(regions): counter += 1 else: counter = 0 size_pre = len(regions) # test if swapping is needed if counter == len(candidates): # start swapping # swapping simply changes the candidate list swap_in = None # area to become new candidate while swap_in is None: # PEP8 E711 swap_count += 1 swap_out = candidates.pop(0) # area to remove from candidates swap_neighs = copy.copy(w.neighbors[swap_out]) swap_neighs = list(np.random.permutation(swap_neighs)) # select area to add to candidates (i.e. remove from an existing region) for i in swap_neighs: if i not in candidates: join = i # area linking swap_in to swap_out swap_index = area2region[join] swap_region = regions[swap_index] swap_region = list(np.random.permutation(swap_region)) for j in swap_region: # test to ensure region connectivity after removing area swap_region_test = swap_region[:] + [swap_out] if check_contiguity(w, swap_region_test, j): swap_in = j break if swap_in is not None: # PEP8 E711 break else: candidates.append(swap_out) # swapping cleanup regions[swap_index].remove(swap_in) regions[swap_index].append(swap_out) area2region.pop(swap_in) area2region[swap_out] = swap_index candidates.append(swap_in) counter = 0 # setup to build a single region building = True seed = candidates.pop(0) region = [seed] potential = [i for i in w.neighbors[seed] if i in candidates] test_card = cards.pop() # begin building single region while building and len(region) < test_card: if potential: region, candidates, potential = grow_region( w, test_card, region, candidates, potential) else: # not enough potential neighbors to reach test_card size building = False cards.append(test_card) if len(region) in cards: # constructed region matches another candidate region size cards.remove(len(region)) else: # constructed region doesn't match a candidate region size candidates.extend(region) region = [] # cleanup when successful region built if region: regions.append(region) region_index = len(regions) - 1 for i in region: area2region[i] = region_index # area2region needed for swapping # handling of regionalization result if len(regions) < num_regions: # regionalization failed self.ids = list(np.random.permutation(self.ids)) regions = [] iter += 1 else: # regionalization successful self.feasible = True iter = maxiter self.regions = regions