def run(self, graph, demands): start_timer = time.time() self.logger.info("run an algorithm") self.current_graph = graph.copy() # context for current solution self.next_graph = graph.copy() # context for next solution self.allocator = SpectrumAllocator(self.current_graph) self.current_solution = self.create_first_solution(demands) self.allocate_solution(self.current_solution, self.current_graph) self.current_energy = calculate_graph_cost(self.current_graph) self.best_solution = copy_demands(self.current_solution) self.best_energy = self.current_energy while self.is_not_cold(): self.logger.debug("temperature = %s", self.temperature) self.next_solution = self.create_new_solution(self.current_solution) self.allocate_solution(self.next_solution, self.next_graph) self.next_energy = calculate_graph_cost(self.next_graph) if self.next_energy < self.current_energy: self.logger.debug("better solution than current one founded with cost: %s", self.next_energy) self.accept_next() self.check_if_next_is_better_than_best() elif self.is_worse_solution_acceptable(): self.logger.debug("worse solution than current accepted with cost: %s", self.next_energy) self.accept_next() self.cool_temperature() stop_timer = time.time() self.final_time = stop_timer - start_timer
def setUp(self): parser = Parser("../test_data", "euro16_k2.txt") scenario = parser.get_scenario(2) graph = graph_factory(scenario.networkTopology) candidatePathFetcher = CandidatePathsFetcher(scenario.candidatePaths, len(graph.nodes), scenario.pathsLengths) # get path list_of_paths1 = candidatePathFetcher.fetch_candidates(0, 1) # 1, 6, 10 self.path = list_of_paths1[1] self.edges = graph.edges self.sa = SpectrumAllocator(graph)
class SimulatedAnnealing: def __init__(self, temperature=1000, cooling_rate=0.1, minimal_temperature=1): self.logger = logging.getLogger(str(self.__class__)) self.temperature = temperature self.cooling_rate = cooling_rate self.minimal_temperature = minimal_temperature self.best_solution = None self.best_energy = None self.current_solution = None self.next_solution = None self.current_energy = None self.next_energy = None self.allocator = None self.final_time = None self.logger.info("initialize algorithm") self.current_graph = None self.next_graph = None def run(self, graph, demands): start_timer = time.time() self.logger.info("run an algorithm") self.current_graph = graph.copy() # context for current solution self.next_graph = graph.copy() # context for next solution self.allocator = SpectrumAllocator(self.current_graph) self.current_solution = self.create_first_solution(demands) self.allocate_solution(self.current_solution, self.current_graph) self.current_energy = calculate_graph_cost(self.current_graph) self.best_solution = copy_demands(self.current_solution) self.best_energy = self.current_energy while self.is_not_cold(): self.logger.debug("temperature = %s", self.temperature) self.next_solution = self.create_new_solution(self.current_solution) self.allocate_solution(self.next_solution, self.next_graph) self.next_energy = calculate_graph_cost(self.next_graph) if self.next_energy < self.current_energy: self.logger.debug("better solution than current one founded with cost: %s", self.next_energy) self.accept_next() self.check_if_next_is_better_than_best() elif self.is_worse_solution_acceptable(): self.logger.debug("worse solution than current accepted with cost: %s", self.next_energy) self.accept_next() self.cool_temperature() stop_timer = time.time() self.final_time = stop_timer - start_timer def create_new_solution(self, demands): solution = copy_demands(demands) index = random.randint(0, len(demands) - 2) solution[index], solution[index+1] = solution[index+1], solution[index] demand = solution[index] if isinstance(demand, UnicastDemand): path_index = random.randint(0, demand.nr_of_paths - 1) demand.select_path(path_index) elif isinstance(demand, AnycastDemand): data_center_index = random.randint(0, demand.nr_of_data_centers - 1) path_up_index = random.randint(0, demand.nr_of_paths - 1) path_down_index = random.randint(0, demand.nr_of_paths - 1) demand.select_data_center_by_index(data_center_index) demand.select_path_up(path_up_index) demand.select_path_down(path_down_index) return solution def create_first_solution(self, demands): solution = [] size_of_demands = len(demands) # todo: think how to remove redundancy demands = copy_demands(demands) while size_of_demands > 0: selected_demand_index = random.randint(0, size_of_demands - 1) demand = demands.pop(selected_demand_index) if isinstance(demand, UnicastDemand): path_index = random.randint(0, demand.nr_of_paths - 1) demand.select_path(path_index) solution.append(demand) elif isinstance(demand, AnycastDemand): data_center_index = random.randint(0, demand.nr_of_data_centers - 1) path_up_index = random.randint(0, demand.nr_of_paths - 1) path_down_index = random.randint(0, demand.nr_of_paths - 1) demand.select_data_center_by_index(data_center_index) demand.select_path_up(path_up_index) demand.select_path_down(path_down_index) solution.append(demand) size_of_demands -= 1 return solution def allocate_solution(self, list_of_demands, context): """ It allocates list of demands on graf provided by context :param list_of_demands: :param context: :return: """ self.allocator.set_context(context) self.allocator.clear() for demand in list_of_demands: if isinstance(demand, UnicastDemand): path = demand.get_selected_path() self.allocator.allocate_first_free_spectrum_on_path(path) elif isinstance(demand, AnycastDemand): path_up = demand.get_selected_path_up() path_down = demand.get_selected_path_down() self.allocator.allocate_first_free_spectrum_on_path(path_up) self.allocator.allocate_first_free_spectrum_on_path(path_down) def accept_next(self): self.current_energy = self.next_energy self.current_solution = copy_demands(self.next_solution) # copy def check_if_next_is_better_than_best(self): if self.next_energy < self.best_energy: self.logger.debug("new best solution found with cost: %s", self.next_energy) self.best_energy = self.next_energy self.best_solution = copy_demands(self.next_solution) # copy def is_worse_solution_acceptable(self): probability = math.exp(-(self.next_energy - self.current_energy) * 1.0 / self.temperature) if probability > random.random(): return True return False def cool_temperature(self): self.temperature *= 1 - self.cooling_rate def is_not_cold(self): return self.temperature > self.minimal_temperature
class SpectrumTest(unittest.TestCase): @classmethod def setUpClass(cls): logging.basicConfig(level=logging.DEBUG) def setUp(self): parser = Parser("../test_data", "euro16_k2.txt") scenario = parser.get_scenario(2) graph = graph_factory(scenario.networkTopology) candidatePathFetcher = CandidatePathsFetcher(scenario.candidatePaths, len(graph.nodes), scenario.pathsLengths) # get path list_of_paths1 = candidatePathFetcher.fetch_candidates(0, 1) # 1, 6, 10 self.path = list_of_paths1[1] self.edges = graph.edges self.sa = SpectrumAllocator(graph) def test_normal_allocation(self): """ following scenario: alloc 4 edge 1 free edge 6 alloc 0, 1, 7 edge 10 alloc 2, 7, 8 :return: 3 to 7 """ spectrum_size = 4 expected = [[0, 0, 0, 1, 1, 1, 1], [1, 1, 0, 1, 1, 1, 1, 1], [0, 0, 1, 1, 1, 1, 1, 1, 1]] edge6 = self.edges[6] edge6.spectrum.allocate(0, 2) edge6.spectrum.allocate(7, 8) edge10 = self.edges[10] edge10.spectrum.allocate(2, 3) edge10.spectrum.allocate(7, 9) self.sa.allocate_first_free_spectrum_on_path(self.path, spectrum_size) self.print_edges() for value, edge_id in zip(expected, self.path.edges): self.assertListEqual(value, self.edges[edge_id].spectrum.spectrum) def test_moved_allocation(self): """ following scenario: alloc 4 edge 1 free edge 6 alloc 0, 1, 6, 7 edge 10 alloc 2, 7, 8 :return: 9, 13 """ spectrum_size = 4 expected = [ [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1], [1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1], [0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1], ] edge6 = self.edges[6] edge6.spectrum.allocate(0, 2) edge6.spectrum.allocate(6, 8) edge10 = self.edges[10] edge10.spectrum.allocate(2, 3) edge10.spectrum.allocate(7, 9) self.sa.allocate_first_free_spectrum_on_path(self.path, spectrum_size) self.print_edges() for value, edge_id in zip(expected, self.path.edges): self.assertListEqual(value, self.edges[edge_id].spectrum.spectrum) def print_edges(self): for edge_index in self.path.edges: print self.edges[edge_index]