Le Coin Wiki
d'Olivier Dalle
$WikiTagline
 

Cours de simulation: Correction exercice 4

Vous trouverez ci-apres: le code source des 3 composants atomiques, le code source du composant coupl BufProc=Buffer+Processor, et le code source du composant couple GenBufProc = Gen+BufProc.

Composant atomique Generateur (odGen)

package odalle;

/*
 * La liste des imports. Dans eclipse c'est tres simple, on peut les ajouter
 * automatiquement en case de besoin: quand une erreur est signalee qui
 * correspond a un type non declare (par exemple message ou content), alors
 * cliquer sur le type qui provoque l'erreur avec le bouton droit, puis
 * aller dans le sous-menu Source, et cliquer sur "Add import".
 */

import GenCol.entity;
import genDevs.modeling.content;
import genDevs.modeling.message;
import simView.ViewableAtomic;

public class odGen extends ViewableAtomic {

        /*
         * La periode, un parametre du modele.
         */

        protected double period_;

        /**
         * Le constructeur du composant DEVS permet de preciser le nom
         * du composant (utile pour les distinguer si on veut en utiliser
         * plusieurs en meme temps) et les parametres par defaut (ici la periode).
         * @param name Le nom du composant
         * @param period Le periode du generateur
         */

        public odGen(String name,double period) {
                super(name);
                this.period_ = period;
                this.name = name;
                addOutport("out");
        }


        public odGen() {
                super("Generator");
                period_ = 5.0;
                /* Ce qui suit permet de materialiser le port dans la vue graphique */
                addOutport("out");
        }

        /**
         * La methode initialize calcule l'etat initial du composant DEVS.
         * L'etat initial est forme de la phase (ici toujours "active"),
         * de sigma, le temps qu'il reste a attendre dans l'etat courant
         * (on l'initialise donc a la valeur de la periode), et puis on appelle
         * la methode initialize de la classe parente pour enregistrer cette
         * modification.
         */

        public void initialize() {
                sigma = period_;
                phase = "active";
                super.initialize();
        }

        /**
         * La methode "delta_int" dans la notation mathematique.
         * En cas de transition interne, on retourne dans l'etat defini
         * par la phase "active". Pour cela on utilise la fonction
         * "holdIn" qui permet d'indiquer la phase et al nouvelle valeur
         * de sigma.
         */

        public void deltint() {
                holdIn("active",period_);
        }

        /**
         * La methode "delta_ext" dans la notation mathematique.
         * Inutile de preciser l'etat courant car il est connu dans l'objet
         * (la combinaison des variables interne, de la variable predefinie
         * "phase", et la variable predefinie "sigma")
         * Dans le cas present cette fonction n'a rien a faire car ce composant
         * ne recoit jamais d'entree!
         */

        public void deltext(double e, message x) {
                /**
                 * En general, on consomme le temps ecoule dans l'etat courant.
                 */

                Continue(e);
        }

        /**
         * Fonction qui calcule la sortie produite par le composant
         * (la fonction "lambda" dans le notation mathematique)
         * Nous utilisons ici la version la plus complete, qui
         * est capable de produire des sorties simultanement sur
         * plusieurs ports. Une sortie multiple est donc la
         * composition de plusieurs sorties simples. Une sortie simple
         * designe un port et une valeur et est de type "content".
         * La valeur d'une sortie simple est un objet de type "entity".
         */

        public message out( )
        {
                /* Construire la valeur de sortie. */
                entity   e = new entity("job");
                /* Construire la sortie simple */
                content  c = makeContent("out",e);
                /* Construire un message vide */
                message  m = new message();
                /* Remplir le message avec une premiere (unique) sortie */
                m.add(c);
                return m;
        }
}

Composant atomique Buffer (odBuffer)

package odalle;

import GenCol.entity;
import genDevs.modeling.content;
import genDevs.modeling.message;
import simView.ViewableAtomic;

public class odBuffer extends ViewableAtomic {
        protected int nbJobs_ = 0;

        /**
         * Le constructeur par dfaut est utilis quand le composant est
         * cr automatiquement sans paramtre, par exemple quand
         * on essaie d'excuter le composant tout seul.
         */

        public odBuffer(){
                /* Un nom par defaut */
                super("Buffer");
                /* Ce qui suit permet de materialiser les ports dans la vue graphique */
                addInport("in");
                addInport("done");
                addOutport("out");
                /* on peut inserer des evenements pour tester le DEVS
                 * Les valeurs inserees (ici "nouveau" et "termine" sont
                 * sans importance car la seule chose qui nous interesse c'est
                 * de savoir si un evenement est present sur le port, peut importe
                 * la veleur associee a cet evenenement.
                 * */

                addTestInput("in",new entity("nouveau"));
                addTestInput("done",new entity("termine"));
                /* on peut aussi ajouter un evenement futur, ici dans 5 unite de tps. */
                addTestInput("in", new entity("nouveau2"),5.0);
        }



