/** Algorithme qui ajoute aléatoirement les villes dans le cycle */ public void algoAleatoire() { Ville v_enCours = _depart; Ville v_suivante; int pos; while (!_villesRestantes.isEmpty()) { // On récupère une ville pos = _rand.nextInt(_villesRestantes.size()); v_suivante = _villesRestantes.get(pos); // Ajout de la ville au cycle // _arretes.add(new Pair(v_enCours, v_suivante)); _arretes.put(v_enCours, v_suivante); // On ajoute la distance _distance += v_enCours.distance(v_suivante); // On supprime la ville _villesRestantes.remove(v_suivante); v_enCours = v_suivante; v_suivante = null; } // _arretes.add(new Pair(v_enCours, _depart)); _arretes.put(v_enCours, _depart); _distance += v_enCours.distance(_depart); }
@Test public void ville_creation() { Ville v1 = Ville.find("byNom", "Chassieu").first(); if (v1 == null) v1 = new Ville("Chassieu", "69680").save(); Ville v2 = Ville.find("byNom", "Lyon").first(); if (v2 == null) v2 = new Ville("Lyon", "69006").save(); }
@Test public void ville_assert_creation() { Ville v1 = Ville.find("byCodePostal", "69680").first(); Ville v2 = Ville.find("byCodePostal", "69006").first(); assertEquals(v1.nom, "Chassieu"); assertEquals(v1.codePostal, "69680"); assertEquals(v2.nom, "Lyon"); assertEquals(v2.codePostal, "69006"); }
/** * Calcul la distance totale a partir des arretes. * * @return distance totale du chemin */ public double calculDistanceTotal() { double d = 0; for (Entry<Ville, Ville> entry : _arretes.entrySet()) { Ville key = entry.getKey(); Ville value = entry.getValue(); d += key.distance(value); } return d; }
/** Solution voisine obtenue via un algo proche du 2-opt (1ère version) */ public ArrayList<Ville> solutionVoisine2Opt(ArrayList<Ville> list) { ArrayList<Ville> res; int i, iplus1, j, jplus1, taille = list.size(); do { i = _rand.nextInt(_nbVilles); } while (i > taille - 4); iplus1 = i + 1; Ville xi = list.get(i), xiplus1 = list.get(iplus1); for (j = i + 2; j < (taille - 1); ++j) { jplus1 = j + 1; Ville xj = list.get(j), xjplus1 = list.get(jplus1); if (xjplus1 != xi) { if (xi.distance(xiplus1) + xj.distance(xjplus1) > xi.distance(xj) + xiplus1.distance(xjplus1)) { // Remplacer les arêtes (xi, xi+1) et (xj, xj+1) par (xi, // xj) et (xi+1, xj+1) dans H res = reverse(list, iplus1, j); // Calcule la nouvelle distance if (calculDistanceTotal(res) < calculDistanceTotal(list)) return res; } } } return reverse(list, iplus1, j - 1); }
/** Fonction d'initialisation du cycle. */ public final void init(boolean nonRandom) { _villesRestantes.addAll(_villes); // On vide le cycle possiblement existant. _arretes.clear(); _distance = 0; // Choix de la ville de depart aléatoirement ou non en fonction du boolean en paramètre if (nonRandom) { // Si le sommet n'a pas été setté. if (Tsp_ps.getSommetAleatoire() == -1) { int pos = _rand.nextInt(_nbVilles); _depart = _villes.get(pos); Tsp_ps.setSommetAleatoire(_depart.getNumber() - 1); } else { // On vérifie que le sommet est bien dans les bornes. Si ce n'est pas le cas, tant pis nous // settons un nouveau sommet. if (Tsp_ps.getSommetAleatoire() < _villes.size()) _depart = _villes.get(Tsp_ps.getSommetAleatoire()); else { int pos = _rand.nextInt(_nbVilles); _depart = _villes.get(pos); Tsp_ps.setSommetAleatoire(_depart.getNumber() - 1); } } } else { int pos = _rand.nextInt(_nbVilles); _depart = _villesRestantes.get(pos); } // On signale la ville choisie. System.out.println("Ville de départ : " + _depart.getNumber() + " / " + _nbVilles); // Retrait de la ville de départ des villes restantes _villesRestantes.remove(_depart); }
/** Algorithme du plus proche voisin */ public void plusProcheVoisin() { Ville v_enCours = _depart; Ville v_best = null; double d, d2; while (!_villesRestantes.isEmpty()) { d = Double.MAX_VALUE; for (Ville v_test : _villesRestantes) { d2 = v_enCours.distanceCarre(v_test); if (d2 < d) { d = d2; v_best = v_test; } } _distance += Math.sqrt(d); _arretes.put(v_enCours, v_best); _villesRestantes.remove(v_best); v_enCours = v_best; } _arretes.put(v_enCours, _depart); _distance += v_enCours.distance(_depart); }
/** * Algortihme de la Plus Proche Insertion. A ete abandonne car beaucoup plus long et moins * performant que le plus proche voisin. */ public void plusProcheInsertion() { Ville v_prime, v, w1, w2; ArrayList<Ville> _villesVisitees = new ArrayList<Ville>(); double d, d_tmp; // On ajoute la ville la plus proche pour avoir un cycle. v = null; d = Double.MAX_VALUE; for (Ville vtest : _villesRestantes) { d_tmp = vtest.distanceCarre(_depart); if (d_tmp < d) { v = vtest; d = d_tmp; } } _arretes.put(_depart, v); _arretes.put(v, _depart); // On enleve la ville des restantes et on l'ajoute aux visitees _villesVisitees.add(_depart); _villesVisitees.add(v); _villesRestantes.remove(v); while (!_villesRestantes.isEmpty()) { v_prime = _villesRestantes.get(0); v = null; w1 = null; w2 = null; d = Double.MAX_VALUE; // On trouve la ville la plus proche for (Ville v_visitee : _villesVisitees) { d_tmp = v_prime.distanceCarre(v_visitee); if (d_tmp < d) { v = v_visitee; d = d_tmp; } } // Maintenant on trouve qu'elle est la ville voisine qui // se liera à v_prime // Il ne peut y avoir que 2 possibilités. for (Entry<Ville, Ville> entry : _arretes.entrySet()) { Ville key = entry.getKey(); Ville value = entry.getValue(); if (value.equals(v)) { w1 = key; break; } } w2 = _arretes.get(v); // Les anciennes arretes sont automatiquement // remplacees. // Si c'est w1 la plus proche if (v.distance(v_prime) + v_prime.distance(w1) - v.distance(w1) < v.distance(v_prime) + v_prime.distance(w2) - v.distance(w2)) { _arretes.put(w1, v_prime); _arretes.put(v_prime, v); } // Si cest w2 else { _arretes.put(v, v_prime); _arretes.put(v_prime, w2); } // On enleve la ville des restantes et on l'ajoute aux // visitees _villesVisitees.add(v_prime); _villesRestantes.remove(v_prime); } }
/** * Algorithme du plus proche voisin amélioré par du multi-thread. Le nombre de thread dépend du * nombre de processeur présent sur la machine. * * @throws InterruptedException */ public void plusProcheVoisinThreading() throws InterruptedException { Ville v_enCours = _depart; Ville v_best = null; double d, d_tmp, d_tmp2; int i, fourchette_val; Thread_ParcoursArrayVille p1, p2; if (Runtime.getRuntime().availableProcessors() > 1) { i = 0; while (!_villesRestantes.isEmpty()) { i++; d = Double.MAX_VALUE; fourchette_val = _villesRestantes.size() / 2; // Pour moins de min_thread points on ne // fait plus de multithread. if (fourchette_val < min_thread) { for (Ville v_test : _villesRestantes) { d_tmp = v_enCours.distanceCarre(v_test); if (d_tmp < d) { v_best = v_test; d = d_tmp; } } } else { // On lance tous les threads sur // une plage de valeur // distincte. p1 = new Thread_ParcoursArrayVille(v_enCours, _villesRestantes, 0, fourchette_val - 1); p2 = new Thread_ParcoursArrayVille( v_enCours, _villesRestantes, fourchette_val, 2 * fourchette_val - 1); p1.start(); p2.start(); p1.join(); p2.join(); d_tmp = p1.getDistance(); d_tmp2 = p2.getDistance(); if (d_tmp < d_tmp2) { d = d_tmp; v_best = _villesRestantes.get(p1.getIndice_resultat()); } else { d = d_tmp2; v_best = _villesRestantes.get(p2.getIndice_resultat()); } } d = Math.sqrt(d); _distance += d; _arretes.put(v_enCours, v_best); _villesRestantes.remove(v_best); v_enCours = v_best; v_best = null; } _arretes.put(v_enCours, _depart); _distance += v_enCours.distance(_depart); } else { // On appelle l'algorithme simple s'il n'y a // qu'un seul processeur. plusProcheVoisin(); } }