예제 #1
0
def fitness(individual: IndividualType, indices: IndicesType, init_state: Dict,
            fleet: Fleet, hp: HyperParameters):
    """
    Positive fitness of the individual.
    :param individual: the individual to evaluate
    :param fleet: fleet instance
    :param hp: GA hyper-parameters
    :return: fitness value of the individual (positive)
    """

    # Decode
    routes = decode(individual, indices, init_state, fleet)

    # Set routes
    fleet.set_routes_of_vehicles(routes)

    # Cost
    costs = np.array(fleet.cost_function())

    # Calculate penalization
    feasible, distance, accept = fleet.feasible()

    penalization = distance + hp.hard_penalization if fleet.deterministic else distance

    # Calculate fitness
    fit = np.dot(costs, np.asarray(hp.weights)) + penalization

    return fit, feasible, accept
예제 #2
0
    def __init__(self,
                 network_path: str,
                 fleet_path: str,
                 measurements_path: str,
                 routes_path: str,
                 history_path: str,
                 mat_path: str,
                 sample_time: float,
                 main_folder: str = None,
                 std_factor: Tuple = (1., 1.),
                 create_routes_xml: bool = True,
                 create_measurements_xml: bool = True,
                 create_history_xml: bool = True):
        if main_folder:
            self.network_path = f'{main_folder}{network_path.split("/")[-1][:-4]}_temp.xml'
            self.fleet_path = f'{main_folder}{fleet_path.split("/")[-1][:-4]}_temp.xml'
        else:
            self.network_path = net_path
            self.fleet_path = fleet_path

        self.measurements_path = measurements_path
        self.history_path = history_path
        self.mat_path = mat_path
        self.sample_time = sample_time

        self.network = Network.from_xml(network_path, instance=False)
        self.fleet = Fleet.from_xml(fleet_path,
                                    assign_customers=False,
                                    with_routes=False,
                                    instance=False)

        self.network.write_xml(self.network_path, print_pretty=False)
        self.fleet.write_xml(self.fleet_path,
                             network_in_file=False,
                             assign_customers=False,
                             with_routes=False,
                             print_pretty=False)

        self.day_points = int(1440 / self.network.edges[0][0].sample_time)

        self.data = self.data_from_mat_file()

        if main_folder:
            self.routes_path = f'{main_folder}{routes_path.split("/")[-1]}'
        else:
            self.routes_path = routes_path

        self.routes, self.depart_info = Dispatcher.read_routes(
            routes_path, read_depart_info=True)
        Dispatcher.write_routes(self.routes_path,
                                self.routes,
                                self.depart_info,
                                write_pretty=False)

        self.measurements, _ = self.create_measurements_file()
        self.history = FleetHistory().create_from_routes(self.routes)
        self.save_history()

        self.std_factor = std_factor
예제 #3
0
def fitness(individual: IndividualType, fleet: Fleet,
            hp: AlphaGA_HyperParameters):
    """
    Positive fitness of the individual.
    :param individual: the individual to evaluate
    :param fleet: fleet instance
    :param hp: GA hyper-parameters
    :return: fitness value of the individual (positive)
    """

    # Decode
    routes = decode(individual, fleet, hp)

    # Set routes
    fleet.set_routes_of_vehicles(routes)

    # Iterate
    fleet.iterate()

    # Cost
    costs = np.array(fleet.cost_function()
                     )  # cost_tt, cost_ec, cost_chg_time, cost_chg_cost

    # Calculate penalization
    feasible, distance, accept = fleet.feasible()

    if distance > 0.:
        penalization = distance + hp.hard_penalization
    else:
        penalization = 0

    # Calculate fitness
    fit = np.dot(costs, np.asarray(hp.weights)) + penalization

    return fit, feasible, accept
예제 #4
0
def fitness(individual: IndividualType, indices: IndicesType,
            critical_points: Dict, fleet: Fleet, hp: HyperParameters):
    """
    Calculates fitness of individual.
    """

    # Decode
    m = len(fleet.vehicles)
    routes = decode(individual, indices, critical_points, fleet, hp)

    # Set routes
    reaching_states = {
        id_ev: (r.x1_0, r.x2_0, r.x3_0)
        for id_ev, r in critical_points.items()
    }
    vehicles_pos = [cp.S0 for cp in critical_points.values()]
    init_theta = np.array(
        [1 if i in vehicles_pos else 0 for i in range(len(fleet.network))])
    fleet.set_routes_of_vehicles(routes,
                                 reaching_states=reaching_states,
                                 init_theta=init_theta)

    # Cost
    costs = np.array(fleet.cost_function())

    # Calculate penalization
    feasible, distance, accept = fleet.feasible()

    penalization = 0
    if not accept:
        penalization = distance + hp.hard_penalization + hp.K2
    elif accept and not feasible:
        penalization = distance + hp.hard_penalization

    # Calculate fitness
    fit = np.dot(costs, np.asarray(hp.weights)) + penalization

    return fit, feasible, accept
