package graphe; import java.io.*; import java.lang.*; import java.util.*; import javax.swing.*; /** * Classe ColorationJeton. * Cette classe permet de gérer une coloraiton du graphe de proche en proche, * par circulation de jeton. * @author Estelle Colin, Thomas Peclier, Fabrice Berna @ IUP GMI * @see Graphe.class, Application, Sommet, ElectionJeton * @version 1.0 */ public class ColorationJeton extends ElectionJeton { /*----------------------------- Variables -----------------------------*/ /** *Nombre de couleurs de la coloration */ private int nbCouleurs = -1; /** * numéro de la couleur que j'ai choisie, -1 sinon */ private int maCouleur = -1; /** * Tableau de taille le nombre de couleurs (nbCouleurs). * Permet de connaître les couleurs occupées par mes voisins déjà coloriés * ainsi que les couleurs que j'ai déjà tentées d'utiliser, sans succès */ private boolean couleursLibres[]; /** * Tableau de taille le nombre de voisins (nbvoisins), * permet d'associer chacun de mes voisins déjà colorié à sa couleur */ private int couleursVoisins[]; /** * Tableau de taille le nombre de voisins (nbvoisins), * permet de savoir lesquels de mes fils sont coloriés, * de manière à ne relancer la coloration que sur ces sommets et non * sur mes voisins qui étaient colorés précédemment. * * Dans ce tableaux on ne voit que les voisins qui dépendent de moi pour la coloration. */ private boolean mesFilsColores[]; /** * Identifiant de mon pere (celui qui m'a demandé de choisir une couleur) */ private int pere = id; /*----------------------------- Accesseurs -----------------------------*/ /** * Accesseurs en lecture * @return int */ public final int getCouleur() { return maCouleur; } /** * Setter nbCouleurs */ public void setNbCouleurs(int k) { initialiserCouleurs(k); } /*----------------------------- Méthodes -----------------------------*/ /** * Constructeur, * Initialise couleursVoisins et mesFilsColores * @param int, mon identifiant * @param int, le nombre de sommets dans le graphe * @param boolean[], la liste de mes voisins et de mes non voisins */ public ColorationJeton(int i, int nb, boolean[] v, JTextArea out) { super(i, nb, v, out); couleursVoisins = new int[nbvoisins]; mesFilsColores = new boolean[nbvoisins]; for (int j = 0; j < nbvoisins; j++) { couleursVoisins[j] = -1; mesFilsColores[j] = false; } } /** * Méthode de déclenchement de la coloration, appelée par le chef élu * * Ce sommet va choisir une couleur, * la communiquer à ses voisins, * demander à un de ses voisins de se colorer * @throws IOException */ public final void initierColoration() throws IOException { if (nbvoisins == 0) { maCouleur = 0; etat = "colore"; println("##### " + id + " : Je suis élu (pas de voisin) #####"); cancel(); } else if (chef == id) { initialiserCouleurs(nbCouleurs); maCouleur = choisirCouleur(); try { sleep(1000); } catch (Exception e) { } diffuser("Couleur", maCouleur, nbCouleurs); lancerColorationAFils(); } } /** * Méthode de choix d'une couleur: * @return int,la couleur libre de plus petit indice, -1 s'il n'y en a plus */ private final int choisirCouleur() { int i = 0; while ((i < nbCouleurs) && (!couleursLibres[i])) { i++; } if (i == nbCouleurs) { return -1; } else { couleursLibres[i] = false; return i; } } /** * Diffuse le message couleur, la couleur c et le nombre de couleur * à mes voisins N'AYANT PAS ENCORE DE COULEUR * @param String, le message à diffuser * @param int, la couleur à diffuser * @param int, nombre de couleurs de la k-coloration * @throws IOException */ private final void diffuser(String s, int c, int nb) throws IOException { for (int i = 0; i < nbvoisins; i++) { if (couleursVoisins[i] == -1) { ecrit(i, s + " " + c + " " + nb); } } } /** * Méthode de réinitialisation des couleurs * Appelée lorsqu'un voisin se colore et nous communique sa couleur * pour la première fois. * @param int, le nombre de couleur de la k-coloration */ private final void initialiserCouleurs(int k) { nbCouleurs = k; couleursLibres = new boolean[nbCouleurs]; for (int i = 0; i < nbCouleurs; i++) couleursLibres[i] = true; } /** * Méthode d'actualisation des couleurs, * Appelée lorsqu'un voisin nous envoie une deuxième fois sa couleur * * On réinitialise couleursLibres en repassant tout à vrai * sauf les couleurs choisies par nos voisins non-fils (Autrement dit, * les sommets coloriés avant moi dans le temps) * @param int, le nombre de couleur de la k-coloration */ private final void actualiserCouleurs(int k) { for (int i = 0; i < nbCouleurs; i++) couleursLibres[i] = true; for (int i = 0; i < nbvoisins; i++) { mesFilsColores[i] = false; if (couleursVoisins[i] != -1) couleursLibres[couleursVoisins[i]] = false; } } /** * Permet de demander à un fils de lancer la coloration sur son * sous-arbre * @return boolean, si la demande a réussi * @throws IOException */ private final boolean lancerColorationAFils() throws IOException { int prochain = extraireVoisin(); if (prochain == -1) return false; else { ecrit(prochain, "Coloration"); return true; } } /** * Retourne un voisin qui n'a pas encore de couleur * @return int, le voisin, ou -1 si on a plus de voisins */ private final int extraireVoisin() { int i = 0; while ((i < nbvoisins) && (couleursVoisins[i] != -1)) { i++; } if (i == nbvoisins) return -1; else return i; } /** * Appelée à la reception de la couleur c d'un voisin j. * A la première reception de ce message on appelle initialiserCouleurs. * Si j nous a déjà envoyé une couleur, on appelle actualiserCouleurs * Sinon on enregistre la couleur de j et on marque la couleur c comme indisponible. * @param int, la couleur reçue * @param int, le nombre de couleurs de la k-coloration * @param int, le canal de réception du message */ private final void sur_Reception_Couleur(int c, int n, int j) { //Si j nous a déjà envoyé une couleur if (couleursVoisins[j] != -1) { couleursVoisins[j] = c; actualiserCouleurs(n); } else { couleursVoisins[j] = c; couleursLibres[c] = false; } } /** * Appelée à la reception d'un message demandant de se colorer * -> A la première réception de ce message, on enregistre l'id de * son père * -> Lorsque l'on est voisin avec un de nos aïeuls, il va nous envoyer * ce message. Dans ce cas c'est que la remontée de notre sous arbre * aura réussie jusqu'à cet aïeul, celui-ci lançant la coloration sur * un nouveau voisin. On peut donc lui renvoyer une confirmation de * notre couleur * -> Si ce message ne vient pas d'un aïeul, * On choisit une couleur, s'il n'y en a plus aucune, on envoie Erreur à * son père. * On la communique à un de ses voisins, si on a plus de voisin on envoie * Ok à son père. * On demande à un de ses fils de se lancer * @param int, le numéro du voisin * @throws IOException */ private final void sur_Reception_Coloration(int j) throws IOException { if (pere == id) pere = voisinsId[j]; if (pere != voisinsId[j]) { etat = "colore"; ecrit(j, "Ok " + maCouleur); } else { maCouleur = choisirCouleur(); if (maCouleur != -1) { //Pour voir la coloration try { sleep(1000); } catch (Exception e) { } diffuser("Couleur ", maCouleur, nbCouleurs); if (!lancerColorationAFils()) { etat = "colore"; ecrit(voisins[pere], "Ok " + maCouleur); } } else { etat = "pasColore"; ecrit(voisins[pere], "Erreur "); } } } /** * Appelée à la reception de Ok * * On enregistre la couleur de son fils * On enregistre que ce fils a réussi à se colorer dans mesFilsColores * On demande à un autre fils de se colorer par appel de lancerColorationAFils * Si on a plus de fils * on envoie Ok à son père * si je suis mon propre père (c'est que je suis l'initiateur de la coloration): * la coloration a réussie * @param int, la couleur réussie * @param int, le numéro du voisin * @throws IOException */ private final void sur_Reception_Ok(int c, int j) throws IOException { couleursVoisins[j] = c; mesFilsColores[j] = true; if (!lancerColorationAFils()) { etat = "colore"; if (pere != id) { ecrit(voisins[pere], "Ok " + maCouleur); } else { println("Coloration en " + nbCouleurs + "-couleurs Réussie"); } } } /** * Appelée à réception d'un message d'erreur d'un de ses fils * * J'annule les couleurs de mes fils déjà colorés * Je choisis une couleur * si j'ai trouvé une couleur * je diffuse cette couleur à mes fils * je demande à de mes fils de se colorer par lancerColorationAFils * sinon c'est que je n'ai plus de couleur disponible * j'envoie erreur à mon père * si je suis mon propre père (c'est que je suis l'initiateur de la coloration): * la coloration a échoué * @param int, le numéro du voisin * @throws IOException */ private final void sur_Reception_Erreur(int j) throws IOException { if (pere == id){ println("Coloration en " + nbCouleurs + "-couleurs Ratée"); return; } for (int i = 0; i < nbvoisins; i++) { if (mesFilsColores[i]) couleursVoisins[i] = -1; } maCouleur = choisirCouleur(); if (maCouleur != -1) { diffuser("Couleur ", maCouleur, nbCouleurs); lancerColorationAFils(); } else ecrit(voisins[pere], "Erreur "); } /** * Méthode d'interprétation des messages reçus * @param String, le message à interpréter * @param int, le numéro du voisin * @throws IOException */ public final void interprete(String s, int i) throws IOException { strToken = new StringTokenizer(s); message = strToken.nextToken(); if (message.equals("Election")) { initiateurId = Integer.parseInt(strToken.nextToken()); sur_reception_req(i, message, initiateurId); } else if (message.equals("Conf")) { initiateurId = Integer.parseInt(strToken.nextToken()); sur_reception_conf(i, message, initiateurId); } else if (message.equals("Couleur")) { int couleur = Integer.parseInt(strToken.nextToken()); int nbcoul = Integer.parseInt(strToken.nextToken()); sur_Reception_Couleur(couleur, nbcoul, i); } else if (message.equals("Erreur")) sur_Reception_Erreur(i); else if (message.equals("Ok")) { int couleur = Integer.parseInt(strToken.nextToken()); sur_Reception_Ok(couleur, i); } else if (message.equals("Coloration")) sur_Reception_Coloration(i); else sur_reception_de(i, message, initiateurId); } /** * affichage de l'état du sommet */ public final void etat() { println( id + " | " + nbvoisins + " voisins | etat " + etat + " | chef " + chef + " | couleur " + maCouleur); } }