/// <summary> /// Retourne une solution par la méthode des plus prches voisins /// </summary> /// <param name="parser">DataParser à utiliser</param> /// <param name="loadConstraint">Contrainte de chargement</param> /// <returns>Solution générée</returns> public static CVRPSolution PPVSolution(DataParser parser, double loadConstraint) { CVRPSolution sol = _AddVars(parser); //Génère une instance de la solution sol.addNewRoute(parser); //Créé une nouvelle route sol.setVariable(0, parser, loadConstraint); //Fixe le dépot dans la route double[,] arcWeight = (double[, ])parser.arcWeight.Clone(); //Créé une copie de la matrice des distance //On boucle tant que tout les clients ne sont pas servis while (sol.freeVarCount != 0) { int nearestId = 0; //On initialise le plus proche voisin double distance = arcWeight[sol.varsIdList[sol.varsIdList.Count - 1], 0]; //On initialise sa distance au dernier point visité //On parcours tout les voisins potentiels for (int j = 1; j < parser.nodeList.Count; j++) { //Si l'arc vers j est réalisable et meilleur que les précédents considérés if (arcWeight[sol.varsIdList[sol.varsIdList.Count - 1], j] != 0 && (distance == 0 || arcWeight[sol.varsIdList[sol.varsIdList.Count - 1], j] < distance)) { //On met à jour le plus prche voisin nearestId = j; distance = arcWeight[sol.varsIdList[sol.varsIdList.Count - 1], j]; } } //Si on revient au dépot, on créé une nouvelle solution if (nearestId == 0) { sol.endRoute(); } else { sol.setVariable(nearestId, parser, loadConstraint); //On fixe le plus proche voisin } //On empêche le plus proche voisin d'être de nouveau disponible for (int j = 0; j < parser.nodeList.Count; j++) { arcWeight[j, nearestId] = 0; } } sol.endSolution(); //On termine la solution return(sol); }
/// <summary> /// Fonction récursive de résolution /// </summary> /// <param name="currentNode">Noeud courant de l'arbre</param> /// <param name="step">Profondeur du parcours</param> /// <returns>Noeud courant</returns> private TreeNode solve(TreeNode currentNode, int step) { //Si la solution est une solution finale if (currentNode.sol.isFinalSolution()) { //On al déclare comme finale ((CVRPSolution)currentNode.sol).endSolution(); currentNode.sol.eval = getFixedCost((CVRPSolution)currentNode.sol); //Si cette solution est meilleure if (majValue > currentNode.sol.eval) { //On met à jour la meilleure solution et on l'affiche majValue = currentNode.sol.eval; bestSol = (CVRPSolution)currentNode.sol; logger.log("Meilleur solution trouvée de coût:" + ((int)Math.Round(currentNode.sol.eval)).ToString(), Message.Level.Warning); computedSteps++; displaySolution(bestSol); } else { currentNode.isLocked = true; //On bloque la solution computedSteps++; } updateBenchmark(step); return(currentNode); } else { List <TreeNode> nextSol = new List <TreeNode>(); //On initialise la liste des enfants for (int i = 0; i < _pb.varCount; i++) { //Pour chaque variable en encors libre if (!currentNode.sol.isFixed(i)) { CVRPSolution nSol1 = (CVRPSolution)currentNode.sol.copy(); //On copie la solution nSol1.setVariable(i, data, loadConstraint); //On fixe une nouvelle variable nSol1.eval = evaluateSolution(nSol1, step); //On détermine la borne inférieure //Si la solution est viable //> ou < selon minimisation ou maximisation if (nSol1.eval <= majValue) { nextSol.Add(new TreeNode(nSol1, null)); //On l'ajoute aux enfants } else { computedSteps++; } //Si on peut obtenir une autre solution en créant une nouvelle route if (nSol1.routes.Count == ((CVRPSolution)currentNode.sol).routes.Count) { CVRPSolution nSol2 = (CVRPSolution)currentNode.sol.copy(); nSol2.endRoute(); nSol2.setVariable(i, data, loadConstraint); nSol2.eval = evaluateSolution(nSol2, step); //> ou < selon minimisation ou maximisation if (nSol2.eval <= majValue) { nextSol.Add(new TreeNode(nSol2, null)); } else { computedSteps++; } } } } //Si il y a des enfants if (nextSol.Count != 0) { nextSol.Sort((x, y) => x.sol.eval.CompareTo(y.sol.eval)); //On les trie selon leur borne inférieure //On parcours les enfants for (int i = 0; i < nextSol.Count; i++) { //Si la solution est toujours viable if (nextSol[i].sol.eval <= majValue) { nextSol[i] = solve(nextSol[i], step + 1); //On poursuit la résolution } else { nextSol[i].isLocked = true; computedSteps++; } } currentNode.childs = nextSol; } else { currentNode.isLocked = true; updateBenchmark(step); } computedSteps++; int locked = 0; //On regarde si tout les enfants sont bloquéss foreach (TreeNode node in nextSol) { if (node.isLocked) { node.Dispose(); locked++; } } //Si ils le sont tous, on bloque la solution if (locked == nextSol.Count) { currentNode.isLocked = true; nextSol = null; } return(currentNode); } }