def local_search(): # This function carries out a local search to improve # the current guess. You can only examine *ONE* possible # update to the current solution per call. That is, at # most one of the current medians should change from # call to call. Note that this procedure is greedy # and will only update the current solution if its # new guess yields a better cost #################################################### ## ## TO DO: Complete this function to perform simple ## local search for better solutions to the ## K-medians problem. ## ## Make sure your code updates the global ## 'current_medians' list! #################################################### point = random.randint(0, Kmedians_global_data.N - 1) median = random.randint(0, Kmedians_global_data.K - 1) temp_medians = list(Kmedians_global_data.current_medians) temp_medians.pop(median) temp_medians.append(Kmedians_global_data.all_points[point]) if Kmedians_global_data.current_cost( temp_medians) < Kmedians_global_data.current_cost( Kmedians_global_data.current_medians): Kmedians_global_data.current_medians = temp_medians print Kmedians_global_data.current_cost(temp_medians) return
def local_search(): # This function carries out a local search to improve # the current guess. You can only examine *ONE* possible # update to the current solution per call. That is, at # most one of the current medians should change from # call to call. Note that this procedure is greedy # and will only update the current solution if its # new guess yields a better cost #################################################### ## ## TO DO: Complete this function to perform simple ## local search for better solutions to the ## K-medians problem. ## ## Make sure your code updates the global ## 'current_medians' list! #################################################### point =random.randint(0, Kmedians_global_data.N-1) median = random.randint(0, Kmedians_global_data.K-1) temp_medians = list(Kmedians_global_data.current_medians) temp_medians.pop(median) temp_medians.append(Kmedians_global_data.all_points[point]) if Kmedians_global_data.current_cost(temp_medians) < Kmedians_global_data.current_cost(Kmedians_global_data.current_medians): Kmedians_global_data.current_medians = temp_medians print Kmedians_global_data.current_cost(temp_medians) return
def deterministic_annealing(): # This function carries out a local search using the # deterministic annealing method as discussed in lecture. # The 'temperature' is set by the initKmedians function. # Each call to this function will try a new solution # and accept it under the conditions specified by the # deterministic annealing method. # temperature as T=T*D, where D<1.0 is a decay factor that # controls how quickly the temperature decreases. # Both the temperature and decay factor are global # variables. # Each call to this function can examine only *ONE* # guess at the solution. #################################################### # THE SAME NEIGHBOURHOOD DEFINITION APPLIES AS FOR # LOCAL SEARCH ABOVE #################################################### #################################################### ## ## TO DO: Complete this function to perform ## local search with deterministic annealing. ## ## Make sure your code updates the global ## 'current_medians' list! #################################################### T = Kmedians_global_data.Temperature = Kmedians_global_data.Temperature * Kmedians_global_data.Decay medians = try_new_medians() if not medians: return med_cost = Kmedians_global_data.current_cost(medians) cur_cost = Kmedians_global_data.current_cost( Kmedians_global_data.current_medians) delta_t = abs(med_cost - cur_cost) probability = math.exp(-delta_t / T) r = random.random() if med_cost > cur_cost: if r < probability: Kmedians_global_data.current_medians = medians else: Kmedians_global_data.current_medians = medians print med_cost return
def MainLoop(): global iters global screen_shot_on_done global screeny_filename temp = list(Kmedians_global_data.current_medians) if iters < 150: if Kmedians_global_data.Temperature <= 0: local_search() if temp == Kmedians_global_data.current_medians: iters = iters + 1 else: iters = 0 else: deterministic_annealing() if temp == Kmedians_global_data.current_medians: iters = iters + 1 else: iters = 0 renderFrame() UpdateFrame() else: print 'No improvement for past 150 iterations. Search stop.\n' print "Press 'q' to quit\n" print "final cost:", Kmedians_global_data.current_cost( Kmedians_global_data.current_medians) if not screen_shot_on_done: exit(0)
def local_search(): # This function carries out a local search to improve # the current guess. You can only examine *ONE* possible # update to the current solution per call. That is, at # most one of the current medians should change from # call to call. Note that this procedure is greedy # and will only update the current solution if its # new guess yields a better cost ##################################################### # NEIGHBOURHOOD DEFINITION: # At each step, one of the current guesses for your # median locations can be swaped for another # point as long as the distance between the current # guess and the point is less than 250 units # (this is Euclidean distance of course) # This means that you CAN NOT SWAP with just any # point! Make sure your updates consider this # simple neighbourhood structure. # # If the proposed swap is more than 250 units away, # do not perform the sawp! just return from this # function with the same guess you started with. ###################################################### #################################################### ## ## TO DO: Complete this function to perform simple ## local search for better solutions to the ## K-medians problem. ## ## Make sure your code updates the global ## 'current_medians' list! #################################################### medians = try_new_medians() if not medians: return med_cost = Kmedians_global_data.current_cost(medians) cur_cost = Kmedians_global_data.current_cost( Kmedians_global_data.current_medians) if med_cost < cur_cost: Kmedians_global_data.current_medians = medians print med_cost return
def deterministic_annealing(): # This function carries out a local search using the # deterministic annealing method as discussed in lecture. # The 'temperature' is set by the initKmedians function. # Each call to this function will try a new solution # and accept it under the conditions specified by the # deterministic annealing method. # Also, each call to this function will update the # temperature as T=T*D, where D<1.0 is a decay factor that # controls how quickly the temperature decreases. # Both the temperature and decay factor are global # variables. # Each call to this function can examine only *ONE* # guess at the solution. #################################################### ## ## TO DO: Complete this function to perform ## local search with deterministic annealing. ## ## Make sure your code updates the global ## 'current_medians' list! #################################################### point = random.randint(0, Kmedians_global_data.N - 1) median = random.randint(0, Kmedians_global_data.K - 1) temp_medians = list(Kmedians_global_data.current_medians) temp_medians.pop(median) temp_medians.append(Kmedians_global_data.all_points[point]) if Kmedians_global_data.current_cost( temp_medians) < Kmedians_global_data.current_cost( Kmedians_global_data.current_medians): Kmedians_global_data.current_medians = temp_medians print Kmedians_global_data.current_cost(temp_medians) else: # get the probability cost_diff = abs( Kmedians_global_data.current_cost(temp_medians) - Kmedians_global_data.current_cost( Kmedians_global_data.current_medians)) probability = math.exp(-cost_diff / Kmedians_global_data.Temperature) # generate a random float between 0 and 1 rand_float = random.random() if probability > rand_float: Kmedians_global_data.current_medians = temp_medians print Kmedians_global_data.current_cost(temp_medians) Kmedians_global_data.Temperature = Kmedians_global_data.Temperature * Kmedians_global_data.Decay return
def deterministic_annealing(): # This function carries out a local search using the # deterministic annealing method as discussed in lecture. # The 'temperature' is set by the initKmedians function. # Each call to this function will try a new solution # and accept it under the conditions specified by the # deterministic annealing method. # Also, each call to this function will update the # temperature as T=T*D, where D<1.0 is a decay factor that # controls how quickly the temperature decreases. # Both the temperature and decay factor are global # variables. # Each call to this function can examine only *ONE* # guess at the solution. #################################################### ## ## TO DO: Complete this function to perform ## local search with deterministic annealing. ## ## Make sure your code updates the global ## 'current_medians' list! #################################################### point =random.randint(0, Kmedians_global_data.N-1) median = random.randint(0, Kmedians_global_data.K-1) temp_medians = list(Kmedians_global_data.current_medians) temp_medians.pop(median) temp_medians.append(Kmedians_global_data.all_points[point]) if Kmedians_global_data.current_cost(temp_medians) < Kmedians_global_data.current_cost(Kmedians_global_data.current_medians): Kmedians_global_data.current_medians = temp_medians print Kmedians_global_data.current_cost(temp_medians) else: # get the probability cost_diff = abs(Kmedians_global_data.current_cost(temp_medians) - Kmedians_global_data.current_cost(Kmedians_global_data.current_medians)) probability = math.exp(-cost_diff/Kmedians_global_data.Temperature) # generate a random float between 0 and 1 rand_float = random.random() if probability > rand_float: Kmedians_global_data.current_medians = temp_medians print Kmedians_global_data.current_cost(temp_medians) Kmedians_global_data.Temperature = Kmedians_global_data.Temperature*Kmedians_global_data.Decay return
def deterministic_annealing(): # This function carries out a local search using the # deterministic annealing method as discussed in lecture. # The 'temperature' is set by the initKmedians function. # Each call to this function will try a new solution # and accept it under the conditions specified by the # deterministic annealing method. # Also, each call to this function will update the # temperature as T=T*D, where D<1.0 is a decay factor that # controls how quickly the temperature decreases. # Both the temperature and decay factor are global # variables. # Each call to this function can examine only *ONE* # guess at the solution. #################################################### # THE SAME NEIGHBOURHOOD DEFINITION APPLIES AS FOR # LOCAL SEARCH ABOVE #################################################### # all_points - List of [x,y] point coordinates # current_medians - List of [x,y] with current medians # N - Number of points # K - Number of medians # Temperature - Temperature for deterministic annealing # Decay - Decay factor for deterministic annealing g.current_cost(g.current_medians) old_median = random.choice(g.current_medians) new_median = random.choice(g.all_points) if distance(old_median, new_median) > 250: return new_medians = g.current_medians[:] new_medians.remove(old_median) new_medians.append(new_median) dT = abs(g.current_cost(g.current_medians) - g.current_cost(new_medians)) P = exp(-dT/g.Temperature) g.Temperature *= g.Decay print("temp: %f" % g.Temperature) print("cost: %f" % g.current_cost(g.current_medians)) if g.current_cost(g.current_medians) > g.current_cost(new_medians): g.current_medians = new_medians elif random.random() < P: g.current_medians = new_medians return
def local_search(): # This function carries out a local search to improve # the current guess. You can only examine *ONE* possible # update to the current solution per call. That is, at # most one of the current medians should change from # call to call. Note that this procedure is greedy # and will only update the current solution if its # new guess yields a better cost ##################################################### # NEIGHBOURHOOD DEFINITION: # At each step, one of the current guesses for your # median locations can be swaped for another # point as long as the distance between the current # guess and the point is less than 250 units # (this is Euclidean distance of course) # This means that you CAN NOT SWAP with just any # point! Make sure your updates consider this # simple neighbourhood structure. # # If the proposed swap is more than 250 units away, # do not perform the sawp! just return from this # function with the same guess you started with. ##################################################### g.current_cost(g.current_medians) old_median = random.choice(g.current_medians) new_median = random.choice(g.all_points) if distance(old_median, new_median) > 250: return new_medians = g.current_medians[:] new_medians.remove(old_median) new_medians.append(new_median) if g.current_cost(g.current_medians) > g.current_cost(new_medians): g.current_medians = new_medians print g.current_cost(g.current_medians)
def initKmedians(seedNo, N, K, screeny=False, filename=''): global N_comps global sigs global pis global mus global blank global screen_shot_on_done global screeny_filename screen_shot_on_done = screeny if filename: screeny_filename = filename Kmedians_global_data.N = N Kmedians_global_data.K = K if N < 50 or N > 5000: print 'Value of N should be between 50 and 5000. Using 100\n' Kmedians_global_data.N = 100 if K < 1 or K > 15: print 'Value of K should be between 1 and 15. Using 10\n' Kmedians_global_data.K = 5 random.seed(31415) if seedNo >= 0: pisum = 0 for i in range(N_comps + 1): pis.append(random.random()) mus.append([random.randint(1, 1022), randint(1, 1022)]) sigs.append([random.randint(50, 500)]) pisum = pisum + pis[i] for i in range(N_comps + 1): pis[i] = pis[i] / pisum else: blank = open('TO_dense.ppm') pis.append(7) mus.append([165, 697]) sigs.append(70) pis.append(7) mus.append([185, 530]) sigs.append(100) pis.append(7) mus.append([490, 590]) sigs.append(55) pis.append(7) mus.append([710, 475]) sigs.append(70) pis.append(4) mus.append([300, 250]) sigs.append(150) pis.append(2.5) mus.append([950, 340]) sigs.append(140) pis.append(1.5) mus.append([610, 230]) sigs.append(200) pis.append(0.5) mus.append([512, 512]) sigs.append(1) pisum = 0 for i in range(N_comps + 1): pisum = pisum + pis[i] for i in range(N_comps + 1): pis[i] = pis[i] / pisum for i in range(Kmedians_global_data.N): done = 0 while not done: dice = random.random() pisum = 0 idx = 0 while idx < N_comps: pisum = pisum + pis[idx] if pisum >= dice: break idx = idx + 1 if idx < N_comps: mu = mus[idx] sig = sigs[idx] pt = list([ random.normal(mu[0], sig, 1), random.normal(mu[1], sig, 1) ]) if pt[0] > 0 and pt[0] < 1023 and pt[1] > 0 and pt[1] < 1023: done = 1 else: pt = [random.randint(1, 1023), random.randint(1, 1023)] done = 1 if seedNo < 0 and done: pix = list(blank.getpixel(tuple([round(pt[0]), round(pt[1])]))) if pix[0] == 0 and pix[1] == 0 and pix[2] == 0: done = 0 if done == 1: Kmedians_global_data.all_points.append(pt) random.seed(abs(seedNo)) for i in range(Kmedians_global_data.K): Kmedians_global_data.current_medians.append( Kmedians_global_data.all_points[random.randint(0, N - 1)]) print 'Initial K-medians guess:\n' print Kmedians_global_data.current_medians print 'Initial assignment cost (average distance from a point to the closest candidate median):\n' print Kmedians_global_data.current_cost( Kmedians_global_data.current_medians)