public void Factoriser()
        {
            /*if ( TypeOperateur != ETypeOperateur.OU )
             *  return;*/
            Dictionary <string, int> compteur = new Dictionary <string, int>();
            Dictionary <string, List <CElementDeArbreOperationnel> > dicConcernesParElement = new Dictionary <string, List <CElementDeArbreOperationnel> >();
            int nNbOccurMax = 0;

            foreach (CElementDeArbreOperationnelOperateur element in from f in m_listeFils.ToArray()
                     where
                     typeof(CElementDeArbreOperationnelOperateur).IsAssignableFrom(f.GetType())
                     select f as CElementDeArbreOperationnelOperateur)
            {
                foreach (CElementDeArbreOperationnel fils in element.Fils)
                {
                    int    nVal   = 0;
                    string strKey = fils.GetKeyFactorisation();
                    compteur.TryGetValue(strKey, out nVal);

                    nVal++;
                    if (nVal > nNbOccurMax)
                    {
                        nNbOccurMax = nVal;
                    }
                    compteur[fils.GetKeyFactorisation()] = nVal;
                    List <CElementDeArbreOperationnel> lst = null;
                    if (!dicConcernesParElement.TryGetValue(strKey, out lst))
                    {
                        lst = new List <CElementDeArbreOperationnel>();
                        dicConcernesParElement[strKey] = lst;
                    }
                    lst.Add(element);
                }
            }
            foreach (CElementDeArbreOperationnelEntite element in from f in m_listeFils.ToArray()
                     where
                     f.GetType() == typeof(CElementDeArbreOperationnelEntite)
                     select f as CElementDeArbreOperationnelEntite)
            {
                int    nVal   = 0;
                string strKey = element.GetKeyFactorisation();
                compteur.TryGetValue(strKey, out nVal);
                nVal++;
                if (nVal > nNbOccurMax)
                {
                    nNbOccurMax = nVal;
                }
                compteur[strKey] = nVal;
                List <CElementDeArbreOperationnel> lst = null;
                if (!dicConcernesParElement.TryGetValue(strKey, out lst))
                {
                    lst = new List <CElementDeArbreOperationnel>();
                    dicConcernesParElement[strKey] = lst;
                }
                lst.Add(element);
            }

            if (nNbOccurMax > 1)
            {
                //Il est possible de factoriser
                foreach (KeyValuePair <string, int> kv in compteur)
                {
                    if (kv.Value == nNbOccurMax)
                    {
                        //On a trouvé celui qu'on voulait factoriser
                        List <CElementDeArbreOperationnel> lstConcernes = null;
                        dicConcernesParElement.TryGetValue(kv.Key, out lstConcernes);
                        if (lstConcernes != null || lstConcernes.Count <= 1)
                        {
                            CElementDeArbreOperationnelOperateur opGlobal;
                            if (GetType() == typeof(CElementDeArbreOperationnelOperateurOu))
                            {
                                opGlobal = new CElementDeArbreOperationnelOperateurEt(null);
                            }
                            else
                            {
                                opGlobal = new CElementDeArbreOperationnelOperateurOu(null);
                            }

                            CElementDeArbreOperationnelOperateur opFactorise;
                            if (GetType() == typeof(CElementDeArbreOperationnelOperateurOu))
                            {
                                opFactorise = new CElementDeArbreOperationnelOperateurOu(null);
                            }
                            else
                            {
                                opFactorise = new CElementDeArbreOperationnelOperateurEt(null);
                            }
                            bool bHasEltToutSeul = false;
                            foreach (CElementDeArbreOperationnel elt in lstConcernes)
                            {
                                if (elt.GetKeyFactorisation() == kv.Key)
                                {
                                    opGlobal.AddFils(elt);
                                    m_listeFils.Remove(elt);
                                    bHasEltToutSeul = true;
                                    //Si c'est un ou, on a "a+(a.b) = a.(1+b)"
                                    //Si c'est un et, on a "a.(a+b) = a"
                                    if (GetType() == typeof(CElementDeArbreOperationnelOperateurOu))
                                    {
                                        opFactorise.AddFils(new CElementDeArbreOperationnelOperateurOu(opFactorise));
                                    }
                                }
                                else if (elt is CElementDeArbreOperationnelOperateur)
                                {
                                    CElementDeArbreOperationnelOperateur operateur = elt as CElementDeArbreOperationnelOperateur;
                                    foreach (CElementDeArbreOperationnel fils in operateur.Fils.ToArray())
                                    {
                                        if (fils.GetKeyFactorisation() == kv.Key)
                                        {
                                            opGlobal.AddFils(fils);
                                            operateur.RemoveFils(fils);
                                        }
                                    }
                                    RemoveFils(elt);
                                    opFactorise.AddFils(elt);
                                }
                            }
                            if (GetType() == typeof(CElementDeArbreOperationnelOperateurOu) ||
                                !bHasEltToutSeul)
                            {
                                //Si et et que on a a.(a+b), ça fait a, donc l'op global n'a que le premier élément
                                opGlobal.AddFils(opFactorise);
                            }
                            AddFils(opGlobal);
                            Simplifier();
                            return;
                        }
                    }
                }
            }
        }