        /**
         * Le constructeur du composant DEVS permet de preciser le nom
         * du composant (utile pour les distinguer si on veut en utiliser
         * plusieurs en meme temps) et les parametres par defaut (ici la periode).
         * @param name Le nom du composant
         */

        public odBuffer(String name){
                super(name);
                addInport("in");
                addInport("done");
                addOutport("out");
        }

        /**
         * La methode initialize calcule l'etat initial du composant DEVS.
         * L'etat initial est forme de la phase (ici "passive") et de sigma,
         * le temps qu'il reste a attendre dans l'etat courant (on
         * l'initialise donc a la valeur de la periode), et puis on appelle
         * la methode initialize de la classe parente pour enregistrer cette
         * modification.
         * Plus tard, on pourra changer ces valeurs soit directement,
         * soit l'aide de fonctions prdfinies:
         * - passivate() : passe la phase dans l'tat "passive" avec une
         * valeur de sigma = INFINITY
         * - holdIn(etat,duree) : passe dans la phase etat (un chaine) pour
         * une certaine duree
         */

        public void initialize(){
                phase = "passive";
                sigma = INFINITY;
                super.initialize();
        }

        /**
         * La methode "delta_ext" dans la notation mathematique.
         * Inutile de preciser l'etat courant car il est connu dans l'objet
         * (la combinaison des variables interne, de la variable predefinie
         * "phase", et la variable predefinie "sigma")
         * Dans le cas present cette fonction doit considrer les deux
         * types d'entres possibles en meme temps, sur le port "in" et
         * le port "done".
         */

        public void deltext(double e,message x) {
                Continue(e);

                /* Un message peut etre multiple, cad contenir plusieur messages
                 * simples. Donc pour parcourir les messages il faut faire une
                 * boucle. Ensuite, a chaque tour de boucle, on test sur quel
                 * port se trouve le message (ici soit le port "in" doit le port
                 * "done").
                 */

                for (int i=0; i< x.getLength();i++) {
                        if (messageOnPort(x,"in",i)) {
                                if (nbJobs_ == 0){
                                        holdIn("active",0);
                                }
                                nbJobs_ ++;
                        }

                        if (messageOnPort(x,"done",i)) {
                                if (nbJobs_ > 1) {
                                        holdIn("active",0);
                                }
                                nbJobs_--;     
                        }
                }

        }

        /**
         * La methode "delta_int" de la notation mathematique.
         * Ici, on passe dans l'etat passif pour une duree inifinie.
         */

        public void deltint() {
                passivate();
        }

        /**
         * La mthode lambda de la notation mathmatique (calcule la sortie
         * du DEVS).
         */

        public message out( )
        {
                /* Construire la valeur de sortie. */
                entity   e = new entity("job");
                /* Construire la sortie simple */
                content  c = makeContent("out",e);
                /* Construire un message vide */
                message  m = new message();
                /* Remplir le message avec une premiere (unique) sortie */
                m.add(c);
                return m;
        }

        /**
         * Cette methode permet d'ajouter des informations dans
         * la bulle qui s'affiche quand on passe la souris au dessus du composant
         * dans la fenetre graphique.
         */

        public String getTooltipText(){
                return super.getTooltipText()
                    +"\n"+"nbJobs: " + nbJobs_;
        }
}

Composant atomique Processeur (odProc)

package odalle;

import genDevs.modeling.content;
import genDevs.modeling.message;
import GenCol.entity;
import simView.ViewableAtomic;

public class odProc extends ViewableAtomic {

        /*
         * La periode, un parametre du modele.
         */

        protected double period_;

        /**
         * Le constructeur du composant DEVS permet de preciser le nom
         * du composant (utile pour les distinguer si on veut en utiliser
         * plusieurs en meme temps) et les parametres par defaut (ici la periode).
         * @param name Le nom du composant
         * @param period Le periode du generateur
         */

        public odProc(String name,double period) {
                super(name);
                this.period_ = period;
                this.name = name;
                addInport("in");
                addOutport("out");
        }


        public odProc() {
                super("Proc");
                period_ = 2.0;
                /* Ce qui suit permet de materialiser le port dans la vue graphique */
                addInport("in");
                addOutport("out");
                /* on peut inserer des evenements pour tester le DEVS
                 * Les valeurs inserees (ici "nouveau" et "termine" sont
                 * sans importance car la seule chose qui nous interesse c'est
                 * de savoir si un evenement est present sur le port, peut importe
                 * la veleur associee a cet evenenement.
                 * */

                addTestInput("in",new entity("job0"));
                /* on peut aussi ajouter un evenement futur, ici dans 1 unite de tps. */
                addTestInput("in", new entity("job1"),1.0);
        }

