def __init__(self, network, demands, max_weight=20, ecmp=True): self.network = network self.demands = demands self.max_weight = max_weight self.congestion = CongestionOptimization(self.network, self.demands) self.allow_ecmp = ecmp self.stop = timeit.default_timer()
def sp_routing(self, dic_assig, weights, dem=None, of="mlu", ecmp=True): if dem is None: dem = self.generate_e2e_demands(dic_assig) cong_opt = CongestionOptimization(self.network, dem) if ecmp: of_val, links = cong_opt.sp_congestion_ties(weights, of) else: of_val, links = cong_opt.sp_congestion(weights, of) if of == "fortz": of_val -= 1.0 return of_val, links
def best_routing(self, dic_assig, dem=None, of="mlu"): if dem is None: dem = self.generate_e2e_demands(dic_assig) cong_opt = CongestionOptimization(self.network, dem) cong_opt.setup_problem(of, False, False) res = cong_opt.solve_problem() if of == "fortz": res_cong = res[1] - 1.0 else: res_cong = res[1] if (res is not None): return res_cong, cong_opt.get_all_used_links() else: print("No optimal routing could be found") return None
def run_evol_alg(self, parallel=False, max_cpus=4, ea_pars={}, display=True, save_file=None): popsize = ea_pars.get("pop_size", 100) maxevals = ea_pars.get("max_evaluations", 10000) numselected = ea_pars.get("num_selected", 80) mutationrate = ea_pars.get("mutation_rate", 0.05) numelites = ea_pars.get("num_elites", 20) local_opt_rate = ea_pars.get("local_opt_rate", 0.2) if display: print("Population size: ", popsize) print("Number evaluations: ", maxevals) print("Num selected: ", numselected) print("Num elites: ", numelites) print("Mutation rate: ", mutationrate) print("Local opt rate: ", local_opt_rate) if save_file is not None: print("Saving results to files with prefix: ", save_file) lower_limits = [0] * (len(self.ord_users) * len(self.ord_services)) upper_limits = [] for u in range(len(self.ord_users)): for k in range(len(self.ord_services)): upper_limits.append(self.number_servers[k] - 1) if self.opt_rout_weig: lower_limits.extend([0] * self.composite.network.number_edges()) upper_limits.extend([self.maxw] * self.composite.network.number_edges()) rand = Random() rand.seed(int(time())) if parallel: my_ec = inspyred.ec.DEA(rand) else: my_ec = inspyred.ec.EvolutionaryComputation(rand) my_ec.selector = inspyred.ec.selectors.rank_selection if self.opt_rout_weig: my_ec.variator = [ inspyred.ec.variators.n_point_crossover, inspyred.ec.variators.random_reset_mutation, self.single_inteligent_mut, self.increment_mut ] else: my_ec.variator = [ inspyred.ec.variators.n_point_crossover, inspyred.ec.variators.random_reset_mutation, self.single_inteligent_mut, self.increment_mut # self.improve_user_assig ] #my_ec.replacer = inspyred.ec.replacers.steady_state_replacement# my_ec.replacer = inspyred.ec.replacers.generational_replacement my_ec.terminator = inspyred.ec.terminators.evaluation_termination stat_file = None #ind_file = None if save_file is not None: my_ec.observer = inspyred.ec.observers.file_observer stat_file = open(save_file + "-stats.txt", "w") #ind_file = open(save_file + "-pop.txt", "w") elif display: my_ec.observer = inspyred.ec.observers.stats_observer if parallel: final_pop = my_ec.evolve( generator=self.generate_solution_random, evaluator=inspyred.ec.evaluators.parallel_evaluation_mp, mp_evaluator=self.evaluate_serv_assig, mp_num_cpus=max_cpus, maximize=False, ### set to True if maximizing utility pop_size=popsize, bounder=inspyred.ec.Bounder(lower_limits, upper_limits), max_evaluations=maxevals, num_selected=numselected, mutation_rate=mutationrate, num_elites=numelites, num_crossover_points=3, local_opt_rate=local_opt_rate, statistics_file=stat_file, #individuals_file=ind_file ) else: final_pop = my_ec.evolve( generator=self.generate_solution_random, evaluator=self.evaluate_serv_assig, maximize=False, ### set to True if maximizing utility pop_size=popsize, bounder=inspyred.ec.Bounder(lower_limits, upper_limits), max_evaluations=maxevals, num_selected=numselected, mutation_rate=mutationrate, num_elites=numelites, num_crossover_points=3, local_opt_rate=local_opt_rate, statistics_file=stat_file, #individuals_file=ind_file ) print('Terminated due to {0}.'.format(my_ec.termination_cause)) best_sol = max(final_pop).candidate res = {} res["popsize"] = popsize res["evals"] = maxevals res["selected"] = numselected res["elites"] = numelites res["mutation_rate"] = mutationrate res["local_rate"] = local_opt_rate if self.opt_rout_weig: size_assig = len(self.ord_users) * len(self.ord_services) assig = self.decode_serv_assig(best_sol[:size_assig]) w = self.decode_weights(best_sol[size_assig:]) res["of_value"] = self.composite.of_normalized_penalty( assig, True, self.mincost, sp_weights=w) of = self.composite.of_normalized_penalty(assig, False, self.mincost, sp_weights=w, return_dic=True) res["of_fh"] = of["fh"] res["of_e2e"] = of["e2e"] res["of_cost"] = of["cost"] res["of_cong"] = of["cong"] else: assig = self.decode_serv_assig(best_sol) res["of_value"] = self.composite.of_normalized_penalty( assig, True, self.mincost) of = self.composite.of_normalized_penalty(assig, False, self.mincost, return_dic=True) res["of_fh"] = of["fh"] res["of_e2e"] = of["e2e"] res["of_cost"] = of["cost"] if not self.composite.congestion_cost: ## reporting congestion even if not used in the optimization dem = self.composite.generate_e2e_demands(assig.dic_assig) l = Loads(self.composite.network) l.add_loads_from_paths(self.composite.del_paths, dem) if self.composite.cong_of == "mlu": cong = l.mlu()[0] elif self.composite.cong_of == "alu": cong = l.alu() elif self.composite.cong_of == "fortz": co = CongestionOptimization(self.composite.network, dem) phiu = co.phi_uncap() cong = l.fortz_of(phiu) - 1.0 print("Congestion (not optimized):", cong) res["of_cong"] = cong else: res["of_cong"] = of["cong"] print("Objective function value: ", res["of_value"]) if save_file is not None: stat_file.close() #ind_file.close() return assig, res
class DeapCongestion: def __init__(self, network, demands, max_weight=20, ecmp=True): self.network = network self.demands = demands self.max_weight = max_weight self.congestion = CongestionOptimization(self.network, self.demands) self.allow_ecmp = ecmp def decode_solution(self, sol): L = self.network.link_ids() w = {} for i, e in enumerate(L): w[e] = sol[i] return w def evaluate_solution(self, individual): w = self.decode_solution(individual) if self.allow_ecmp: fit = self.congestion.sp_congestion_ties(w, self.of, False)[0] else: fit = self.congestion.sp_congestion(w, self.of, False)[0] return fit, def run_evol_alg(self, ea_pars={}, of="mlu", display=True): self.of = of popsize = ea_pars.get("pop_size", 100) creator.create("FitnessMin", base.Fitness, weights=(-1.0, )) creator.create("Individual", list, fitness=creator.FitnessMin) toolbox = base.Toolbox() # Attribute generator toolbox.register("attr_int", random.randint, 1, self.max_weight) # Structure initializers toolbox.register("individual", tools.initRepeat, creator.Individual, toolbox.attr_int, self.network.number_edges()) toolbox.register("population", tools.initRepeat, list, toolbox.individual) toolbox.register("evaluate", self.evaluate_solution) toolbox.register("mate", tools.cxTwoPoint) toolbox.register("mutate", tools.mutUniformInt, low=1, up=self.max_weight, indpb=0.05) toolbox.register("select", tools.selTournament, tournsize=3) pop = toolbox.population(n=popsize) hof = tools.HallOfFame(1) stats = tools.Statistics(lambda ind: ind.fitness.values) stats.register("avg", numpy.mean) stats.register("std", numpy.std) stats.register("min", numpy.min) stats.register("max", numpy.max) pop, log = algorithms.eaSimple(pop, toolbox, cxpb=0.5, mutpb=0.2, ngen=200, stats=stats, halloffame=hof, verbose=True) return pop, log, hof
def of_normalized_penalty(self, serv_assig, printcomps=False, mincost=None, sp_weights=None, return_dic=False): if mincost is None: mincost = self.min_cost() dic_assig = serv_assig.dic_assig fix_costs = self.sum_fixed_costs(dic_assig) var_costs = self.sum_var_costs(dic_assig) total_costs = fix_costs + var_costs cost_pen = self.cost_norm_penalty(total_costs, mincost) if printcomps: print("Var. costs: ", var_costs) print("Fixed costs: ", fix_costs) print("Total costs: ", total_costs) print("Cost Penalty: ", cost_pen) if self.opt_cong or self.congestion_cost: dem = self.generate_e2e_demands(dic_assig) if self.opt_cong: if self.cong_opt_method == "milp": cong, paths = self.best_routing(dic_assig, dem, self.cong_of) elif self.cong_opt_method == "sp": cong, paths = self.sp_routing(dic_assig, sp_weights, dem, self.cong_of) if printcomps: print("Congestion: ", cong) self.update_delays_from_routing(paths) elif self.congestion_cost: l = Loads(self.network) l.add_loads_from_paths(self.del_paths, dem) if self.cong_of == "mlu": cong = l.mlu()[0] elif self.cong_of == "alu": cong = l.alu() elif self.cong_of == "fortz": co = CongestionOptimization(self.network, dem) phiu = co.phi_uncap() cong = l.fortz_of(phiu) - 1.0 else: print("OF not defined") return None if printcomps: print("Congestion: ", cong) e2e_pen = self.latency_pen_all_users(dic_assig) fh_pen = self.firsthop_penalties_all_users(dic_assig) if printcomps: print("E2E penalties: ", e2e_pen) print("FH penalties: ", fh_pen) if return_dic: res = {} res["fh"] = fh_pen res["e2e"] = e2e_pen res["cost"] = cost_pen if self.congestion_cost: res["cong"] = cong return res # if self.congestion_cost: # return ( (fh_pen+ e2e_pen)/2.0, cost_pen, cong) # else: # return ( (fh_pen+ e2e_pen)/2.0, cost_pen) else: if self.congestion_cost: return (self.weights["cost"] * cost_pen + self.weights["e2e"] * e2e_pen + self.weights["fh"] * fh_pen + self.weights["congestion"] * cong) else: return (self.weights["cost"] * cost_pen + self.weights["e2e"] * e2e_pen + self.weights["fh"] * fh_pen)
def heuristic(self, solution): ord_users = self.composite.users.ord_users() num_services = len(self.ord_services) assig_dic = {} fixed_cost_dic = {} ## includes servers used by previous users servers_per_service = {} for s in self.ord_services: servers_per_service[ s] = self.composite.servers.servers_for_service(s) # each user in the provided order for u in solution: print(u) user_id = ord_users[u] # update min cost for user dem = self.composite.users.get_demand(user_id) for service_id in self.ord_services: ls = servers_per_service[service_id] mc = None for server_id in ls: fcost = self.composite.servers.get_fixed_cost( service_id, server_id) vcost = self.composite.servers.get_var_cost( service_id, server_id) if (service_id, server_id) not in fixed_cost_dic: cost_server = fcost + dem * vcost else: cost_server = dem * vcost if mc is None or cost_server < mc: mc = cost_server # for each possible assignment of servers to services (try all for this user) nxt_assig = [0] * len(self.ord_services) opt_assig = None opt_cost = math.inf while nxt_assig is not None: # build the solution cur_sol_dic = {} for s in range(len(nxt_assig)): service_id = self.ord_services[s] server_id = servers_per_service[service_id][nxt_assig[s]] cur_sol_dic[service_id] = server_id assig_dic[user_id] = cur_sol_dic # calculate added cost added_cost = 0 for s in assig_dic[user_id].keys(): server_id = assig_dic[user_id][s] if (s, server_id) not in fixed_cost_dic: added_cost += self.composite.servers.get_fixed_cost( s, server_id) added_cost += self.composite.var_cost( user_id, s, server_id) cost_pen = self.composite.cost_norm_penalty(added_cost, mc) if self.composite.opt_cong or self.composite.congestion_cost: dem = self.composite.generate_e2e_demands(assig_dic) if self.composite.opt_cong: cong, paths = self.composite.best_routing( assig_dic, dem, self.composite.cong_of) self.composite.update_delays_from_routing(paths) elif self.composite.congestion_cost: l = Loads(self.composite.network) l.add_loads_from_paths(self.composite.del_paths, dem) if self.composite.cong_of == "mlu": cong = l.mlu()[0] elif self.composite.cong_of == "alu": cong = l.alu() elif self.composite.cong_of == "fortz": co = CongestionOptimization(self.composite.network, dem) phiu = co.phi_uncap() if phiu <= 0.0: cong = 0.0 else: cong = l.fortz_of(phiu) - 1.0 lat = self.composite.latency_user(user_id, assig_dic[user_id]) minlat, maxlat = self.composite.users.get_latencies(user_id) lat_pen = self.composite.latency_norm_penalty( lat, minlat, maxlat) fh_lat = self.composite.get_fh_latency(user_id, assig_dic[user_id]) minlat_fh, maxlat_fh = self.composite.users.get_fh_latencies( user_id) lat_fh = self.composite.latency_norm_penalty( fh_lat, minlat_fh, maxlat_fh) if self.composite.congestion_cost: cost = self.composite.weights[ "cost"] * cost_pen + self.composite.weights[ "e2e"] * lat_pen +self.composite.weights[ "fh"] * lat_fh + self.composite.weights[ "congestion"] * cong else: cost = self.composite.weights[ "cost"] * cost_pen + self.composite.weights[ "e2e"] * lat_pen +self.composite.weights["fh"] * lat_fh del (assig_dic[user_id]) if opt_assig is None or cost < opt_cost: opt_assig = nxt_assig opt_cost = cost nxt_assig = self.next_assig(nxt_assig, num_services, servers_per_service, self.ord_services) # update optimal solution with best assignment for this user opt_sol_dic = {} for s in range(len(opt_assig)): service_id = self.ord_services[s] server_id = servers_per_service[service_id][opt_assig[s]] opt_sol_dic[service_id] = server_id if (service_id, server_id) not in fixed_cost_dic: fixed_cost_dic[(service_id, server_id)] = True assig_dic[user_id] = opt_sol_dic return ServicesAssignment(self.composite, assig_dic)
def run(): ## FORMAT: type_optimization network_file services_tree instance_file ## type_optimization: ## nc - no congestion ## d - congestion costs; shortest path delays ## oc - congestion costs; MILP optimizaing congestion ## network file - assuming sndlib format ## services tree - file with "tree" of services ## instance_file - defines "name" of instance ## assuming: instance_file + "-users.txt" - users demands ## assuming: instance_file + "-user_topo.txt" - users topologies ## assuming: instance_file + "-costs.txt" - server costs network_file = sys.argv[2] n = Network(network_file, "sndlib") filename_tree = sys.argv[3] loops = False t = ServicesTree(loops, filename_tree) servers_file = sys.argv[4] + "-costs.txt" s = Servers(t, n, servers_file) users_dem_file = sys.argv[4] + "-users.txt" users_top_file = sys.argv[4] + "-user_topo.txt" u = Users(n, users_dem_file, users_top_file) if sys.argv[1] == "nc": cs = CompositeServices(n, t, s, u, opt_cong=False, congestion_cost=False, cong_of="fortz") elif sys.argv[1] == "d": cs = CompositeServices(n, t, s, u, opt_cong=False, congestion_cost=True, cong_of="fortz") elif sys.argv[1] == "oc": cs = CompositeServices(n, t, s, u, opt_cong=True, congestion_cost=True, cong_opt_method="milp", cong_of="fortz") else: print("Type of optimization not defined") sys.exit(1) hcs = CompositeHeuristic(cs) order = list(range(len(cs.users))) sol = hcs.heuristic(order) of = cs.of_normalized_penalty(sol, True) if not cs.congestion_cost: ## reporting congestion even if not used in the optimization dem = cs.generate_e2e_demands(sol.dic_assig) l = Loads(n) l.add_loads_from_paths(cs.del_paths, dem) if cs.cong_of == "mlu": cong = l.mlu()[0] elif cs.cong_of == "alu": cong = l.alu() elif cs.cong_of == "fortz": co = CongestionOptimization(n, dem) phiu = co.phi_uncap() cong = l.fortz_of(phiu) - 1.0 print("Congestion (not optimized):", cong) print("Objective function:", of)
class EACongestion: def __init__(self, network, demands, max_weight=20, ecmp=True): self.network = network self.demands = demands self.max_weight = max_weight self.congestion = CongestionOptimization(self.network, self.demands) self.allow_ecmp = ecmp self.stop = timeit.default_timer() def generate_solution_random(self, random, args): from random import randint res = [] for i in range(self.network.number_edges()): res.append(randint(1, self.max_weight)) return res def decode_solution(self, sol): L = self.network.link_ids() w = {} for i, e in enumerate(L): w[e] = sol[i] return w def evaluate_solutions(self, candidates, args): fitness = [] for cs in candidates: w = self.decode_solution(cs) if self.allow_ecmp: self.start = timeit.default_timer() #print('Time else: ', self.start - self.stop) fit = self.congestion.sp_congestion_ties(w, self.of, False)[0] self.stop = timeit.default_timer() #print('Time eval: ', self.stop - self.start) else: fit = self.congestion.sp_congestion(w, self.of, False)[0] fitness.append(fit) return fitness def increment_mut(self, random, candidates, args): import copy mutants = [] for candidate in candidates: if random.random() < 0.5: numchanges = random.randint(1, 4) for k in range(numchanges): mutant = copy.copy(candidate) pos = random.randint(0, len(candidate) - 1) current = mutant[pos] f = random.random() if f > 0.5: if current == self.max_weight: mutant[pos] = 1 else: mutant[pos] = current + 1 else: if current == 1: mutant[pos] = self.max_weight else: mutant[pos] = current - 1 mutants.append(mutant) else: mutants.append(candidate) return mutants def run_evol_alg(self, ea_pars={}, of="mlu", display=True): self.of = of popsize = ea_pars.get("pop_size", 100) maxevals = ea_pars.get("max_evaluations", 20000) # tournamentsize = ea_pars.get("tournament_size", 20) numselected = ea_pars.get("num_selected", 50) mutationrate = ea_pars.get("mutation_rate", 0.002) numelites = ea_pars.get("num_elites", 20) lower_limits = [1] * self.network.number_edges() upper_limits = [self.max_weight] * self.network.number_edges() rand = Random() rand.seed(int(time())) my_ec = inspyred.ec.EvolutionaryComputation(rand) #my_ec.selector = inspyred.ec.selectors.tournament_selection my_ec.selector = inspyred.ec.selectors.rank_selection my_ec.variator = [ inspyred.ec.variators.uniform_crossover, inspyred.ec.variators.random_reset_mutation, self.increment_mut ] #my_ec.replacer = inspyred.ec.replacers.steady_state_replacement my_ec.replacer = inspyred.ec.replacers.generational_replacement my_ec.terminator = inspyred.ec.terminators.evaluation_termination if display: my_ec.observer = inspyred.ec.observers.stats_observer final_pop = my_ec.evolve( generator=self.generate_solution_random, evaluator=self.evaluate_solutions, maximize=False, ### set to True if maximizing utility pop_size=popsize, bounder=inspyred.ec.Bounder(lower_limits, upper_limits), max_evaluations=maxevals, num_selected=numselected, mutation_rate=mutationrate, # tournament_size= tournamentsize, num_elites=numelites) print('Terminated due to {0}.'.format(my_ec.termination_cause)) best_sol = max(final_pop).candidate print(best_sol)
def run_evol_alg(self, ea_pars={}, of="mlu", parallel=None, max_cpus=1, save_file=None): ## parallel & max_cpus - being ignored for now !!!! ## save_file as well self.of = of popsize = ea_pars.get("pop_size", 100) maxevals = ea_pars.get("max_evaluations", 10000) localrate = ea_pars.get("local_opt_rate", 0.2) numgen = int(maxevals / popsize) + 1 indsize = len(self.ord_users) * len(self.ord_services) if self.opt_rout_weig: indsize += self.composite.network.number_edges() #lower_limits = [0]*(len(self.ord_users)*len(self.ord_services)) upper_limits = [] for u in range(len(self.ord_users)): for k in range(len(self.ord_services)): upper_limits.append(self.number_servers[k] - 1) if self.opt_rout_weig: #lower_limits.extend ( [0]*self.composite.network.number_edges() ) upper_limits.extend([self.maxw] * self.composite.network.number_edges()) creator.create("FitnessMin", base.Fitness, weights=(-1.0, )) creator.create("Individual", list, fitness=creator.FitnessMin) toolbox = base.Toolbox() toolbox.register("individual", tools.initIterate, creator.Individual, self.generate_solution_random) toolbox.register("population", tools.initRepeat, list, toolbox.individual) toolbox.register("evaluate", self.evaluate_serv_assig) # toolbox.register("mate", tools.cxTwoPoint) toolbox.register("mate", tools.cxUniform, indpb=0.05) toolbox.register("mutate", self.single_inteligent_mut, localrate=localrate, maxtries=50) # toolbox.register("mutate", tools.mutUniformInt, low = 1, up = upper_limits, indpb=0.05) toolbox.register("select", tools.selTournament, tournsize=3) pop = toolbox.population(n=popsize) hof = tools.HallOfFame(1) stats = tools.Statistics(lambda ind: ind.fitness.values) stats.register("avg", numpy.mean) stats.register("std", numpy.std) stats.register("min", numpy.min) stats.register("max", numpy.max) pop, log = algorithms.eaSimple(pop, toolbox, cxpb=0.5, mutpb=1.0, ngen=numgen, stats=stats, halloffame=hof, verbose=True) #print(pop) #print(log) best_sol = hof[0] res = {} res["popsize"] = popsize res["evals"] = maxevals if self.opt_rout_weig: size_assig = len(self.ord_users) * len(self.ord_services) assig = self.decode_serv_assig(best_sol[:size_assig]) w = self.decode_weights(best_sol[size_assig:]) res["of_value"] = self.composite.of_normalized_penalty( assig, True, self.mincost, sp_weights=w) of = self.composite.of_normalized_penalty(assig, False, self.mincost, sp_weights=w, return_dic=True) res["of_fh"] = of["fh"] res["of_e2e"] = of["e2e"] res["of_cost"] = of["cost"] res["of_cong"] = of["cong"] else: assig = self.decode_serv_assig(best_sol) res["of_value"] = self.composite.of_normalized_penalty( assig, True, self.mincost) of = self.composite.of_normalized_penalty(assig, False, self.mincost, return_dic=True) res["of_fh"] = of["fh"] res["of_e2e"] = of["e2e"] res["of_cost"] = of["cost"] if not self.composite.congestion_cost: ## reporting congestion even if not used in the optimization dem = self.composite.generate_e2e_demands(assig.dic_assig) l = Loads(self.composite.network) l.add_loads_from_paths(self.composite.del_paths, dem) if self.composite.cong_of == "mlu": cong = l.mlu()[0] elif self.composite.cong_of == "alu": cong = l.alu() elif self.composite.cong_of == "fortz": co = CongestionOptimization(self.composite.network, dem) phiu = co.phi_uncap() cong = l.fortz_of(phiu) - 1.0 print("Congestion (not optimized):", cong) res["of_cong"] = cong else: res["of_cong"] = of["cong"] print("Objective function value: ", res["of_value"]) # NEED TO CHECK HOW TO SAVE Logbook to file # if (save_file is not None): # f = open(save_file, "w") # f.write(log) # f.close() return assig, res