예제 #5
0
def alphaGA(fleet: Fleet,
            hp: AlphaGA_HyperParameters,
            save_to: str = None,
            init_pop=None,
            savefig=False,
            plot_best_generation=False):
    # OBJECTS
    creator.create("FitnessMin", base.Fitness, weights=(-1.0, ))
    creator.create("Individual",
                   list,
                   fitness=creator.FitnessMin,
                   feasible=False,
                   acceptable=False)

    # TOOLBOX
    toolbox = base.Toolbox()
    toolbox.register("individual",
                     random_individual,
                     num_customers=len(fleet.network.customers),
                     num_cs=len(fleet.network.charging_stations),
                     m=len(fleet),
                     r=hp.r)
    toolbox.register("evaluate", fitness, fleet=fleet, hp=hp)
    toolbox.register("mate",
                     crossover,
                     fleet=fleet,
                     hp=hp,
                     block_probability=(.33, .33, .33),
                     index=None)
    toolbox.register("mutate",
                     mutate,
                     fleet=fleet,
                     hp=hp,
                     block_probability=(.33, .33, .33),
                     index=None)
    toolbox.register("select",
                     tools.selTournament,
                     tournsize=hp.tournament_size)
    toolbox.register("select_worst", tools.selWorst)
    toolbox.register("decode", decode, fleet=fleet, hp=hp)

    # BEGIN ALGORITHM
    t_init = time.time()

    # Population from first candidates
    random_inds_num = int(hp.num_individuals / 3)
    init_size = len(init_pop)
    mutate_num = hp.num_individuals - init_size - random_inds_num
    pop = [creator.Individual(i) for i in init_pop]

    # Random population
    pop += [
        toolbox.mutate(toolbox.clone(pop[randint(0, init_size - 1)]))
        for i in range(mutate_num)
    ]
    pop += [
        creator.Individual(toolbox.individual())
        for _ in range(random_inds_num)
    ]

    # Evaluate the initial population and get fitness of each individual
    for k, ind in enumerate(pop):
        fit, feasible, acceptable = toolbox.evaluate(ind)
        ind.fitness.values = (fit, )
        ind.feasible = feasible
        ind.acceptable = acceptable

    print(f'  Evaluated {len(pop)} individuals')
    bestOfAll = tools.selBest(pop, 1)[0]
    print(
        f"Best individual  : {bestOfAll}\n Fitness: {bestOfAll.fitness.wvalues[0]} Feasible: {bestOfAll.feasible}"
    )

    # These will save statistics
    cs_capacity = fleet.network.nodes[
        fleet.network.charging_stations[0]].capacity
    opt_data = GenerationsData([], [], [], [], [], [], fleet, hp, bestOfAll,
                               bestOfAll.feasible, bestOfAll.acceptable,
                               len(fleet), cs_capacity)

    print("################  Start of evolution  ################")
    # Begin the evolution
    for g in range(hp.max_generations):
        # A new generation
        print(f"-- Generation {g}/{hp.max_generations} --")
        opt_data.generations.append(g)

        # Update block probabilities
        if g < 50:
            block_probabilities = (.33, .33, .33)
        elif g < 100:
            block_probabilities = (.2, .6, .2)
        elif g < 150:
            block_probabilities = (.6, .2, .2)
        elif g < 200:
            block_probabilities = (.33, .33, .33)
        elif g < 250:
            block_probabilities = (.2, .6, .2)
        elif g < 300:
            block_probabilities = (.6, .2, .33)
        else:
            block_probabilities = (.33, .33, .33)

        # Select the best individuals, if given
        if hp.elite_individuals:
            best_individuals = list(
                map(toolbox.clone, tools.selBest(pop, hp.elite_individuals)))

        # Select and clone the next generation individuals
        offspring = toolbox.select(pop, len(pop))
        offspring = list(map(toolbox.clone, offspring))

        # Mutation
        for mutant in offspring:
            if random() < hp.MUTPB:
                toolbox.mutate(mutant, block_probability=block_probabilities)
                del mutant.fitness.values

        # Crossover
        for child1, child2 in zip(offspring[::2], offspring[1::2]):
            if random() < hp.CXPB:
                toolbox.mate(child1, child2)
                del child1.fitness.values
                del child2.fitness.values

        # Evaluate the individuals with invalid fitness
        invalid_ind = [ind for ind in offspring if not ind.fitness.valid]
        for ind in invalid_ind:
            fit, feasible, acceptable = toolbox.evaluate(ind)
            ind.fitness.values = (fit, )
            ind.feasible = feasible
            ind.acceptable = acceptable

        print(f'  Evaluated {len(invalid_ind)} individuals')

        # The population is entirely replaced by a sorted offspring
        pop[:] = offspring
        pop[:] = tools.selBest(pop, len(pop))

        # Insert best individuals from previous generation
        if hp.elite_individuals:
            pop[:] = best_individuals + pop[:-hp.elite_individuals]

        # Update best individual
        bestInd = tools.selBest(pop, 1)[0]
        if bestInd.fitness.wvalues[0] > bestOfAll.fitness.wvalues[0]:
            bestOfAll = bestInd

        # Real-time info
        print(
            f"Best individual  : {bestInd}\n Fitness: {bestInd.fitness.wvalues[0]} Feasible: {bestInd.feasible} Acceptable: {bestInd.acceptable}"
        )

        worstInd = tools.selWorst(pop, 1)[0]
        print(
            f"Worst individual : {worstInd}\n Fitness: {worstInd.fitness.wvalues[0]} Feasible: {worstInd.feasible}  Acceptable: {worstInd.acceptable}"
        )

        print(
            f"Curr. best-of-all: {bestOfAll}\n Fitness: {bestOfAll.fitness.wvalues[0]} Feasible: {bestOfAll.feasible}  Acceptable: {bestOfAll.acceptable}"
        )

        # Statistics
        fits = [sum(ind.fitness.wvalues) for ind in pop]
        mean = np.average(fits)
        std = np.std(fits)

        print(f"Max {max(fits)}")
        print(f"Min {min(fits)}")
        print(f"Avg {mean}")
        print(f"Std {std}")

        opt_data.best_fitness.append(-max(fits))
        opt_data.worst_fitness.append(-min(fits))
        opt_data.average_fitness.append(mean)
        opt_data.std_fitness.append(std)
        opt_data.best_individuals.append(bestInd)

        print()

        if plot_best_generation:
            toolbox.evaluate(bestOfAll)
            fleet.plot_operation_pyplot()
            plt.show()
            input('Press ENTER to evolve...')

    t_end = time.time()
    print("################  End of (successful) evolution  ################")

    algo_time = t_end - t_init
    print('Algorithm time:', algo_time)

    fit, feasible, acceptable = toolbox.evaluate(bestOfAll)
    routes = toolbox.decode(bestOfAll)

    opt_data.bestOfAll = bestOfAll
    opt_data.feasible = feasible
    opt_data.acceptable = acceptable
    opt_data.algo_time = algo_time
    opt_data.fleet = fleet

    if save_to:
        path = save_to + hp.algorithm_name + f'_fleetsize_{len(fleet)}/'
        try:
            os.mkdir(path)
        except FileExistsError:
            pass
        opt_data.save_opt_data(path, savefig=savefig)
    return routes, opt_data, toolbox