Esempio n. 2
0
        //-------------------------------------------------
        /// <summary>
        /// Calcule l'arbre entre deux noeuds pour un schéma
        /// </summary>
        /// <param name="schema"></param>
        /// <param name="graphe"></param>
        /// <param name="noeudDepart"></param>
        /// <param name="noeudArrivee"></param>
        /// <returns></returns>
        public CResultAErreur CalculArbreRedondanceAuto(
            CSchemaReseau schema,
            CGrapheReseau graphe,
            CNoeudDeGrapheReseau noeudDepart,
            CNoeudDeGrapheReseau noeudArrivee)
        {
            CResultAErreur result = CResultAErreur.True;

            CNoeudDeGrapheReseau[] noeudsEntree;
            if (noeudDepart != null)
            {
                noeudsEntree = new CNoeudDeGrapheReseau[] { noeudDepart }
            }
            ;
            else if (schema.LienReseau == null)  //Ce n'est pas un schéma de lien
            {
                noeudsEntree = graphe.GetNoeudsEntreeNiveau0();
            }
            else
            {
                noeudsEntree = new CNoeudDeGrapheReseau[] {
                    graphe.GetNoeudForElement(schema.LienReseau.Element1, schema)
                };
            }
            CNoeudDeGrapheReseau[] noeudsSortie;
            if (noeudArrivee != null)
            {
                noeudsSortie = new CNoeudDeGrapheReseau[] { noeudArrivee }
            }
            ;
            else if (schema.LienReseau == null)  //Ce n'est pas un schéma de lien
            {
                noeudsSortie = graphe.GetNoeudsSortieNiveau0();
            }
            else
            {
                noeudsSortie = new CNoeudDeGrapheReseau[] {
                    graphe.GetNoeudForElement(schema.LienReseau.Element2, schema)
                };
            }

            CElementDeArbreOperationnelOperateurEt eltSource = new CElementDeArbreOperationnelOperateurEt(null);

            m_elementRacine = eltSource;

            //Ajoute les éléments seuls
            foreach (CNoeudDeGrapheReseau noeud in graphe.GetNoeudsIsoles())
            {
                if (schema.LienReseau == null || noeud.Equals(noeudsEntree[0]) || noeud.Equals(noeudsSortie[0]))
                //si c'est un schéma de lien n'ajoute que les noeuds isolé correspondant à l'entrée ou à la sortie
                {
                    CElementDeArbreOperationnelEntite composant = new CElementDeArbreOperationnelEntite(eltSource, noeud);
                    eltSource.AddFils(composant);
                    result = composant.GetElementCablage(graphe.SensDuGraphe, schema.ContexteDonnee);
                    if (!result)
                    {
                        return(result);
                    }
                    CElementDeArbreOperationnel elementCablage = result.Data as CElementDeArbreOperationnel;
                    if (elementCablage != null)
                    {
                        eltSource.AddFils(elementCablage);
                    }
                }
            }

            foreach (CNoeudDeGrapheReseau noeudEntree in noeudsEntree)
            {
                foreach (CNoeudDeGrapheReseau noeudSortie in noeudsSortie)
                {
                    List <CCheminDeGrapheReseau> chemins = graphe.GetChemins(noeudEntree, noeudSortie);
                    if (chemins.Count() > 0)
                    {
                        CElementDeArbreOperationnelOperateurOu ouPourExtremites = new CElementDeArbreOperationnelOperateurOu(eltSource);
                        eltSource.AddFils(ouPourExtremites);
                        foreach (CCheminDeGrapheReseau chemin in chemins) //parcours tous les chemins en mettant un ou dessus
                        {
                            Stack <CRacineDeSchema> lstRacines = new Stack <CRacineDeSchema>();
                            CRacineDeSchema         racine     = new CRacineDeSchema(schema.Id, null, new CElementDeArbreOperationnelOperateurEt(ouPourExtremites));
                            ouPourExtremites.AddFils(racine.ElementRacine);
                            lstRacines.Push(racine);
                            int nLien = 0;
                            foreach (CLienDeGrapheReseau lien in chemin.Liens)
                            {
                                CRacineDeSchema racineEnCours = lstRacines.Peek();
                                if (lien.EtapesNoeudDepart != null)
                                {
                                    int[] idsSchemas = lien.EtapesNoeudDepart.IdsSchemas;
                                    //Dépile les sous schémas
                                    for (int nEtape = idsSchemas.Count() - 1; nEtape >= 0; nEtape--)
                                    {
                                        int nIdSchema = idsSchemas[nEtape];
                                        if (racineEnCours.IdSchema != nIdSchema)
                                        {
                                            result.EmpileErreur(I.T("Bad path for link @1 in graph for @2 diagram|20050",
                                                                    lien.IdLienReseau.ToString(), lien.IdSchemaReseau.ToString()));
                                            return(result);
                                        }
                                        if (racineEnCours.ElementSousSchema != null)
                                        {
                                            racineEnCours.ElementSousSchema.NoeudArrive = lien.NoeudDepart;
                                        }
                                        lstRacines.Pop();
                                        racineEnCours = lstRacines.Peek();
                                    }
                                }
                                //Si les extremités du lien sont cablées, le lien est dans un et, sinon,
                                //il est directement sous la racine en cours
                                CElementDeArbreOperationnelOperateur elementParentDeLien = racineEnCours.ElementRacine;

                                //Si ce n'est pas le dernier lien, on ajoute que les cablages des noeuds de départ,
                                //Puisque le cablage du noeud d'arrivé sera le cablage du noeud de départ du prochain lien
                                //Par contre, si c'est le dernier lien du chemin, il faut ajouter ce cablage

                                if ((lien.NoeudDepart is CNoeudDeGrapheReseauSite && ((CNoeudDeGrapheReseauSite)lien.NoeudDepart).IsCable) ||
                                    (nLien == chemin.Liens.Count() - 1 && (lien.NoeudArrive is CNoeudDeGrapheReseauSite && ((CNoeudDeGrapheReseauSite)lien.NoeudArrive).IsCable)))
                                {
                                    elementParentDeLien = new CElementDeArbreOperationnelOperateurEt(racineEnCours.ElementRacine);
                                    racineEnCours.ElementRacine.AddFils(elementParentDeLien);
                                }
                                elementParentDeLien.AddFils(new CElementDeArbreOperationnelEntite(elementParentDeLien, lien));

                                //Cablage du site entrée
                                CNoeudDeGrapheReseauSite noeudSite = lien.NoeudDepart as CNoeudDeGrapheReseauSite;
                                if (noeudSite != null && noeudSite.IsCable)
                                {
                                    //Le noeud correspondant à l'élément est déjà dans le schéma du lien
                                    CElementDeArbreOperationnelEntite elementNoeud = new CElementDeArbreOperationnelEntite(null, noeudSite);
                                    result = elementNoeud.GetElementCablage(graphe.SensDuGraphe, schema.ContexteDonnee);
                                    if (!result)
                                    {
                                        return(result);
                                    }
                                    CElementDeArbreOperationnel elementCablage = result.Data as CElementDeArbreOperationnel;
                                    if (elementCablage != null)
                                    {
                                        elementParentDeLien.AddFils(elementCablage);
                                    }
                                }
                                //Cablage du site sortie
                                noeudSite = lien.NoeudArrive as CNoeudDeGrapheReseauSite;
                                if (noeudSite != null && noeudSite.IsCable && nLien == chemin.Liens.Count() - 1)
                                {
                                    CElementDeArbreOperationnelEntite elementNoeud = new CElementDeArbreOperationnelEntite(null, noeudSite);
                                    result = elementNoeud.GetElementCablage(graphe.SensDuGraphe, schema.ContexteDonnee);
                                    if (!result)
                                    {
                                        return(result);
                                    }
                                    CElementDeArbreOperationnel elementCablage = result.Data as CElementDeArbreOperationnel;
                                    if (elementCablage != null)
                                    {
                                        elementParentDeLien.AddFils(elementCablage);
                                    }
                                }

                                if (lien.EtapesNoeudArrivee != null)
                                {
                                    int[] idsSchemas = lien.EtapesNoeudArrivee.IdsSchemas;
                                    foreach (int nIdSchema in idsSchemas)
                                    {
                                        CElementDeArbreOperationnelSousSchema eltSousSchema = new CElementDeArbreOperationnelSousSchema(racineEnCours.ElementRacine);
                                        eltSousSchema.NoeudDepart    = lien.NoeudArrive;
                                        eltSousSchema.ElementDeArbre = new CElementDeArbreOperationnelOperateurEt(racine.ElementRacine);
                                        eltSousSchema.IdSchema       = nIdSchema;
                                        CRacineDeSchema newRacine = new CRacineDeSchema(
                                            nIdSchema,
                                            eltSousSchema,
                                            eltSousSchema.ElementDeArbre as CElementDeArbreOperationnelOperateur);
                                        lstRacines.Push(newRacine);
                                        racineEnCours.ElementRacine.AddFils(eltSousSchema);
                                        racineEnCours = newRacine;
                                    }
                                }
                                nLien++;
                            }
                        }
                    }
                }
            }
            eltSource.Simplifier();
            return(result);
        }
        public override void Simplifier()
        {
            //Simplifie les fils
            foreach (CElementDeArbreOperationnel elt in Fils)
            {
                elt.Simplifier();
            }

            m_listeFils.Sort();
            //Si c'est un OU et qu'il contient un 1, le ou ne sert à rien
            //1+a+b+c = 1
            if (GetType() == typeof(CElementDeArbreOperationnelOperateurOu))
            {
                if (m_listeFils.ToArray().FirstOrDefault(f => f is CElementDeArbreOperationnelTrue) != null)
                {
                    m_listeFils.Clear();
                    return;
                }
            }


            bool bChange = true;

            while (bChange)
            {
                bChange = false;

                /*Fait remonter les fils du même type sur ses propres paramètres
                 * suivant la règle a+(b+c) = a+b+c et a.(b.c) = a.b.c
                 * */
                foreach (CElementDeArbreOperationnelOperateur element in from f in m_listeFils.ToArray()
                         where
                         f.GetType() == GetType()
                         select f as CElementDeArbreOperationnelOperateur)
                {
                    foreach (CElementDeArbreOperationnel fils in element.Fils)
                    {
                        AddFils(fils);
                    }
                    RemoveFils(element);
                    bChange = true;
                }

                /*Supprime les doublons
                 * suivant la règle a+a = a et a.a = a ou les combine, s'il s'agit de trucs
                 * plus compliqués (comme des sous schémas)
                 * */
                Dictionary <string, CElementDeArbreOperationnel> dicElements = new Dictionary <string, CElementDeArbreOperationnel>();
                foreach (CElementDeArbreOperationnel element in m_listeFils.ToArray())
                {
                    if (dicElements.Keys.Contains(element.GetKeyFactorisation()))
                    {
                        IElementDeArbreOperationnelAEgaliteComplexe elementComplexe = element as IElementDeArbreOperationnelAEgaliteComplexe;
                        if (elementComplexe != null)
                        {
                            IElementDeArbreOperationnelAEgaliteComplexe autreElement = dicElements[element.GetKeyFactorisation()] as IElementDeArbreOperationnelAEgaliteComplexe;
                            CElementDeArbreOperationnelOperateur        op;
                            if (GetType() == typeof(CElementDeArbreOperationnelOperateurEt))
                            {
                                op = new CElementDeArbreOperationnelOperateurOu(null);
                            }
                            else
                            {
                                op = new CElementDeArbreOperationnelOperateurEt(null);
                            }
                            if (autreElement.CombineKeyEgal(op, element))
                            {
                                RemoveFils(element);
                            }
                            bChange = true;
                        }
                        else
                        {
                            CElementDeArbreOperationnel autreElement = dicElements[element.GetKeyFactorisation()];
                            if (autreElement.GetFullKey() == element.GetFullKey())
                            {
                                RemoveFils(element);
                                bChange = true;
                            }
                        }
                    }
                    else
                    {
                        dicElements[element.GetKeyFactorisation()] = element;
                    }
                }

                //Supprime les opérateurs avec un zéro ou seul paramètere
                foreach (CElementDeArbreOperationnelOperateur element in from f in m_listeFils.ToArray()
                         where
                         typeof(CElementDeArbreOperationnelOperateur).IsAssignableFrom(f.GetType()) &&
                         ((CElementDeArbreOperationnelOperateur)f).Fils.Count() <= 1
                         select f as CElementDeArbreOperationnelOperateur)
                {
                    if (element.Fils.Count() == 1)
                    {
                        AddFils(element.Fils.ElementAt(0));
                    }
                    m_listeFils.Remove(element);
                    bChange = true;
                }

                if (GetType() == typeof(CElementDeArbreOperationnelOperateurEt))
                {
                    foreach (CElementDeArbreOperationnelTrue opTrue in from f in Fils
                             where f is CElementDeArbreOperationnelTrue
                             select f as CElementDeArbreOperationnelTrue)
                    {
                        RemoveFils(opTrue);
                        bChange = true;
                    }
                }
            }
            //if ( TypeOperateur == ETypeOperateur.OU )
            Factoriser();
            m_listeFils.Sort();
        }