new deliverable
This commit is contained in:
parent
312b168ed4
commit
7b6d997110
@ -264,7 +264,7 @@
|
|||||||
"id": "7670fdf4-884c-4352-83fa-eed0c8b50074",
|
"id": "7670fdf4-884c-4352-83fa-eed0c8b50074",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"source": [
|
"source": [
|
||||||
"## <u>Resolution algorithm </u>"
|
"## <u>Resolution algorithm (with coordinates)</u>"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -287,809 +287,7 @@
|
|||||||
"import matplotlib.pyplot as plt\n",
|
"import matplotlib.pyplot as plt\n",
|
||||||
"import numpy as np\n",
|
"import numpy as np\n",
|
||||||
"import random, time, math\n",
|
"import random, time, math\n",
|
||||||
"from tests.clustering import split_tour_across_clusters"
|
"from tests.libs.clustering import split_tour_across_clusters"
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "code",
|
|
||||||
"execution_count": 17,
|
|
||||||
"id": "c177ac22",
|
|
||||||
"metadata": {},
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"ename": "AttributeError",
|
|
||||||
"evalue": "module 'networkx.linalg.graphmatrix' has no attribute 'to_numpy_matrix'",
|
|
||||||
"output_type": "error",
|
|
||||||
"traceback": [
|
|
||||||
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
|
|
||||||
"\u001b[1;31mAttributeError\u001b[0m Traceback (most recent call last)",
|
|
||||||
"Cell \u001b[1;32mIn[17], line 41\u001b[0m\n\u001b[0;32m 38\u001b[0m \u001b[39mreturn\u001b[39;00m adjacency_matrix\n\u001b[0;32m 40\u001b[0m \u001b[39m# Générer la matrice d'adjacence pondérée\u001b[39;00m\n\u001b[1;32m---> 41\u001b[0m weighted_adjacency_matrix \u001b[39m=\u001b[39m generate_weighted_adjacency_matrix(graph)\n\u001b[0;32m 43\u001b[0m \u001b[39m# Afficher la matrice d'adjacence pondérée\u001b[39;00m\n\u001b[0;32m 44\u001b[0m \u001b[39mprint\u001b[39m(weighted_adjacency_matrix)\n",
|
|
||||||
"Cell \u001b[1;32mIn[17], line 36\u001b[0m, in \u001b[0;36mgenerate_weighted_adjacency_matrix\u001b[1;34m(graph)\u001b[0m\n\u001b[0;32m 34\u001b[0m \u001b[39mdef\u001b[39;00m \u001b[39mgenerate_weighted_adjacency_matrix\u001b[39m(graph):\n\u001b[0;32m 35\u001b[0m \u001b[39m# Créer une matrice d'adjacence pondérée à partir du graphe\u001b[39;00m\n\u001b[1;32m---> 36\u001b[0m adjacency_matrix \u001b[39m=\u001b[39m graphmatrix\u001b[39m.\u001b[39;49mto_numpy_matrix(graph, weight\u001b[39m=\u001b[39m\u001b[39m'\u001b[39m\u001b[39mdistance\u001b[39m\u001b[39m'\u001b[39m)\n\u001b[0;32m 38\u001b[0m \u001b[39mreturn\u001b[39;00m adjacency_matrix\n",
|
|
||||||
"\u001b[1;31mAttributeError\u001b[0m: module 'networkx.linalg.graphmatrix' has no attribute 'to_numpy_matrix'"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"source": [
|
|
||||||
"\n",
|
|
||||||
"import random\n",
|
|
||||||
"import numpy as np\n",
|
|
||||||
"import networkx as nx\n",
|
|
||||||
"import matplotlib.pyplot as plt\n",
|
|
||||||
"import time as time\n",
|
|
||||||
"\n",
|
|
||||||
"from networkx.linalg import graphmatrix\n",
|
|
||||||
"\n",
|
|
||||||
"def generate_graph(num_nodes):\n",
|
|
||||||
" G = nx.Graph()\n",
|
|
||||||
" G.add_nodes_from(range(num_nodes + 1))\n",
|
|
||||||
" \n",
|
|
||||||
" for node in G.nodes():\n",
|
|
||||||
" connected_nodes = sorted(set(G.nodes()) - {node})\n",
|
|
||||||
" if len(connected_nodes) < 2:\n",
|
|
||||||
" continue\n",
|
|
||||||
" distance1 = random.randint(1, 10)\n",
|
|
||||||
" distance2 = random.randint(1, 10)\n",
|
|
||||||
" random_nodes = random.sample(connected_nodes, 2)\n",
|
|
||||||
" G.add_edges_from([(node, random_nodes[0], {'distance': distance1}),\n",
|
|
||||||
" (node, random_nodes[1], {'distance': distance2})])\n",
|
|
||||||
"\n",
|
|
||||||
" while not nx.is_connected(G):\n",
|
|
||||||
" node1, node2 = random.sample(G.nodes(), 2)\n",
|
|
||||||
" if not G.has_edge(node1, node2):\n",
|
|
||||||
" distance = random.randint(1, 10)\n",
|
|
||||||
" G.add_edge(node1, node2, distance=distance)\n",
|
|
||||||
"\n",
|
|
||||||
" return G\n",
|
|
||||||
"\n",
|
|
||||||
"graph = generate_graph(12)\n",
|
|
||||||
"A = nx.adjacency_matrix(graph)\n",
|
|
||||||
"\n",
|
|
||||||
"def generate_weighted_adjacency_matrix(graph):\n",
|
|
||||||
" # Créer une matrice d'adjacence pondérée à partir du graphe\n",
|
|
||||||
" adjacency_matrix = graphmatrix.to_numpy_matrix(graph, weight='distance')\n",
|
|
||||||
"\n",
|
|
||||||
" return adjacency_matrix\n",
|
|
||||||
"\n",
|
|
||||||
"# Générer la matrice d'adjacence pondérée\n",
|
|
||||||
"weighted_adjacency_matrix = generate_weighted_adjacency_matrix(graph)\n",
|
|
||||||
"\n",
|
|
||||||
"# Afficher la matrice d'adjacence pondérée\n",
|
|
||||||
"print(weighted_adjacency_matrix)\n",
|
|
||||||
"\n",
|
|
||||||
"\n",
|
|
||||||
"def generate_distance_matrix(graph):\n",
|
|
||||||
" num_nodes = graph.number_of_nodes()\n",
|
|
||||||
" distance_array = np.full((num_nodes, num_nodes), float('inf')) # Initialiser avec l'infini\n",
|
|
||||||
" for edge in graph.edges(data=True):\n",
|
|
||||||
" i, j, data = edge\n",
|
|
||||||
" distance_array[i][j] = data['distance']\n",
|
|
||||||
" distance_array[j][i] = data['distance'] # Pour un graphe non orienté\n",
|
|
||||||
" np.fill_diagonal(distance_array, 0) # Remplir la diagonale avec des zéros\n",
|
|
||||||
" return distance_array\n",
|
|
||||||
"\n",
|
|
||||||
"# Générer la matrice de distances\n",
|
|
||||||
"distance_matrix = generate_distance_matrix(graph)\n",
|
|
||||||
"\n",
|
|
||||||
"\n",
|
|
||||||
"# Afficher la matrice de distances\n",
|
|
||||||
"print(distance_matrix)\n",
|
|
||||||
"\n",
|
|
||||||
"\n",
|
|
||||||
"\n",
|
|
||||||
"# Dessiner le graphe\n",
|
|
||||||
"nx.draw(graph, with_labels=True)\n",
|
|
||||||
"plt.show()"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"attachments": {},
|
|
||||||
"cell_type": "markdown",
|
|
||||||
"id": "9aac4453",
|
|
||||||
"metadata": {},
|
|
||||||
"source": [
|
|
||||||
"# On applique l'algorithme des fourmis (ACO) sur notre graphe\n"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "code",
|
|
||||||
"execution_count": 10,
|
|
||||||
"id": "23e32e2a",
|
|
||||||
"metadata": {},
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "stdout",
|
|
||||||
"output_type": "stream",
|
|
||||||
"text": [
|
|
||||||
"Meilleure solution : [[6, 5, 4, 8, 1, 11, 0], [9, 3, 7, 12, 10, 2, 0]]\n",
|
|
||||||
"Distance totale : 81.0\n"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"source": [
|
|
||||||
"import concurrent.futures\n",
|
|
||||||
"num_trucks = 2 # Nombre de camions disponibles\n",
|
|
||||||
"\n",
|
|
||||||
"\n",
|
|
||||||
"# Fonction d'évaluation de la qualité d'une solution (ici, la distance totale)\n",
|
|
||||||
"def evaluate_solution(solution, distances):\n",
|
|
||||||
" total_distance = 0\n",
|
|
||||||
" num_nodes = len(solution)\n",
|
|
||||||
"\n",
|
|
||||||
" for i in range(num_nodes - 1):\n",
|
|
||||||
" current_node = solution[i]\n",
|
|
||||||
" next_node = solution[i + 1]\n",
|
|
||||||
" total_distance += distances[current_node][next_node]\n",
|
|
||||||
"\n",
|
|
||||||
"\n",
|
|
||||||
" # Ajouter la distance de retour au dépôt\n",
|
|
||||||
" total_distance += distances[solution[-1]][solution[0]]\n",
|
|
||||||
"\n",
|
|
||||||
" return total_distance\n",
|
|
||||||
"\n",
|
|
||||||
" \n",
|
|
||||||
"def ant_colony_optimization(distances, num_ants, num_iterations, evaporation_rate, alpha, beta, num_trucks):\n",
|
|
||||||
" num_nodes = len(distances)\n",
|
|
||||||
" \n",
|
|
||||||
" pheromone = np.ones((num_nodes, num_nodes)) # Matrice de phéromones initiale\n",
|
|
||||||
" best_solution = None\n",
|
|
||||||
" best_distance = float('inf')\n",
|
|
||||||
"\n",
|
|
||||||
" start_time = time.time()\n",
|
|
||||||
"\n",
|
|
||||||
" for iteration in range(num_iterations):\n",
|
|
||||||
" # Construction de solutions par les fourmis\n",
|
|
||||||
" solutions = []\n",
|
|
||||||
"\n",
|
|
||||||
" for ant in range(num_ants):\n",
|
|
||||||
" visited = set()\n",
|
|
||||||
" current_node = random.randint(0, num_nodes - 1)\n",
|
|
||||||
" visited.add(current_node)\n",
|
|
||||||
" solution = [current_node]\n",
|
|
||||||
"\n",
|
|
||||||
" while len(visited) < num_nodes:\n",
|
|
||||||
" next_node = None\n",
|
|
||||||
" probabilities = []\n",
|
|
||||||
"\n",
|
|
||||||
" # Calcul des probabilités de choisir chaque prochain nœud\n",
|
|
||||||
" for node in range(num_nodes):\n",
|
|
||||||
" if node not in visited and (node !=0 or len(visited) == num_nodes - 1):\n",
|
|
||||||
" pheromone_value = pheromone[current_node][node]\n",
|
|
||||||
" distance_value = distances[current_node][node]\n",
|
|
||||||
" probability = (pheromone_value ** alpha) * ((1 / distance_value) ** beta)\n",
|
|
||||||
" probabilities.append((node, probability))\n",
|
|
||||||
"\n",
|
|
||||||
" total_probability = sum(prob for _, prob in probabilities)\n",
|
|
||||||
" probabilities = [(node, prob / total_probability) for node, prob in probabilities]\n",
|
|
||||||
"\n",
|
|
||||||
" \n",
|
|
||||||
" roulette_wheel = random.random()\n",
|
|
||||||
" probability_sum = 0\n",
|
|
||||||
"\n",
|
|
||||||
"\n",
|
|
||||||
" for node, probability in probabilities:\n",
|
|
||||||
" \n",
|
|
||||||
" probability_sum += probability\n",
|
|
||||||
" if probability_sum >= roulette_wheel:\n",
|
|
||||||
" next_node = node\n",
|
|
||||||
" break\n",
|
|
||||||
"\n",
|
|
||||||
" visited.add(next_node)\n",
|
|
||||||
" solution.append(next_node)\n",
|
|
||||||
" current_node = next_node\n",
|
|
||||||
"\n",
|
|
||||||
" # Ajouter le retour au dépôt central à la fin du trajet\n",
|
|
||||||
" solution.append(0)\n",
|
|
||||||
"\n",
|
|
||||||
" solutions.append(solution)\n",
|
|
||||||
"\n",
|
|
||||||
" # Évaluation des solutions et mise à jour de la meilleure solution\n",
|
|
||||||
" for solution in solutions:\n",
|
|
||||||
" distance = evaluate_solution(solution, distances)\n",
|
|
||||||
" if distance < best_distance:\n",
|
|
||||||
" best_solution = solution\n",
|
|
||||||
" best_distance = distance\n",
|
|
||||||
"\n",
|
|
||||||
" # Mise à jour des phéromones\n",
|
|
||||||
" pheromone *= evaporation_rate # Évaporation des phéromones existantes\n",
|
|
||||||
"\n",
|
|
||||||
" for solution in solutions:\n",
|
|
||||||
" delta_pheromone = 1 / evaluate_solution(solution, distances)\n",
|
|
||||||
" for i in range(num_nodes - 1):\n",
|
|
||||||
" node1 = solution[i]\n",
|
|
||||||
" node2 = solution[i + 1]\n",
|
|
||||||
" pheromone[node1][node2] += delta_pheromone\n",
|
|
||||||
" pheromone[node2][node1] += delta_pheromone\n",
|
|
||||||
"\n",
|
|
||||||
" # Séparer la meilleure solution en trajets pour chaque camion\n",
|
|
||||||
" truck_solutions = []\n",
|
|
||||||
" num_nodes_per_truck = num_nodes // num_trucks\n",
|
|
||||||
"\n",
|
|
||||||
" for i in range(num_trucks):\n",
|
|
||||||
" start_index = i * num_nodes_per_truck\n",
|
|
||||||
" end_index = start_index + num_nodes_per_truck\n",
|
|
||||||
" truck_solution = best_solution[start_index:end_index]\n",
|
|
||||||
" truck_solutions.append(truck_solution + [0])\n",
|
|
||||||
" \n",
|
|
||||||
"\n",
|
|
||||||
" return truck_solutions, best_distance\n",
|
|
||||||
"\n",
|
|
||||||
"\n",
|
|
||||||
"def trucks_thread(i, num_nodes_per_truck, best_solution, truck_solutions):\n",
|
|
||||||
" start_index = i * num_nodes_per_truck\n",
|
|
||||||
" end_index = start_index + num_nodes_per_truck\n",
|
|
||||||
" truck_solution = best_solution[start_index:end_index]\n",
|
|
||||||
" truck_solutions.append(truck_solution)\n",
|
|
||||||
" return truck_solutions\n",
|
|
||||||
"\n",
|
|
||||||
"\n",
|
|
||||||
"num_ants = 10\n",
|
|
||||||
"num_iterations = 100\n",
|
|
||||||
"evaporation_rate = 0.5\n",
|
|
||||||
"alpha = 1\n",
|
|
||||||
"beta = 1\n",
|
|
||||||
"\n",
|
|
||||||
"best_truck_solutions, best_distance = ant_colony_optimization(distance_matrix, num_ants, num_iterations, evaporation_rate, alpha, beta, num_trucks)\n",
|
|
||||||
"\n",
|
|
||||||
"\n",
|
|
||||||
"print(\"Meilleure solution :\", best_truck_solutions)\n",
|
|
||||||
"print(\"Distance totale :\", best_distance)\n",
|
|
||||||
" "
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "code",
|
|
||||||
"execution_count": 11,
|
|
||||||
"id": "6928bbbd",
|
|
||||||
"metadata": {},
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"ename": "AttributeError",
|
|
||||||
"evalue": "module 'networkx' has no attribute 'from_numpy_matrix'",
|
|
||||||
"output_type": "error",
|
|
||||||
"traceback": [
|
|
||||||
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
|
|
||||||
"\u001b[1;31mAttributeError\u001b[0m Traceback (most recent call last)",
|
|
||||||
"Cell \u001b[1;32mIn[11], line 114\u001b[0m\n\u001b[0;32m 111\u001b[0m \u001b[39m# Pour chaque solution de camion, nous devons trouver le chemin le plus court du dépôt au premier nœud du chemin\u001b[39;00m\n\u001b[0;32m 112\u001b[0m \u001b[39mfor\u001b[39;00m i, truck_solution \u001b[39min\u001b[39;00m \u001b[39menumerate\u001b[39m(best_truck_solutions):\n\u001b[0;32m 113\u001b[0m \u001b[39m# Créer un graphe à partir de la matrice de distance\u001b[39;00m\n\u001b[1;32m--> 114\u001b[0m G \u001b[39m=\u001b[39m nx\u001b[39m.\u001b[39;49mfrom_numpy_matrix(distance_matrix)\n\u001b[0;32m 116\u001b[0m \u001b[39m# Utiliser l'algorithme de Dijkstra pour trouver le chemin le plus court du dépôt (nœud 0) au premier nœud du chemin du camion\u001b[39;00m\n\u001b[0;32m 117\u001b[0m shortest_path \u001b[39m=\u001b[39m nx\u001b[39m.\u001b[39mdijkstra_path(G, \u001b[39m0\u001b[39m, truck_solution[\u001b[39m1\u001b[39m])\n",
|
|
||||||
"\u001b[1;31mAttributeError\u001b[0m: module 'networkx' has no attribute 'from_numpy_matrix'"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"source": [
|
|
||||||
"num_trucks = 2 # Nombre de camions disponibles\n",
|
|
||||||
"\n",
|
|
||||||
"def evaluate_solution(solution, distances):\n",
|
|
||||||
" total_distance = 0\n",
|
|
||||||
" num_nodes = len(solution)\n",
|
|
||||||
"\n",
|
|
||||||
" # Calculer la distance entre chaque paire consécutive de nœuds dans la solution\n",
|
|
||||||
" for i in range(num_nodes - 1):\n",
|
|
||||||
" current_node = solution[i]\n",
|
|
||||||
" next_node = solution[i + 1]\n",
|
|
||||||
" total_distance += distances[current_node][next_node]\n",
|
|
||||||
"\n",
|
|
||||||
" # Ajouter la distance de retour au dépôt\n",
|
|
||||||
" total_distance += distances[solution[-1]][solution[0]]\n",
|
|
||||||
"\n",
|
|
||||||
" return total_distance\n",
|
|
||||||
"\n",
|
|
||||||
"def ant_colony_optimization(distances, num_ants, num_iterations, evaporation_rate, alpha, beta, num_trucks):\n",
|
|
||||||
" num_nodes = len(distances)\n",
|
|
||||||
" \n",
|
|
||||||
" pheromone = np.ones((num_nodes, num_nodes)) # Matrice de phéromones initiale\n",
|
|
||||||
" best_solution = None\n",
|
|
||||||
" best_distance = float('inf')\n",
|
|
||||||
"\n",
|
|
||||||
" for iteration in range(num_iterations):\n",
|
|
||||||
" # Construction de solutions par les fourmis\n",
|
|
||||||
" solutions = []\n",
|
|
||||||
"\n",
|
|
||||||
" for ant in range(num_ants):\n",
|
|
||||||
" visited = set()\n",
|
|
||||||
" current_node = 0 # Initialiser current_node à 0\n",
|
|
||||||
" visited.add(current_node)\n",
|
|
||||||
" solution = [current_node]\n",
|
|
||||||
"\n",
|
|
||||||
" while len(visited) < num_nodes:\n",
|
|
||||||
" next_node = None\n",
|
|
||||||
" probabilities = []\n",
|
|
||||||
"\n",
|
|
||||||
" # Calcul des probabilités de choisir chaque prochain nœud\n",
|
|
||||||
" for node in range(num_nodes):\n",
|
|
||||||
" if node not in visited and node < len(pheromone) and current_node < len(pheromone):\n",
|
|
||||||
" pheromone_value = pheromone[current_node][node]\n",
|
|
||||||
" distance_value = distances[current_node][node]\n",
|
|
||||||
" probability = (pheromone_value ** alpha) * ((1 / distance_value) ** beta)\n",
|
|
||||||
" probabilities.append((node, probability))\n",
|
|
||||||
"\n",
|
|
||||||
" total_probability = sum(prob for _, prob in probabilities)\n",
|
|
||||||
" probabilities = [(node, prob / total_probability) for node, prob in probabilities]\n",
|
|
||||||
"\n",
|
|
||||||
" roulette_wheel = random.random()\n",
|
|
||||||
" probability_sum = 0\n",
|
|
||||||
"\n",
|
|
||||||
" for node, probability in probabilities:\n",
|
|
||||||
" probability_sum += probability\n",
|
|
||||||
" if probability_sum >= roulette_wheel:\n",
|
|
||||||
" next_node = node\n",
|
|
||||||
" break\n",
|
|
||||||
"\n",
|
|
||||||
" visited.add(next_node)\n",
|
|
||||||
" solution.append(next_node)\n",
|
|
||||||
" current_node = next_node\n",
|
|
||||||
"\n",
|
|
||||||
" # Ajouter le retour au dépôt central à la fin du trajet\n",
|
|
||||||
" solution.append(0)\n",
|
|
||||||
"\n",
|
|
||||||
" solutions.append(solution)\n",
|
|
||||||
"\n",
|
|
||||||
" # Évaluation des solutions et mise à jour de la meilleure solution\n",
|
|
||||||
" for solution in solutions:\n",
|
|
||||||
" distance = evaluate_solution(solution, distances)\n",
|
|
||||||
" if distance < best_distance:\n",
|
|
||||||
" best_solution = solution\n",
|
|
||||||
" best_distance = distance\n",
|
|
||||||
"\n",
|
|
||||||
" # Mise à jour des phéromones\n",
|
|
||||||
" pheromone *= evaporation_rate # Évaporation des phéromones existantes\n",
|
|
||||||
"\n",
|
|
||||||
" for solution in solutions:\n",
|
|
||||||
" delta_pheromone = 1 / evaluate_solution(solution, distances)\n",
|
|
||||||
" for i in range(num_nodes - 1):\n",
|
|
||||||
" node1 = solution[i]\n",
|
|
||||||
" node2 = solution[i + 1]\n",
|
|
||||||
" pheromone[node1][node2] += delta_pheromone\n",
|
|
||||||
" pheromone[node2][node1] += delta_pheromone\n",
|
|
||||||
"\n",
|
|
||||||
" # Séparer la meilleure solution en trajets pour chaque camion\n",
|
|
||||||
" truck_solutions = []\n",
|
|
||||||
" num_nodes_per_truck = num_nodes // num_trucks\n",
|
|
||||||
"\n",
|
|
||||||
" for i in range(num_trucks):\n",
|
|
||||||
" start_index = i * num_nodes_per_truck\n",
|
|
||||||
" end_index = start_index + num_nodes_per_truck\n",
|
|
||||||
" truck_solution = best_solution[start_index:end_index]\n",
|
|
||||||
" truck_solutions.append(truck_solution + [0])\n",
|
|
||||||
" \n",
|
|
||||||
"\n",
|
|
||||||
" return truck_solutions, best_distance\n",
|
|
||||||
"\n",
|
|
||||||
"\n",
|
|
||||||
"\n",
|
|
||||||
"\n",
|
|
||||||
"\n",
|
|
||||||
"num_ants = 10\n",
|
|
||||||
"num_iterations = 100\n",
|
|
||||||
"evaporation_rate = 0.5\n",
|
|
||||||
"alpha = 1\n",
|
|
||||||
"beta = 1\n",
|
|
||||||
"\n",
|
|
||||||
"best_truck_solutions,best_distance = ant_colony_optimization(distance_matrix, num_ants, num_iterations, evaporation_rate, alpha, beta, num_trucks)\n",
|
|
||||||
"\n",
|
|
||||||
"# Pour chaque solution de camion, nous devons trouver le chemin le plus court du dépôt au premier nœud du chemin\n",
|
|
||||||
"for i, truck_solution in enumerate(best_truck_solutions):\n",
|
|
||||||
" # Créer un graphe à partir de la matrice de distance\n",
|
|
||||||
" G = nx.from_numpy_matrix(distance_matrix)\n",
|
|
||||||
" \n",
|
|
||||||
" # Utiliser l'algorithme de Dijkstra pour trouver le chemin le plus court du dépôt (nœud 0) au premier nœud du chemin du camion\n",
|
|
||||||
" shortest_path = nx.dijkstra_path(G, 0, truck_solution[1])\n",
|
|
||||||
" \n",
|
|
||||||
" # Remplacer le premier nœud du chemin du camion par le chemin le plus court trouvé\n",
|
|
||||||
" best_truck_solutions[i] = [0] + shortest_path + truck_solution[2:]\n",
|
|
||||||
"\n",
|
|
||||||
"# Calculer la distance totale pour chaque solution de camion\n",
|
|
||||||
"total_distances = [evaluate_solution(truck_solution, distance_matrix) for truck_solution in best_truck_solutions]\n",
|
|
||||||
"\n",
|
|
||||||
"# Afficher les solutions et les distances totales pour chaque camion\n",
|
|
||||||
"for i, (truck_solution, total_distance) in enumerate(zip(best_truck_solutions, total_distances)):\n",
|
|
||||||
" print(f\"Camion {i+1} :\")\n",
|
|
||||||
" print(\"Solution :\", truck_solution)\n",
|
|
||||||
" print(\"Distance totale :\", total_distance)\n",
|
|
||||||
" print()"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"attachments": {},
|
|
||||||
"cell_type": "markdown",
|
|
||||||
"id": "421c05e1",
|
|
||||||
"metadata": {},
|
|
||||||
"source": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"attachments": {},
|
|
||||||
"cell_type": "markdown",
|
|
||||||
"id": "a6ffa6c9",
|
|
||||||
"metadata": {},
|
|
||||||
"source": [
|
|
||||||
"\n",
|
|
||||||
"def ant_colony_optimization(distances, num_ants, num_iterations, evaporation_rate, alpha, beta, num_trucks):\n",
|
|
||||||
" num_nodes = len(distances)\n",
|
|
||||||
" \n",
|
|
||||||
" pheromone = np.ones((num_nodes, num_nodes)) # Matrice de phéromones initiale\n",
|
|
||||||
" best_solution = None\n",
|
|
||||||
" best_distance = float('inf')\n",
|
|
||||||
"\n",
|
|
||||||
" for iteration in range(num_iterations):\n",
|
|
||||||
" # Construction de solutions par les fourmis\n",
|
|
||||||
" solutions = []\n",
|
|
||||||
"\n",
|
|
||||||
" for ant in range(num_ants):\n",
|
|
||||||
" visited = set()\n",
|
|
||||||
" current_node = 0 # Tous les camions partent du dépôt\n",
|
|
||||||
" visited.add(current_node)\n",
|
|
||||||
" solution = [current_node]\n",
|
|
||||||
"\n",
|
|
||||||
" while len(visited) < num_nodes:\n",
|
|
||||||
" next_node = None\n",
|
|
||||||
" probabilities = []\n",
|
|
||||||
"\n",
|
|
||||||
" # Calcul des probabilités de choisir chaque prochain nœud\n",
|
|
||||||
" for node in range(num_nodes):\n",
|
|
||||||
" if node not in visited:\n",
|
|
||||||
" pheromone_value = pheromone[current_node][node]\n",
|
|
||||||
" distance_value = distances[current_node][node]\n",
|
|
||||||
" probability = (pheromone_value ** alpha) * ((1 / distance_value) ** beta)\n",
|
|
||||||
" probabilities.append((node, probability))\n",
|
|
||||||
"\n",
|
|
||||||
" total_probability = sum(prob for _, prob in probabilities)\n",
|
|
||||||
" probabilities = [(node, prob / total_probability) for node, prob in probabilities]\n",
|
|
||||||
"\n",
|
|
||||||
" roulette_wheel = random.random()\n",
|
|
||||||
" probability_sum = 0\n",
|
|
||||||
"\n",
|
|
||||||
" for node, probability in probabilities:\n",
|
|
||||||
" probability_sum += probability\n",
|
|
||||||
" if probability_sum >= roulette_wheel:\n",
|
|
||||||
" next_node = node\n",
|
|
||||||
" break\n",
|
|
||||||
"\n",
|
|
||||||
" visited.add(next_node)\n",
|
|
||||||
" solution.append(next_node)\n",
|
|
||||||
" current_node = next_node\n",
|
|
||||||
"\n",
|
|
||||||
" # Ajouter le retour au dépôt central à la fin du trajet\n",
|
|
||||||
" solution.append(0)\n",
|
|
||||||
"\n",
|
|
||||||
" solutions.append(solution)\n",
|
|
||||||
"\n",
|
|
||||||
" # Évaluation des solutions et mise à jour de la meilleure solution\n",
|
|
||||||
" for solution in solutions:\n",
|
|
||||||
" distance = evaluate_solution(solution, distances)\n",
|
|
||||||
" if distance < best_distance:\n",
|
|
||||||
" best_solution = solution\n",
|
|
||||||
" best_distance = distance\n",
|
|
||||||
"\n",
|
|
||||||
" # Mise à jour des phéromones\n",
|
|
||||||
" pheromone *= evaporation_rate # Évaporation des phéromones existantes\n",
|
|
||||||
"\n",
|
|
||||||
" for solution in solutions:\n",
|
|
||||||
" delta_pheromone = 1 / evaluate_solution(solution, distances)\n",
|
|
||||||
" for i in range(num_nodes - 1):\n",
|
|
||||||
" node1 = solution[i]\n",
|
|
||||||
" node2 = solution[i + 1]\n",
|
|
||||||
" pheromone[node1][node2] += delta_pheromone\n",
|
|
||||||
" pheromone[node2][node1] += delta_pheromone\n",
|
|
||||||
"\n",
|
|
||||||
" # Séparer la meilleure solution en trajets pour chaque camion\n",
|
|
||||||
" truck_solutions = []\n",
|
|
||||||
" num_nodes_per_truck = num_nodes // num_trucks\n",
|
|
||||||
"\n",
|
|
||||||
" for i in range(num_trucks):\n",
|
|
||||||
" start_index = i * num_nodes_per_truck\n",
|
|
||||||
" end_index = start_index + num_nodes_per_truck\n",
|
|
||||||
" truck_solution = best_solution[start_index:end_index]\n",
|
|
||||||
" truck_solutions.append(truck_solution + [0])\n",
|
|
||||||
" \n",
|
|
||||||
"\n",
|
|
||||||
" return truck_solutions, best_distance\n",
|
|
||||||
"\n",
|
|
||||||
"num_ants = 10\n",
|
|
||||||
"num_iterations = 100\n",
|
|
||||||
"evaporation_rate = 0.5\n",
|
|
||||||
"alpha = 1\n",
|
|
||||||
"beta = 1\n",
|
|
||||||
"\n",
|
|
||||||
"best_truck_solutions,best_distance = ant_colony_optimization(distance_matrix, num_ants, num_iterations, evaporation_rate, alpha, beta, num_trucks)\n",
|
|
||||||
"\n",
|
|
||||||
"# Pour chaque solution de camion, nous devons trouver le chemin le plus court du dépôt au premier nœud du chemin\n",
|
|
||||||
"for i, truck_solution in enumerate(best_truck_solutions):\n",
|
|
||||||
" # Créer un graphe à partir de la matrice de distance\n",
|
|
||||||
" G = nx.from_numpy_matrix(distance_matrix)\n",
|
|
||||||
" \n",
|
|
||||||
" # Utiliser l'algorithme de Dijkstra pour trouver le chemin le plus court du dépôt (nœud 0) au premier nœud du chemin du camion\n",
|
|
||||||
" shortest_path = nx.dijkstra_path(G, 0, truck_solution[1])\n",
|
|
||||||
" \n",
|
|
||||||
" # Remplacer le premier nœud du chemin du camion par le chemin le plus court trouvé\n",
|
|
||||||
" best_truck_solutions[i] = [0] + shortest_path + truck_solution[2:]\n",
|
|
||||||
"\n",
|
|
||||||
"# Calculer la distance totale pour chaque solution de camion\n",
|
|
||||||
"total_distances = [evaluate_solution(truck_solution, distance_matrix) for truck_solution in best_truck_solutions]\n",
|
|
||||||
"\n",
|
|
||||||
"# Afficher les solutions et les distances totales pour chaque camion\n",
|
|
||||||
"for i, (truck_solution, total_distance) in enumerate(zip(best_truck_solutions, total_distances)):\n",
|
|
||||||
" print(f\"Camion {i+1} :\")\n",
|
|
||||||
" print(\"Solution :\", truck_solution)\n",
|
|
||||||
" print(\"Distance totale :\", total_distance)\n",
|
|
||||||
" print()"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"attachments": {},
|
|
||||||
"cell_type": "markdown",
|
|
||||||
"id": "29df0137",
|
|
||||||
"metadata": {},
|
|
||||||
"source": [
|
|
||||||
"# En rajoutant la contrainte de Time Window pour une instance de VRPTW\n",
|
|
||||||
"\n",
|
|
||||||
"Dans un premier temps on va attribuer des fenêtres de temps pour chaque clients (ville dans notre graphe)"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "code",
|
|
||||||
"execution_count": 7,
|
|
||||||
"id": "8266e414-d350-4101-8f15-9cc05ee02934",
|
|
||||||
"metadata": {
|
|
||||||
"scrolled": true
|
|
||||||
},
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "stdout",
|
|
||||||
"output_type": "stream",
|
|
||||||
"text": [
|
|
||||||
"20\n",
|
|
||||||
"Client 0 : (0, inf)\n",
|
|
||||||
"Client 1 : (44, 94)\n",
|
|
||||||
"Client 2 : (99, 111)\n",
|
|
||||||
"Client 3 : (80, 125)\n",
|
|
||||||
"Client 4 : (85, 96)\n",
|
|
||||||
"Client 5 : (71, 85)\n",
|
|
||||||
"Client 6 : (34, 69)\n",
|
|
||||||
"Client 7 : (20, 30)\n",
|
|
||||||
"Client 8 : (46, 56)\n",
|
|
||||||
"Client 9 : (90, 109)\n",
|
|
||||||
"Client 10 : (74, 116)\n",
|
|
||||||
"Client 11 : (95, 112)\n",
|
|
||||||
"Client 12 : (93, 131)\n",
|
|
||||||
"Client 13 : (46, 82)\n",
|
|
||||||
"Client 14 : (86, 124)\n",
|
|
||||||
"Client 15 : (87, 129)\n",
|
|
||||||
"Client 16 : (13, 23)\n",
|
|
||||||
"Client 17 : (0, 28)\n",
|
|
||||||
"Client 18 : (77, 108)\n",
|
|
||||||
"Client 19 : (76, 105)\n",
|
|
||||||
"Client 20 : (78, 94)\n",
|
|
||||||
"[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]\n",
|
|
||||||
"[(0, 19), (0, 16), (0, 5), (0, 10), (1, 18), (1, 8), (1, 11), (2, 18), (2, 6), (2, 3), (2, 9), (2, 10), (2, 14), (2, 17), (3, 7), (3, 8), (3, 16), (4, 15), (4, 5), (4, 13), (5, 8), (5, 7), (6, 16), (6, 19), (7, 15), (7, 19), (8, 13), (9, 20), (10, 15), (11, 14), (11, 18), (12, 15), (12, 17), (12, 16), (13, 19), (13, 17), (13, 20), (14, 20), (14, 15), (15, 18), (15, 20)]\n"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"source": [
|
|
||||||
"\n",
|
|
||||||
"def assign_time_windows(graph):\n",
|
|
||||||
" # Créer un dictionnaire pour stocker les fenêtres de temps des clients\n",
|
|
||||||
" time_windows = {}\n",
|
|
||||||
"\n",
|
|
||||||
" # Définir la fenêtre de temps pour le dépôt central (nœud 0)\n",
|
|
||||||
" time_windows[0] = (0, float('inf'))\n",
|
|
||||||
"\n",
|
|
||||||
" # Assigner une fenêtre de temps à chaque client\n",
|
|
||||||
" for node in graph.nodes():\n",
|
|
||||||
" if node !=0 and node != graph.number_of_nodes() :\n",
|
|
||||||
" # Générer une fenêtre de temps aléatoire pour chaque client\n",
|
|
||||||
" start_time = random.randint(0, 100)\n",
|
|
||||||
" end_time = start_time + random.randint(10, 50)\n",
|
|
||||||
" time_windows[node] = (start_time, end_time)\n",
|
|
||||||
" \n",
|
|
||||||
"\n",
|
|
||||||
" return time_windows\n",
|
|
||||||
"\n",
|
|
||||||
"# Attribuer les fenêtres de temps aux clients\n",
|
|
||||||
"time_windows = assign_time_windows(graph)\n",
|
|
||||||
"\n",
|
|
||||||
"print(max(graph.nodes()))\n",
|
|
||||||
"# Afficher les fenêtres de temps assignées\n",
|
|
||||||
"for node, window in time_windows.items():\n",
|
|
||||||
" print(\"Client\", node, \":\", window)\n",
|
|
||||||
" \n",
|
|
||||||
"#paramètres ACO\n",
|
|
||||||
"\n",
|
|
||||||
"print(graph.nodes())\n",
|
|
||||||
"print(graph.edges())\n"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"attachments": {},
|
|
||||||
"cell_type": "markdown",
|
|
||||||
"id": "747541f5",
|
|
||||||
"metadata": {},
|
|
||||||
"source": [
|
|
||||||
"# On va ensuite réadapter l'algorithme pour prendre en compte les time Windows "
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "code",
|
|
||||||
"execution_count": 15,
|
|
||||||
"id": "901e6b93",
|
|
||||||
"metadata": {},
|
|
||||||
"outputs": [],
|
|
||||||
"source": [
|
|
||||||
"import concurrent.futures\n",
|
|
||||||
"import random\n",
|
|
||||||
"import numpy as np\n",
|
|
||||||
"import time\n",
|
|
||||||
"import heapq\n",
|
|
||||||
"\n",
|
|
||||||
"\n",
|
|
||||||
"# Fonction d'évaluation de la qualité d'une solution (ici, la distance totale)\n",
|
|
||||||
"def evaluate_solution(solution, distances, time_windows, dijkstra_distances):\n",
|
|
||||||
" total_distance = 0\n",
|
|
||||||
" total_delay = 0\n",
|
|
||||||
" arrival_time = 0\n",
|
|
||||||
" num_nodes = len(solution)\n",
|
|
||||||
" waiting_times = []\n",
|
|
||||||
"\n",
|
|
||||||
" total_distance += dijkstra_distances[solution[1]]\n",
|
|
||||||
"\n",
|
|
||||||
" for i in range(num_nodes - 1):\n",
|
|
||||||
" current_node = solution[i]\n",
|
|
||||||
" next_node = solution[i + 1]\n",
|
|
||||||
" total_distance += distances[current_node][next_node]\n",
|
|
||||||
" arrival_time += distances[current_node][next_node]\n",
|
|
||||||
"\n",
|
|
||||||
" if arrival_time < time_windows[next_node][0]:\n",
|
|
||||||
" waiting_time = time_windows[next_node][0] - arrival_time\n",
|
|
||||||
" waiting_times.append((next_node, waiting_time))\n",
|
|
||||||
" arrival_time = time_windows[next_node][0]\n",
|
|
||||||
" elif arrival_time > time_windows[next_node][1]:\n",
|
|
||||||
" total_delay += arrival_time - time_windows[next_node][1]\n",
|
|
||||||
"\n",
|
|
||||||
" # Ajouter la distance de retour au dépôt\n",
|
|
||||||
" total_distance += distances[solution[-1]][solution[0]]\n",
|
|
||||||
"\n",
|
|
||||||
" return total_distance, total_delay, waiting_times\n",
|
|
||||||
"\n",
|
|
||||||
" \n",
|
|
||||||
"# Fonction pour l'algorithme de Dijkstra\n",
|
|
||||||
"def calculate_dijkstra(start_node, distances):\n",
|
|
||||||
" num_nodes = len(distances)\n",
|
|
||||||
" shortest_distances = [float('inf')] * num_nodes\n",
|
|
||||||
" shortest_distances[start_node] = 0\n",
|
|
||||||
" shortest_paths = [[] for _ in range(num_nodes)]\n",
|
|
||||||
" shortest_paths[start_node] = [start_node]\n",
|
|
||||||
" priority_queue = [(0, start_node)]\n",
|
|
||||||
" while priority_queue:\n",
|
|
||||||
" current_distance, current_node = heapq.heappop(priority_queue)\n",
|
|
||||||
" if current_distance == shortest_distances[current_node]:\n",
|
|
||||||
" for neighbor, distance in enumerate(distances[current_node]):\n",
|
|
||||||
" new_distance = current_distance + distance\n",
|
|
||||||
" if new_distance < shortest_distances[neighbor]:\n",
|
|
||||||
" shortest_distances[neighbor] = new_distance\n",
|
|
||||||
" shortest_paths[neighbor] = shortest_paths[current_node] + [neighbor]\n",
|
|
||||||
" heapq.heappush(priority_queue, (new_distance, neighbor))\n",
|
|
||||||
" return shortest_distances, shortest_paths\n",
|
|
||||||
"\n",
|
|
||||||
"\n",
|
|
||||||
"dijkstra_distances, dijkstra_paths = calculate_dijkstra(0, distance_matrix)\n",
|
|
||||||
"\n",
|
|
||||||
"\n",
|
|
||||||
"def ant_colony_optimization(distances, num_ants, num_iterations, evaporation_rate, alpha, beta, num_trucks):\n",
|
|
||||||
" num_nodes = len(distances)\n",
|
|
||||||
" pheromone = np.ones((num_nodes, num_nodes)) \n",
|
|
||||||
" best_solution = None\n",
|
|
||||||
" best_distance = float('inf')\n",
|
|
||||||
" best_delay = float('inf')\n",
|
|
||||||
" best_score = float('inf') \n",
|
|
||||||
" best_waiting_times = None\n",
|
|
||||||
"\n",
|
|
||||||
" for iteration in range(num_iterations):\n",
|
|
||||||
" solutions = []\n",
|
|
||||||
" for ant in range(num_ants):\n",
|
|
||||||
" visited = set()\n",
|
|
||||||
" current_node = random.randint(0, num_nodes - 1)\n",
|
|
||||||
" visited.add(current_node)\n",
|
|
||||||
" solution = [current_node]\n",
|
|
||||||
" while len(visited) < num_nodes:\n",
|
|
||||||
" next_node = None\n",
|
|
||||||
" probabilities = []\n",
|
|
||||||
" arrival_time = 0\n",
|
|
||||||
" for node in range(num_nodes):\n",
|
|
||||||
" if node not in visited and (node !=0 or len(visited) == num_nodes - 1):\n",
|
|
||||||
" pheromone_value = pheromone[current_node][node]\n",
|
|
||||||
" distance_value = distances[current_node][node]\n",
|
|
||||||
" wait_time = max(0, time_windows[node][0]- (arrival_time + distance_value))\n",
|
|
||||||
" probability = (pheromone_value ** alpha) * ((1 / (distance_value + wait_time)) ** beta)\n",
|
|
||||||
" probabilities.append((node, probability))\n",
|
|
||||||
" total_probability = sum(prob for _, prob in probabilities)\n",
|
|
||||||
" probabilities = [(node, prob / total_probability) for node, prob in probabilities]\n",
|
|
||||||
" roulette_wheel = random.random()\n",
|
|
||||||
" probability_sum = 0\n",
|
|
||||||
" for node, probability in probabilities:\n",
|
|
||||||
" probability_sum += probability\n",
|
|
||||||
" if probability_sum >= roulette_wheel:\n",
|
|
||||||
" next_node = node\n",
|
|
||||||
" break\n",
|
|
||||||
" visited.add(next_node)\n",
|
|
||||||
" solution.append(next_node)\n",
|
|
||||||
" current_node = next_node\n",
|
|
||||||
" solution.append(0)\n",
|
|
||||||
" solutions.append(solution)\n",
|
|
||||||
"\n",
|
|
||||||
" for solution in solutions:\n",
|
|
||||||
" distance, delay, waiting_times = evaluate_solution(solution, distances, time_windows, dijkstra_distances)\n",
|
|
||||||
" score = distance + delay\n",
|
|
||||||
" if score < best_score:\n",
|
|
||||||
" best_solution = solution\n",
|
|
||||||
" best_distance = distance\n",
|
|
||||||
" best_delay = delay\n",
|
|
||||||
" best_waiting_times = waiting_times\n",
|
|
||||||
" pheromone *= evaporation_rate\n",
|
|
||||||
" for solution in solutions:\n",
|
|
||||||
" delta_pheromone = 1 / (evaluate_solution(solution, distances, time_windows, dijkstra_distances)[0] + 0.01)\n",
|
|
||||||
" for i in range(num_nodes - 1):\n",
|
|
||||||
" node1 = solution[i]\n",
|
|
||||||
" node2 = solution[i + 1]\n",
|
|
||||||
" pheromone[node1][node2] += delta_pheromone\n",
|
|
||||||
" pheromone[node2][node1] += delta_pheromone\n",
|
|
||||||
" truck_solutions = []\n",
|
|
||||||
" num_nodes_per_truck = num_nodes // num_trucks\n",
|
|
||||||
" for i in range(num_trucks):\n",
|
|
||||||
" start_index = i * num_nodes_per_truck\n",
|
|
||||||
" end_index = start_index + num_nodes_per_truck\n",
|
|
||||||
" truck_solution = best_solution[start_index:end_index]\n",
|
|
||||||
" \n",
|
|
||||||
" # Ajoutez le chemin le plus court entre le nœud 0 et le premier nœud du chemin\n",
|
|
||||||
" dijkstra_path_to_first_node = dijkstra_paths[truck_solution[0]]\n",
|
|
||||||
" truck_solution = dijkstra_path_to_first_node + truck_solution\n",
|
|
||||||
" \n",
|
|
||||||
" # Ajoutez le chemin le plus court entre le dernier nœud du chemin et le dépôt (nœud 0)\n",
|
|
||||||
" dijkstra_path_to_depot = dijkstra_paths[truck_solution[-1]]\n",
|
|
||||||
" truck_solution = truck_solution + dijkstra_path_to_depot\n",
|
|
||||||
"\n",
|
|
||||||
" truck_solutions.append(truck_solution)\n",
|
|
||||||
" return truck_solutions, best_distance, best_waiting_times\n",
|
|
||||||
"\n",
|
|
||||||
"\n",
|
|
||||||
"\n"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "code",
|
|
||||||
"execution_count": 16,
|
|
||||||
"id": "f24a5980",
|
|
||||||
"metadata": {},
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "stdout",
|
|
||||||
"output_type": "stream",
|
|
||||||
"text": [
|
|
||||||
"Meilleures solutions :\n",
|
|
||||||
"Camion 1 : [0, 9, 9, 8, 17, 7, 1, 13, 14, 0, 14]\n",
|
|
||||||
"Camion 2 : [0, 12, 12, 18, 4, 5, 20, 19, 15, 0, 15]\n",
|
|
||||||
"Camion 3 : [0, 10, 10, 3, 2, 16, 6, 11, 0, 0]\n",
|
|
||||||
"Distance totale : 48.0\n"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"source": [
|
|
||||||
"num_thread = 1\n",
|
|
||||||
"num_ants = 10\n",
|
|
||||||
"num_iterations = 100\n",
|
|
||||||
"evaporation_rate = 0.5\n",
|
|
||||||
"alpha = 1\n",
|
|
||||||
"beta = 1\n",
|
|
||||||
"\n",
|
|
||||||
"num_trucks = 3 # Nombre de camions disponibles\n",
|
|
||||||
"\n",
|
|
||||||
"\n",
|
|
||||||
"\n",
|
|
||||||
"with concurrent.futures.ThreadPoolExecutor(max_workers=num_thread) as executor:\n",
|
|
||||||
" futures = [executor.submit(ant_colony_optimization, distance_matrix, num_ants, num_iterations, evaporation_rate, alpha, beta, num_trucks) for _ in range(num_thread)]\n",
|
|
||||||
"\n",
|
|
||||||
" for future in concurrent.futures.as_completed(futures):\n",
|
|
||||||
" best_truck_solutions, best_distance, best_waiting_times = future.result()\n",
|
|
||||||
" print(\"Meilleures solutions :\")\n",
|
|
||||||
" for i, truck_solution in enumerate(best_truck_solutions):\n",
|
|
||||||
" print(f\"Camion {i+1} : {truck_solution}\")\n",
|
|
||||||
" print(\"Distance totale :\", best_distance)"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user