diff --git a/Projet_algo.ipynb b/Projet_algo.ipynb
index ad60941..b544ce5 100644
--- a/Projet_algo.ipynb
+++ b/Projet_algo.ipynb
@@ -264,7 +264,7 @@
"id": "7670fdf4-884c-4352-83fa-eed0c8b50074",
"metadata": {},
"source": [
- "## Resolution algorithm "
+ "## Resolution algorithm (with coordinates)"
]
},
{
@@ -287,809 +287,7 @@
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"import random, time, math\n",
- "from tests.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)"
+ "from tests.libs.clustering import split_tour_across_clusters"
]
}
],