コード例 #1
0
ファイル: ea_congestion.py プロジェクト: ptkhoa1984/CNO
 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()
コード例 #2
0
ファイル: composite.py プロジェクト: 5g-media/CNO
    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
コード例 #3
0
ファイル: composite.py プロジェクト: 5g-media/CNO
 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
コード例 #4
0
    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
コード例 #5
0
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
コード例 #6
0
ファイル: composite.py プロジェクト: 5g-media/CNO
    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)
コード例 #7
0
    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)
コード例 #8
0
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)
コード例 #9
0
ファイル: ea_congestion.py プロジェクト: ptkhoa1984/CNO
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)
コード例 #10
0
ファイル: deap_composite.py プロジェクト: ptkhoa1984/CNO
    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