        /**
         * La methode initialize calcule l'etat initial du composant DEVS.
         * L'etat initial est forme de la phase (ici "B" ou "F"),
         * de sigma, le temps qu'il reste a attendre dans l'etat courant
         * (on l'initialise donc a la valeur de la periode), et puis on appelle
         * la methode initialize de la classe parente pour enregistrer cette
         * modification.
         */

        public void initialize() {
                sigma = INFINITY;
                phase = "F";
                super.initialize();
        }

        /**
         * La methode "delta_int" dans la notation mathematique.
         * En cas de transition interne, on retourne dans l'etat defini
         * par la phase "active". Pour cela on utilise la fonction
         * "holdIn" qui permet d'indiquer la phase et al nouvelle valeur
         * de sigma.
         */

        public void deltint() {
                passivateIn("F");
        }

        /**
         * La methode deltcon definit comment traiter les cas ambigus lorsqu'une
         * transition interne et externe se produisent en meme temps.
         * Ici on choisit d'executer d'abord la transition interne (fin d'un job)
         * puis la transition externe (arrivee d'un job).
         */

        public void deltcon(double e, message x) {
                deltint();
                deltext(e,x);
        }

        /**
         * La methode "delta_ext" dans la notation mathematique.
         * Inutile de preciser l'etat courant car il est connu dans l'objet
         * (la combinaison des variables interne, de la variable predefinie
         * "phase", et la variable predefinie "sigma")
         * Dans le cas present, en cas de reception d'un job sur le port
         * "in", on change la phase de "F" (free) en "B" (busy) pour la duree
         * prevue de traitement d'une tache, qui est conservee dans la variable
         * period_
         * Dans le cas ou par erreur le composant recevrait un message sur
         * un autre port que "in", ce message est ignore, et l'horloge interne
         * est avancee avec Continue(e).
         */

        public void deltext(double e, message x) {
                /**
                 * En general, on consomme le temps ecoule dans l'etat courant.
                 * Ce qui permet de traiter correctement le cas des receptions sur
                 * un port non prevu.
                 */

                Continue(e);

                /* Un message peut etre multiple, cad contenir plusieur messages
                 * simples. Donc pour parcourir les messages il faut faire une
                 * boucle. Ensuite, a chaque tour de boucle, on teste sur quel
                 * port se trouve le message (ici le port "in")
                 */

                for (int i=0; i< x.getLength();i++) {
                        if (messageOnPort(x,"in",i)) {
                                holdIn("B",period_);   
                        }

                }

        }

        /**
         * Fonction qui calcule la sortie produite par le composant
         * (la fonction "lambda" dans le notation mathematique)
         * Nous utilisons ici la version la plus complete, qui
         * est capable de produire des sorties simultanement sur
         * plusieurs ports. Une sortie multiple est donc la
         * composition de plusieurs sorties simples. Une sortie simple
         * designe un port et une valeur et est de type "content".
         * La valeur d'une sortie simple est un objet de type "entity".
         */

        public message out( )
        {
                /* Construire la valeur de sortie. */
                entity   e = new entity("job");
                /* Construire la sortie simple */
                content  c = makeContent("out",e);
                /* Construire un message vide */
                message  m = new message();
                /* Remplir le message avec une premiere (unique) sortie */
                m.add(c);
                return m;
        }
}

Composant coupl Buffer+Processeur (odBufProc)

public class odBufProc extends ViewableDigraph {

        public odBufProc(String name,double proc_time) {
                super(name);


                ViewableAtomic buf = new odBuffer("Buffer");           
                ViewableAtomic proc = new odProc("Proc",proc_time);

                add(buf);
                add(proc);

                addInport("in");
                addOutport("out");

                initialize();

                addCoupling(this,"in",buf,"in");
                addCoupling(buf,"out",proc,"in");
                addCoupling(proc,"out",buf,"done");
                addCoupling(proc,"out",this,"out");

                addTestInput("in",new entity("job0"));
                addTestInput("in",new entity("job1"),1.0);

        }
}

Composant coupl Generateur + BufProc (odGenBufProc)

package odalle;

import simView.ViewableAtomic;
import simView.ViewableDigraph;

public class odGenBufProc extends ViewableDigraph {

        public odGenBufProc(){
                super("GenBufProc");

                ViewableAtomic gen = new odGen("Generator",2.0);
                ViewableDigraph bp = new odBufProc("BufProc",3.0);

                add(gen);
                add(bp);

                addOutport("out");

                initialize();

                addCoupling(gen,"out",bp,"in");
                addCoupling(bp,"out",this,"out");
        }
}