def _diversify_soln(core_soln_column, neighbordict,z, floor_variable,lockSoln): #Initialize a local swap space to store n best diversified soln - these do not need to be better div_soln_space = np.empty(sharedSoln.shape) div_soln_space[:] = np.inf div_variance = np.array([sharedVar[:,core_soln_column]] * sharedVar.shape[1]).T workingSoln = np.copy(sharedSoln[0:,core_soln_column]) workingVar = np.copy(sharedVar[:,core_soln_column]) #Iterate through the regions and check all moves, store the 4 best. for region in np.unique(workingSoln[1:]): members = np.where(workingSoln == region)[0] neighbors = [] for member in members: candidates = neighbordict[member-1]#neighbordict is 0 based, member is 1 based candidates = [candidate for candidate in candidates if candidate not in members] candidates = [candidate for candidate in candidates if candidate not in neighbors] neighbors.extend(candidates) candidates = [] #Iterate through the neighbors for neighbor in neighbors: neighborSoln = np.copy(workingSoln[1:]) #Pull a copy of the local working version old_membership = neighborSoln[neighbor]#Track where we started to check_floor neighborSoln[neighbor] = region #Move the neighbor into the new region in the copy #Check the floor floor_check = True if not np.sum(floor_variable[neighborSoln == old_membership]) >= floor: continue if not np.sum(floor_variable[neighborSoln == region]) >= floor: continue #Check contiguity of the swap block = np.where(workingSoln[1:] == neighbor)[0].tolist() if not check_contiguity(neighbordict, block, neighbor): continue #Compute the local variance varcopy = np.copy(workingVar) varcopy[old_membership] = np.var(z[neighborSoln == old_membership]) varcopy[region] = np.var(z[neighborSoln == region]) varcopy[0] = np.sum(varcopy[1:]) if np.any(div_soln_space[0] == np.inf): column = np.where(np.isinf(div_soln_space[0]) == True)[0][0] div_soln_space[1:,column] = neighborSoln[:] div_soln_space[0:,column][0] = varcopy[0] div_variance[:,column] = varcopy else: column = np.argmax(div_soln_space[0]) div_soln_space[1:,column] = neighborSoln[:] div_soln_space[0:,column][0] = varcopy[0] div_variance[:,column] = varcopy #Write one of the neighbor perturbations to the shared memory space to work on. valid = np.where(div_soln_space[0] != np.inf)[0] #print sharedVar[:,core_soln_column] try: selection = randint(0,len(valid)-1) with lockSoln: sharedSoln[:,core_soln_column] = div_soln_space[:,selection] with lockVar: sharedVar[:,core_soln_column] = div_variance[:,selection] #print sharedVar[:,core_soln_column] except: pass #print div_soln_space[0] print "Attempt to diversify failed."
def swap(self): swapping = True swap_iteration = 0 if self.verbose: print 'Initial solution, objective function: ', self.objective_function() total_moves = 0 self.k = len(self.regions) changed_regions = [1] * self.k nr = range(self.k) while swapping: moves_made = 0 regionIds = [r for r in nr if changed_regions[r]] np.random.permutation(regionIds) changed_regions = [0] * self.k swap_iteration += 1 for seed in regionIds: local_swapping = True local_attempts = 0 while local_swapping: local_moves = 0 # get neighbors members = self.regions[seed] neighbors = [] for member in members: candidates = self.w.neighbors[member] candidates = [candidate for candidate in candidates if candidate not in members] candidates = [candidate for candidate in candidates if candidate not in neighbors] neighbors.extend(candidates) candidates = [] for neighbor in neighbors: block = copy.copy(self.regions[self.area2region[ neighbor]]) if check_contiguity(self.w, block, neighbor): block.remove(neighbor) fv = self.check_floor(block) if fv: candidates.append(neighbor) # find the best local move if not candidates: local_swapping = False else: nc = len(candidates) moves = np.zeros([nc, 1], float) best = None cv = 0.0 for area in candidates: current_internal = self.regions[seed] current_outter = self.regions[self.area2region[ area]] current = self.objective_function([current_internal, current_outter]) new_internal = copy.copy(current_internal) new_outter = copy.copy(current_outter) new_internal.append(area) new_outter.remove(area) new = self.objective_function([new_internal, new_outter]) change = new - current if change < cv: best = area cv = change if best: # make the move area = best old_region = self.area2region[area] self.regions[old_region].remove(area) self.area2region[area] = seed self.regions[seed].append(area) moves_made += 1 changed_regions[seed] = 1 changed_regions[old_region] = 1 else: # no move improves the solution local_swapping = False local_attempts += 1 if self.verbose: print 'swap_iteration: ', swap_iteration, 'moves_made: ', moves_made print 'number of regions: ', len(self.regions) print 'number of changed regions: ', sum( changed_regions) print 'internal region: ', seed, 'local_attempts: ', local_attempts print 'objective function: ', self.objective_function() print 'smallest region size: ',min([len(region) for region in self.regions]) total_moves += moves_made if moves_made == 0: swapping = False self.swap_iterations = swap_iteration self.total_moves = total_moves if self.verbose: print 'moves_made: ', moves_made print 'objective function: ', self.objective_function()
def tabu_search(core, z, neighbordict,numP,w,floor, floor_variable,lockSoln, lockflag,lockVar, maxfailures=50,maxiterations=15): ##Pseudo constants pid = mp.current_process()._identity[0] tabu_list = deque(maxlen=sharedupdate[2][core])#What is this core's tabu list length? maxiterations *= cores #Test synchronize cores to exit at the same time. maxfailures += int(maxfailures*uniform(-1.1, 1.2))#James et. al 2007 def _tabu_check(tabu_list, neighbor, region, old_membership): if tabu_list:#If we have a deque with contents for tabu_region in(tabu_list): if neighbor == tabu_region[0]: #print neighbor, tabu_region[0] if region == tabu_region[1] and old_membership == tabu_region[2]: return False def _diversify_soln(core_soln_column, neighbordict,z, floor_variable,lockSoln): #Initialize a local swap space to store n best diversified soln - these do not need to be better div_soln_space = np.empty(sharedSoln.shape) div_soln_space[:] = np.inf div_variance = np.array([sharedVar[:,core_soln_column]] * sharedVar.shape[1]).T workingSoln = np.copy(sharedSoln[0:,core_soln_column]) workingVar = np.copy(sharedVar[:,core_soln_column]) #Iterate through the regions and check all moves, store the 4 best. for region in np.unique(workingSoln[1:]): members = np.where(workingSoln == region)[0] neighbors = [] for member in members: candidates = neighbordict[member-1]#neighbordict is 0 based, member is 1 based candidates = [candidate for candidate in candidates if candidate not in members] candidates = [candidate for candidate in candidates if candidate not in neighbors] neighbors.extend(candidates) candidates = [] #Iterate through the neighbors for neighbor in neighbors: neighborSoln = np.copy(workingSoln[1:]) #Pull a copy of the local working version old_membership = neighborSoln[neighbor]#Track where we started to check_floor neighborSoln[neighbor] = region #Move the neighbor into the new region in the copy #Check the floor floor_check = True if not np.sum(floor_variable[neighborSoln == old_membership]) >= floor: continue if not np.sum(floor_variable[neighborSoln == region]) >= floor: continue #Check contiguity of the swap block = np.where(workingSoln[1:] == neighbor)[0].tolist() if not check_contiguity(neighbordict, block, neighbor): continue #Compute the local variance varcopy = np.copy(workingVar) varcopy[old_membership] = np.var(z[neighborSoln == old_membership]) varcopy[region] = np.var(z[neighborSoln == region]) varcopy[0] = np.sum(varcopy[1:]) if np.any(div_soln_space[0] == np.inf): column = np.where(np.isinf(div_soln_space[0]) == True)[0][0] div_soln_space[1:,column] = neighborSoln[:] div_soln_space[0:,column][0] = varcopy[0] div_variance[:,column] = varcopy else: column = np.argmax(div_soln_space[0]) div_soln_space[1:,column] = neighborSoln[:] div_soln_space[0:,column][0] = varcopy[0] div_variance[:,column] = varcopy #Write one of the neighbor perturbations to the shared memory space to work on. valid = np.where(div_soln_space[0] != np.inf)[0] #print sharedVar[:,core_soln_column] try: selection = randint(0,len(valid)-1) with lockSoln: sharedSoln[:,core_soln_column] = div_soln_space[:,selection] with lockVar: sharedVar[:,core_soln_column] = div_variance[:,selection] #print sharedVar[:,core_soln_column] except: pass #print div_soln_space[0] print "Attempt to diversify failed." ##This shows that we are operating asynchronously. #if core ==2: #time.sleep(5) while sum(sharedupdate[1]) < maxiterations: core_soln_column = (core + sharedupdate[1][core])%len(sharedupdate[1]) if sharedupdate[0][core_soln_column] == False: _diversify_soln(core_soln_column, neighbordict,z, floor_variable,lockSoln) #Li, et. al (in press - P-Compact_Regions) #print "ProcessID %i is processing soln column %i in iteration %i."%(pid, core_soln_column,sharedupdate[1][core]) #Uncomment to see that cores move around the search space failures = 0 #The total local failure counter local_best_variance = sharedSoln[:,core_soln_column][0] workingSoln = np.copy(sharedSoln[:,core_soln_column]) workingVar = np.copy(sharedVar[:,core_soln_column]) while failures <= maxfailures: #Select a random starting point in the search space. nr = np.unique(workingSoln[1:]) #This is 0 based, ie. region 0 - region 31 regionIDs = nr changed_regions = np.ones(len(nr)) randstate = RandomState(pid) #To 'unsync' the cores we need to instantiate a random class with a unique seed. randstate.shuffle(regionIDs) #shuffle the regions so we start with a random region changed_regions[:] = 0 swap_flag = False #Flag to stop looping prior to max iterations if we are not improving. #Iterate through the regions, checking potential swaps for region in regionIDs: members = np.where(workingSoln == region)[0] #get the members of the region #Get the neighbors to the members. Grab only those that could change. neighbors = [] for member in members: candidates = neighbordict[member-1]#neighbordict is 0 based, member is 1 based candidates = [candidate for candidate in candidates if candidate not in members] candidates = [candidate for candidate in candidates if candidate not in neighbors] neighbors.extend(candidates) candidates = [] #Iterate through the neighbors for neighbor in neighbors: neighborSoln = np.copy(workingSoln[1:]) #Pull a copy of the local working version old_membership = neighborSoln[neighbor]#Track where we started to check_floor #For whatever reason candidates block is adding other units in the region, ie. we test moving from region 1 to region 1... '''ToDO: Check the candidates code above, something is wrong with it...testing more than necessary''' if old_membership == region: continue #Check the tabu list tabu_move_check = _tabu_check(tabu_list, neighbor, region, old_membership) if tabu_move_check is not None: continue neighborSoln[neighbor] = region #Move the neighbor into the new region in the copy #Check the floor floor_check = True if not np.sum(floor_variable[neighborSoln == old_membership]) >= floor: continue if not np.sum(floor_variable[neighborSoln == region]) >= floor: continue #Compute the local variance varcopy = np.copy(workingVar) varcopy[old_membership] = np.var(z[neighborSoln== old_membership]) varcopy[region] = np.var(z[neighborSoln == region]) varcopy[0] = np.sum(varcopy[1:]) #Check the locally compute varaince against current working best. if varcopy[0] >= workingSoln[0]: continue #Check contiguity of the swap block = np.where(workingSoln[1:] == neighbor)[0].tolist() if not check_contiguity(neighbordict, block, neighbor): #print "Failed contiguity check" continue #After this we have passed all tests, a check of all possible swaps has yielded a better one. swap_flag = True workingSoln[0] = varcopy[0] workingSoln[1:] = neighborSoln[:] workingVar = varcopy tabu_list.appendleft((neighbor,old_membership,region)) if swap_flag == False: failures += 1 with lockSoln and lockflag: sharedupdate[0][core_soln_column] = 0 sharedSoln[:,core_soln_column] if workingSoln[0] < sharedSoln[:,core_soln_column][0]: sharedSoln[:,core_soln_column] = workingSoln[:] sharedupdate[0][core_soln_column] = 1 #Set the update flag to true if not workingSoln[0] < sharedSoln[0].any(): results = set_half_to_best(len(sharedSoln[0])) with lockVar: sharedVar[:,core_soln_column] = workingVar for result in results: sharedVar[:,result] = workingVar #Increment the core iteration counter sharedupdate[1][core] += 1
def swap(self): swapping = True swap_iteration = 0 if self.verbose: print 'Initial solution, objective function: ', self.objective_function( ) total_moves = 0 self.k = len(self.regions) changed_regions = [1] * self.k nr = range(self.k) while swapping: moves_made = 0 regionIds = [r for r in nr if changed_regions[r]] np.random.permutation(regionIds) changed_regions = [0] * self.k swap_iteration += 1 for seed in regionIds: local_swapping = True local_attempts = 0 while local_swapping: local_moves = 0 # get neighbors members = self.regions[seed] neighbors = [] for member in members: candidates = self.w.neighbors[member] candidates = [ candidate for candidate in candidates if candidate not in members ] candidates = [ candidate for candidate in candidates if candidate not in neighbors ] neighbors.extend(candidates) candidates = [] for neighbor in neighbors: block = copy.copy( self.regions[self.area2region[neighbor]]) if check_contiguity(self.w, block, neighbor): block.remove(neighbor) fv = self.check_floor(block) if fv: candidates.append(neighbor) # find the best local move if not candidates: local_swapping = False else: nc = len(candidates) moves = np.zeros([nc, 1], float) best = None cv = 0.0 for area in candidates: current_internal = self.regions[seed] current_outter = self.regions[ self.area2region[area]] current = self.objective_function( [current_internal, current_outter]) new_internal = copy.copy(current_internal) new_outter = copy.copy(current_outter) new_internal.append(area) new_outter.remove(area) new = self.objective_function( [new_internal, new_outter]) change = new - current if change < cv: best = area cv = change if best: # make the move area = best old_region = self.area2region[area] self.regions[old_region].remove(area) self.area2region[area] = seed self.regions[seed].append(area) moves_made += 1 changed_regions[seed] = 1 changed_regions[old_region] = 1 else: # no move improves the solution local_swapping = False local_attempts += 1 if self.verbose: print 'swap_iteration: ', swap_iteration, 'moves_made: ', moves_made print 'number of regions: ', len(self.regions) print 'number of changed regions: ', sum( changed_regions) print 'internal region: ', seed, 'local_attempts: ', local_attempts print 'objective function: ', self.objective_function() print 'smallest region size: ', min( [len(region) for region in self.regions]) total_moves += moves_made if moves_made == 0: swapping = False self.swap_iterations = swap_iteration self.total_moves = total_moves if self.verbose: print 'moves_made: ', moves_made print 'objective function: ', self.objective_function()
def swapfunc(self, seed, shared_list, shared_lock, smoves): #shared_list[seed].append(self.regions[seed]) # file1 = open("/home/vsindhu1/runtimeswap.txt","a") psttm = time.time() members = shared_list[seed] m_made = 0 neighbors = [] for member in members: candidates = self.w.neighbors[member] candidates = [ candidate for candidate in candidates if candidate not in members ] candidates = [ candidate for candidate in candidates if candidate not in neighbors ] neighbors.extend(candidates) candidates = [] try: for neighbor in neighbors: block = copy.copy(shared_list[self.area2region[neighbor]]) if check_contiguity(self.w, block, neighbor): block.remove(neighbor) fv = self.check_floor(block) if fv: candidates.append(neighbor) except: pass # find the best local move if candidates: nc = len(candidates) moves = np.zeros([nc, 1], float) best = None cv = 0.0 try: for area in candidates: current_internal = shared_list[seed] current_outter = shared_list[self.area2region[area]] current = self.objective_function( [current_internal, current_outter]) new_internal = copy.copy(current_internal) new_outter = copy.copy(current_outter) new_internal.append(area) new_outter.remove(area) new = self.objective_function([new_internal, new_outter]) change = new - current if change < cv: best = area cv = change except: pass if best: # make the move lcksttm = time.time() old_region = self.area2region[best] lock1 = shared_lock[old_region] lock2 = shared_lock[seed] if old_region < seed: lock1.acquire() lock2.acquire() else: lock2.acquire() lock1.acquire() # lck.acquire() #print("Started") #print("Best: ", best) area = best # old_region = self.area2region[area] # shared_lock[old_region].acquire() #print("Area: ", area) #print("Old Region: ", old_region) #print("A Regions before swap: ", shared_list) try: ls = copy.copy(shared_list[self.area2region[neighbor]]) fv1 = self.check_floor(ls) if fv1: so_list = shared_list[old_region] so_list.remove(area) shared_list[old_region] = so_list self.area2region[area] = seed ss_list = shared_list[seed] ss_list.append(area) shared_list[seed] = ss_list m_made += 1 smoves.value += 1 except: pass #print("A Regions after swap: ", shared_list) #changed_regions[seed] = 1 #changed_regions[old_region] = 1 #print("Ended") # lck.release() # shared_lock[old_region].release() # shared_lock[seed].release() # shared_lock[old_region].acquire() if old_region < seed: lock2.release() lock1.release() else: lock1.release() lock2.release() # file1.write("Total Lock Time: %s\n" % str(seed)) # file1.write("%s \n" % (time.time() - lcksttm)) # print("Total Lock Time: ",seed,": ", time.time() - lcksttm) # print("Total Process Time: ",seed,": ", time.time() - psttm) # print("Number of areas: ",seed,": ",len(shared_list[seed])) # file1.write("Total Process Time: %s\n" % str(seed)) # file1.write("%s \n" % (time.time() - psttm)) # file1.close() return m_made
def _diversify_soln(core_soln_column, neighbordict,z, floor_variable,lockSoln): ''' The goal of this function is to diversify a soln that is not improving. What about the possability of diversifying a good answer away from 'the soln?' I do no think that that should be an issue - we make a randomized greedy swap. Is one enough? Rationale: This is a randomized Greedy swap (GRASP), where we store the best n permutations and then randomly select the one we will use. Originally in Li et. al (in press). We need to test different values of n to see what the impact is. ''' #print "Diversifying: ", sharedSoln[0] #Initialize a local swap space to store n best diversified soln - these do not need to be better div_soln_space = np.ndarray(sharedSoln.shape) div_soln_space[:] = float("inf") workingcopy = np.copy(sharedSoln[0:,core_soln_column]) #Iterate through the regions and check all moves, store the 4 best. for region in np.unique(workingcopy[1:]): members = np.where(workingcopy == region)[0] neighbors = [] for member in members: candidates = neighbordict[member-1]#neighbordict is 0 based, member is 1 based candidates = [candidate for candidate in candidates if candidate not in members] candidates = [candidate for candidate in candidates if candidate not in neighbors] neighbors.extend(candidates) candidates = [] #Iterate through the neighbors for neighbor in neighbors: neighborcopy = np.copy(workingcopy[:]) #Pull a copy of the local working version old_membership = neighborcopy[neighbor]#Track where we started to check_floor neighborcopy[neighbor] = region #Move the neighbor into the new region in the copy #Here we start to check the swap and see if it is better swap_var = objective_function_vec(neighborcopy[1:],z)#Variance of the new swap if not swap_var < div_soln_space[0].any(): block = np.where(workingcopy[1:] == neighbor)[0]#A list of the members in a region. block=block.tolist() #For current contiguity check if check_contiguity(neighbordict, block, neighbor):#Check contiguity if check_floor(np.where(neighborcopy[1:,]==region)[0], floor_variable, w) and check_floor(np.where(neighborcopy[1:,]==old_membership)[0],floor_variable,w): neighborcopy[0] = swap_var if not np.isinf(div_soln_space[0].any()): div_soln_space[:,np.argmax(div_soln_space[0])] = neighborcopy[:] else: div_soln_space[:,np.argmin(div_soln_space[0])] = neighborcopy[:] else: del neighborcopy #print "Swap failed due to floor_check." else: del neighborcopy #print "Swap failed due to contiguity." #It is possible that the perturbation will not generate enough soln to fill the space, # so we need to ignore those columns with variance = infinity. #Write one of the neighbor perturbations to the shared memory space to work on. valid = np.where(div_soln_space[0] != np.inf)[0] try: selection = randint(0,len(valid)-1) with lockSoln: sharedSoln[:,core_soln_column] = div_soln_space[:,selection] print "Diversified to:", sharedSoln[0] except: print div_soln_space[0] print "Attempt to diversify failed."
def tabu_search(core, z, neighbordict,numP,w,floor_variable,lockSoln, lockflag, maxfailures=15,maxiterations=10): ##Pseudo constants pid = mp.current_process()._identity[0] tabu_list = deque(maxlen=sharedupdate[2][core])#What is this core's tabu list length? maxiterations *= cores #Test synchronize cores to exit at the same time. maxfailures += int(maxfailures*uniform(-1.1, 1.2))#James et. al 2007 def _tabu_check(tabu_list, neighbor, region, old_membership): if tabu_list:#If we have a deque with contents for tabu_region in(tabu_list): if neighbor == tabu_region[0]: #print neighbor, tabu_region[0] if region == tabu_region[1] and old_membership == tabu_region[2]: return False def _diversify_soln(core_soln_column, neighbordict,z, floor_variable,lockSoln): ''' The goal of this function is to diversify a soln that is not improving. What about the possability of diversifying a good answer away from 'the soln?' I do no think that that should be an issue - we make a randomized greedy swap. Is one enough? Rationale: This is a randomized Greedy swap (GRASP), where we store the best n permutations and then randomly select the one we will use. Originally in Li et. al (in press). We need to test different values of n to see what the impact is. ''' #print "Diversifying: ", sharedSoln[0] #Initialize a local swap space to store n best diversified soln - these do not need to be better div_soln_space = np.ndarray(sharedSoln.shape) div_soln_space[:] = float("inf") workingcopy = np.copy(sharedSoln[0:,core_soln_column]) #Iterate through the regions and check all moves, store the 4 best. for region in np.unique(workingcopy[1:]): members = np.where(workingcopy == region)[0] neighbors = [] for member in members: candidates = neighbordict[member-1]#neighbordict is 0 based, member is 1 based candidates = [candidate for candidate in candidates if candidate not in members] candidates = [candidate for candidate in candidates if candidate not in neighbors] neighbors.extend(candidates) candidates = [] #Iterate through the neighbors for neighbor in neighbors: neighborcopy = np.copy(workingcopy[:]) #Pull a copy of the local working version old_membership = neighborcopy[neighbor]#Track where we started to check_floor neighborcopy[neighbor] = region #Move the neighbor into the new region in the copy #Here we start to check the swap and see if it is better swap_var = objective_function_vec(neighborcopy[1:],z)#Variance of the new swap if not swap_var < div_soln_space[0].any(): block = np.where(workingcopy[1:] == neighbor)[0]#A list of the members in a region. block=block.tolist() #For current contiguity check if check_contiguity(neighbordict, block, neighbor):#Check contiguity if check_floor(np.where(neighborcopy[1:,]==region)[0], floor_variable, w) and check_floor(np.where(neighborcopy[1:,]==old_membership)[0],floor_variable,w): neighborcopy[0] = swap_var if not np.isinf(div_soln_space[0].any()): div_soln_space[:,np.argmax(div_soln_space[0])] = neighborcopy[:] else: div_soln_space[:,np.argmin(div_soln_space[0])] = neighborcopy[:] else: del neighborcopy #print "Swap failed due to floor_check." else: del neighborcopy #print "Swap failed due to contiguity." #It is possible that the perturbation will not generate enough soln to fill the space, # so we need to ignore those columns with variance = infinity. #Write one of the neighbor perturbations to the shared memory space to work on. valid = np.where(div_soln_space[0] != np.inf)[0] try: selection = randint(0,len(valid)-1) with lockSoln: sharedSoln[:,core_soln_column] = div_soln_space[:,selection] print "Diversified to:", sharedSoln[0] except: print div_soln_space[0] print "Attempt to diversify failed." ##This shows that we are operating asynchronously. #if core ==2: #time.sleep(5) while sum(sharedupdate[1]) < maxiterations: core_soln_column = (core + sharedupdate[1][core])%len(sharedupdate[1]) #This iterates the cores around the search space. #Check for diversification here and diversify if necessary... if sharedupdate[0][core_soln_column] == False: _diversify_soln(core_soln_column, neighbordict,z, floor_variable,lockSoln) #Li, et. al (in press - P-Compact_Regions) #print "ProcessID %i is processing soln column %i in iteration %i."%(pid, core_soln_column,sharedupdate[1][core]) #Uncomment to see that cores move around the search space failures = 0 #The total iteration counter #What are the current best solutions local to this core? local_best_variance = sharedSoln[:,core_soln_column][0] workingSoln = np.copy(sharedSoln[:,core_soln_column]) while failures <= maxfailures:#How many total iterations can the core make #Select a random starting point in the search space. nr = np.unique(workingSoln[1:]) #This is 0 based, ie. region 0 - region 31 regionIDs = nr changed_regions = np.ones(len(nr)) randstate = RandomState(pid) #To 'unsync' the cores we need to instantiate a random class with a unique seed. randstate.shuffle(regionIDs) #shuffle the regions so we start with a random region changed_regions[:] = 0 swap_flag = False #Flag to stop looping prior to max iterations if we are not improving. #Iterate through the regions, checking potential swaps for region in regionIDs: members = np.where(workingSoln == region)[0] #get the members of the region #print region, members #Get the neighbors to the members. Grab only those that could change. neighbors = [] for member in members: candidates = neighbordict[member-1]#neighbordict is 0 based, member is 1 based candidates = [candidate for candidate in candidates if candidate not in members] candidates = [candidate for candidate in candidates if candidate not in neighbors] neighbors.extend(candidates) candidates = [] #Iterate through the neighbors for neighbor in neighbors: neighborSoln = np.copy(workingSoln[:]) #Pull a copy of the local working version old_membership = neighborSoln[neighbor]#Track where we started to check_floor tabu_move_check =_tabu_check(tabu_list, neighbor, region, old_membership) if tabu_move_check is not None: break neighborSoln[neighbor] = region #Move the neighbor into the new region in the copy #Here we start to check the swap and see if it is better swap_var = objective_function_vec(neighborSoln[1:],z)#Variance of the new swap if swap_var <= local_best_variance: block = np.where(workingSoln[1:] == neighbor)[0]#A list of the members in a region. block=block.tolist() #For current contiguity check if check_contiguity(neighbordict, block, neighbor):#Check contiguity if check_floor(np.where(neighborSoln[1:,]==region)[0], floor_variable, w) and check_floor(np.where(neighborSoln[1:,]==old_membership)[0],floor_variable,w):#What about the floor of the region loosing the member in the original code? #print "Swap made on core %i. Objective function improved from %f to %f." %(pid, swap_var, local_best_variance) local_best_variance = swap_var#Set the new local best to the swap. We have made a swap that betters the objective function. neighborSoln[0] = swap_var workingSoln[:] = neighborSoln[:] swap_flag = True #We made a swap tabu_list.appendleft((neighbor,old_membership,region))#tuple(polygon_id, oldgroup,newgroup) else: del neighborSoln #print "Swap failed due to floor_check." else: del neighborSoln #print "Swap failed due to contiguity." if swap_flag == False: #print "Failed to make any swap, incrementing the fail counter." failures += 1 #print workingSoln, len(np.unique(workingSoln[1:])) with lockflag: sharedupdate[0][core_soln_column] = 0 #Set the update flag to false #print "Locking update flag to set to false" with lockSoln:#The lock is released at the end of the with statement sharedSoln[:,core_soln_column]#Lock the column of the shared soln we are using. if workingSoln[0] < sharedSoln[:,core_soln_column][0]: sharedSoln[:,core_soln_column] sharedSoln[:,core_soln_column] = workingSoln #print "Better soln loaded into sharedSoln: %f." %(workingSoln[0]) sharedupdate[0][core_soln_column] = 1 #Set the update flag to true if not workingSoln[0] < sharedSoln[0].any(): set_half_to_best(len(sharedSoln[0])) #print "Setting half the soln to new global best. ", sharedSoln[0] #Increment the core iteration counter sharedupdate[1][core] += 1