-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProgram.py
More file actions
79 lines (66 loc) · 3.92 KB
/
Copy pathProgram.py
File metadata and controls
79 lines (66 loc) · 3.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# Required Libraries
import random
import numpy as np
import matplotlib.pyplot as plt
from deap import base, creator, tools, algorithms
# Task 1 - Define the number of locations and vehicles
num_locations = 20 # Define how many locations (excluding the depot) the vehicles need to visit
locations = [(random.randint(0, 100), random.randint(0, 100)) for _ in range(num_locations)] # Generate random (x, y) coordinates for each location
depot = (50, 50) # Define the central depot location as a fixed point
num_vehicles = 3 # Define how many vehicles are available to visit the locations
# Genetic Algorithm Setup
creator.create("FitnessMin", base.Fitness, weights=(-1.0, -1.0)) # Define fitness function to minimize. The two objectives are total distance and balance penalty.
creator.create("Individual", list, fitness=creator.FitnessMin) # Define individual structure. Individuals are lists with a fitness attribute.
# Task 2 - Finish setting up the individuals and population
toolbox = base.Toolbox()
toolbox.register("indices", random.sample, range(num_locations), num_locations) # Function to generate a list of unique, randomly ordered location indices
toolbox.register("individual", tools.initIterate, creator.Individual, toolbox.indices) # Function to create an individual as a shuffled list of location indices
toolbox.register("population", tools.initRepeat, list, toolbox.individual) # Function to create a population of individuals
# Fitness Function
def evalVRP(individual):
total_distance = 0
distances = [] # Track distance traveled by each vehicle for balance calculation
# Split the list of locations among vehicles, ensuring each starts and ends at the depot
for i in range(num_vehicles):
vehicle_route = [depot] + [locations[individual[j]] for j in range(i, len(individual), num_vehicles)] + [depot]
# Calculate total distance traveled by this vehicle
vehicle_distance = sum(np.linalg.norm(np.array(vehicle_route[k+1]) - np.array(vehicle_route[k])) for k in range(len(vehicle_route)-1))
total_distance += vehicle_distance
distances.append(vehicle_distance)
balance_penalty = np.std(distances) # Use standard deviation of distances as a penalty for imbalance among vehicles
return total_distance, balance_penalty
toolbox.register("evaluate", evalVRP) # Register the evaluation function
toolbox.register("mate", tools.cxPartialyMatched) # Register the crossover function suitable for permutation-based representation
toolbox.register("mutate", tools.mutShuffleIndexes, indpb=0.05) # Register the mutation function to shuffle indices with a 5% chance per index
toolbox.register("select", tools.selTournament, tournsize=3) # Register the selection function using tournament selection
# Plotting Function
def plot_routes(individual, title="Routes"):
plt.figure()
# Plot locations as blue dots and the depot as a red square
for (x, y) in locations:
plt.plot(x, y, 'bo')
plt.plot(depot[0], depot[1], 'rs')
# Draw routes for each vehicle
for i in range(num_vehicles):
vehicle_route = [depot] + [locations[individual[j]] for j in range(i, len(individual), num_vehicles)] + [depot]
plt.plot(*zip(*vehicle_route), '-')
plt.title(title)
plt.xlabel('X Coordinate')
plt.ylabel('Y Coordinate')
plt.show()
# Running the Genetic Algorithm
def main():
random.seed(42) # Seed for reproducibility
pop = toolbox.population(n=300) # Generate initial population
hof = tools.HallOfFame(1) # Hall of Fame to store the best individual
# Setup statistics to track
stats = tools.Statistics(lambda ind: ind.fitness.values)
stats.register("avg", np.mean)
stats.register("min", np.min)
# Run the genetic algorithm
algorithms.eaSimple(pop, toolbox, 0.7, 0.2, 300, stats=stats, halloffame=hof)
# Plot the best route found
plot_routes(hof[0], "Optimal Route")
return pop, stats, hof
if __name__ == "__main__":
main()