max_payload = 0.58  # tonnes
weight = 1.52  # tonnes
max_tour_duration = 7 * 60.

# %% Instance fleet
if stochastic:
    ev = Fleet.EV.GaussianElectricVehicle(ev_id, weight, battery_capacity,
                                          battery_capacity_nominal, alpha_upp,
                                          alpha_down, max_tour_duration,
                                          max_payload)
else:
    ev = Fleet.EV.ElectricVehicle(ev_id, weight, battery_capacity,
                                  battery_capacity_nominal, alpha_upp,
                                  alpha_down, max_tour_duration, max_payload)

if stochastic:
    fleet = Fleet.GaussianFleet({0: ev}, network)
else:
    fleet = Fleet.Fleet({0: ev}, network)

fleet.hard_penalization = hard_penalization
fleet.resize_fleet(fleet_size)
# %% Save fleet
fleet.write_xml(f'{main_folder}fleet.xml',
                network_in_file=True,
                assign_customers=False,
                with_routes=False,
                print_pretty=print_pretty)

fleet2 = Fleet.from_xml(f'{main_folder}fleet.xml')
예제 #7
0
def betaGA(fleet: Fleet,
           hp: HyperParameters,
           save_to: str = None,
           best_ind: IndividualType = None,
           savefig=False):
    fleet.assign_customers_in_route()
    customers_to_visit = {
        ev_id: ev.assigned_customers
        for ev_id, ev in fleet.vehicles.items()
    }
    starting_points = {
        ev_id: (0, 0, fleet.vehicles[ev_id].state_leaving[0, 0], ev.alpha_up,
                sum([fleet.network.demand(x) for x in ev.assigned_customers]))
        for ev_id, ev in fleet.vehicles.items()
    }
    indices = block_indices(customers_to_visit)

    # Fitness objects
    creator.create("FitnessMin", base.Fitness, weights=(-1.0, ))
    creator.create("Individual",
                   list,
                   fitness=creator.FitnessMin,
                   feasible=False,
                   acceptable=False)

    # Toolbox
    toolbox = base.Toolbox()

    toolbox.register("individual",
                     random_individual,
                     customers_per_vehicle=customers_to_visit,
                     charging_stations=fleet.network.charging_stations)
    toolbox.register("evaluate",
                     fitness,
                     indices=indices,
                     init_state=starting_points,
                     fleet=fleet,
                     hp=hp)
    toolbox.register("mate", crossover, indices=indices, hp=hp)
    toolbox.register("mutate",
                     mutate,
                     indices=indices,
                     charging_stations=fleet.network.charging_stations,
                     hp=hp)
    toolbox.register("select",
                     tools.selTournament,
                     tournsize=hp.tournament_size)
    toolbox.register("select_worst", tools.selWorst)
    toolbox.register("decode",
                     decode,
                     indices=indices,
                     init_state=starting_points,
                     fleet=fleet)

    # BEGIN ALGORITHM
    t_init = time.time()

    # Random population
    if best_ind is not None:
        pop = [creator.Individual(best_ind)]
    else:
        pop = []

    pop.append(creator.Individual(individual_from_routes(fleet)))
    pop = pop + [
        creator.Individual(toolbox.individual())
        for i in range(hp.num_individuals - len(pop))
    ]

    # Evaluate the initial population and get fitness of each individual
    for ind in pop:
        fit, feasible, acceptable = toolbox.evaluate(ind)
        ind.fitness.values = (fit, )
        ind.feasible = feasible
        ind.acceptable = acceptable

    print(f'  Evaluated {len(pop)} individuals')
    bestOfAll = tools.selBest(pop, 1)[0]
    print(
        f"Best individual  : {bestOfAll}\n Fitness: {bestOfAll.fitness.wvalues[0]} Feasible: {bestOfAll.feasible}"
    )

    # These will save statistics
    m = len(fleet)
    cs_capacity = fleet.network.nodes[
        fleet.network.charging_stations[0]].capacity
    opt_data = GenerationsData([], [], [], [], [], [], fleet, hp, bestOfAll,
                               bestOfAll.feasible, bestOfAll.acceptable, m,
                               cs_capacity)

    print("################  Start of evolution  ################")
    # Begin the evolution
    for g in range(hp.max_generations):
        # A new generation
        print(f"-- Generation {g}/{hp.max_generations} --")
        opt_data.generations.append(g)

        # Update block probabilities
        if g < 50:
            block_probabilities = (.33, .33, .33)
        elif g < 100:
            block_probabilities = (.2, .6, .2)
        elif g < 150:
            block_probabilities = (.6, .2, .2)
        elif g < 200:
            block_probabilities = (.33, .33, .33)
        elif g < 250:
            block_probabilities = (.2, .6, .2)
        elif g < 300:
            block_probabilities = (.6, .2, .33)
        else:
            block_probabilities = (.33, .33, .33)

        # Select the best individuals, if given
        if hp.elite_individuals:
            best_individuals = list(
                map(toolbox.clone, tools.selBest(pop, hp.elite_individuals)))

        # Select and clone the next generation individuals
        offspring = toolbox.select(pop, len(pop))
        offspring = list(map(toolbox.clone, offspring))

        # Mutation
        for mutant in offspring:
            if random() < hp.MUTPB:
                toolbox.mutate(mutant)
                del mutant.fitness.values

        # Crossover
        for child1, child2 in zip(offspring[::2], offspring[1::2]):
            if random() < hp.CXPB:
                toolbox.mate(child1, child2)
                del child1.fitness.values
                del child2.fitness.values

        # Evaluate the individuals with invalid fitness
        invalid_ind = [ind for ind in offspring if not ind.fitness.valid]
        for ind in invalid_ind:
            fit, feasible, acceptable = toolbox.evaluate(ind)
            ind.fitness.values = (fit, )
            ind.feasible = feasible
            ind.acceptable = acceptable

        print(f'  Evaluated {len(invalid_ind)} individuals')

        # The population is entirely replaced by a sorted offspring
        pop[:] = offspring
        pop[:] = tools.selBest(pop, len(pop))

        # Insert best individuals from previous generation
        if hp.elite_individuals:
            pop[:] = best_individuals + pop[:-hp.elite_individuals]

        # Update best individual
        bestInd = tools.selBest(pop, 1)[0]
        if bestInd.fitness.wvalues[0] > bestOfAll.fitness.wvalues[0]:
            bestOfAll = bestInd

        # Real-time info
        print(
            f"Best individual  : {bestInd}\n Fitness: {bestInd.fitness.wvalues[0]} Feasible: {bestInd.feasible}"
        )

        worstInd = tools.selWorst(pop, 1)[0]
        print(
            f"Worst individual : {worstInd}\n Fitness: {worstInd.fitness.wvalues[0]} Feasible: {worstInd.feasible}"
        )

        print(
            f"Curr. best-of-all: {bestOfAll}\n Fitness: {bestOfAll.fitness.wvalues[0]} Feasible: {bestOfAll.feasible}"
        )

        # Statistics
        fits = [sum(ind.fitness.wvalues) for ind in pop]
        mean = np.average(fits)
        std = np.std(fits)

        print(f"Max {max(fits)}")
        print(f"Min {min(fits)}")
        print(f"Avg {mean}")
        print(f"Std {std}")

        opt_data.best_fitness.append(-max(fits))
        opt_data.worst_fitness.append(-min(fits))
        opt_data.average_fitness.append(mean)
        opt_data.std_fitness.append(std)
        opt_data.best_individuals.append(bestInd)

        print()

    t_end = time.time()
    print("################  End of (successful) evolution  ################")

    algo_time = t_end - t_init
    print('Algorithm time:', algo_time)

    fit, feasible, acceptable = toolbox.evaluate(bestOfAll)
    routes = toolbox.decode(bestOfAll)

    opt_data.bestOfAll = bestOfAll
    opt_data.feasible = feasible
    opt_data.acceptable = acceptable
    opt_data.algo_time = algo_time
    opt_data.fleet = fleet

    if save_to:
        path = save_to + hp.algorithm_name + f'_fleetsize_{m}/'
        try:
            os.mkdir(path)
        except FileExistsError:
            pass
        opt_data.save_opt_data(path, savefig=savefig)

    return routes, opt_data, toolbox
