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; } } } } }
//------------------------------------------------- /// <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(); }