예제 #8
0
 def update_fleet(self):
     self.fleet = Fleet.from_xml(self.fleet_path, assign_customers=False, with_routes=False, instance=False,
                                 from_online=False)
                                           MUTPB=0.85,
                                           hard_penalization=200000,
                                           elite_individuals=1,
                                           tournament_size=5,
                                           r=3)
hp_beta = GATools.BetaGA_HyperParameters(weights,
                                         CXPB=0.6,
                                         MUTPB=0.8,
                                         hard_penalization=200000,
                                         elite_individuals=1,
                                         tournament_size=5)

if __name__ == '__main__':
    for i in range(3):
        # %% Read instance data
        fleet = Fleet.from_xml(folder + instance_name + '.xml')
        soc_policy = (fleet.vehicles[0].alpha_down, fleet.vehicles[0].alpha_up)

        # %% Initial population and fleet size
        N = int(
            sum([fleet.network.demand(i) for i in fleet.network.customers]) /
            fleet.vehicles[0].max_payload) + 1
        fill_up_to = N / (
            N + additional_vehicles) if additional_vehicles else fill_up_to
        init_pop, m = alphaGA.heuristic_population_1(hp_alpha.r, fleet,
                                                     fill_up_to)
        fleet.resize_fleet(m)
        hp_alpha.num_individuals = 10 * len(fleet) + 5 * len(
            fleet.network) + 10
        hp_alpha.max_generations = 3 * hp_alpha.num_individuals + 15
        hp_alpha.alpha_up = fleet.vehicles[0].alpha_up