/* *Copyright 2007, 2011 CCLS Columbia University (USA), LIFO University of Orl��ans (France), BRGM (France) * *Authors: Cyril Nortet, Xiangrong Kong, Ansaf Salleb-Aouissi, Christel Vrain, Daniel Cassard * *This file is part of QuantMiner. * *QuantMiner is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version. * *QuantMiner is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. * *You should have received a copy of the GNU General Public License along with QuantMiner. If not, see <http://www.gnu.org/licenses/>. */ package src.solver; import java.util.*; import src.apriori.*; import src.database.*; public abstract class EvaluationBaseAlgorithm { protected class RefItemQualitatif { public DataColumn m_colonneDonnees; // Colonne de la BD o� sont stock�es les valeurs de l'attribut en m�moire public short m_iIndiceValeurAttribut; // Identifiant de la sous-valeur de l'attribut qui �quivaut � l'item public String m_sChaineIdentifiantItem; public RefItemQualitatif(DataColumn colonneDonnees, short iIndiceValeurAttribut, String sChaineIdentifiant) { m_colonneDonnees = colonneDonnees; m_iIndiceValeurAttribut = iIndiceValeurAttribut; m_sChaineIdentifiantItem = sChaineIdentifiant; } } protected class RefItemQuantitatif { public DataColumn m_colonneDonnees = null; public RefItemQuantitatif(DataColumn colonneDonnees) { m_colonneDonnees = colonneDonnees; } } /**potential rules */ protected class ReglePotentielle implements Comparable { public int m_iDimension = 0; public float m_tIntervalleMin [] = null; // Bornes minimales des 'm_iDimension' intervalles public float m_tIntervalleMax [] = null; // Bornes maximales des 'm_iDimension' intervalles public int m_tIndiceMin [] = null; // Indices des bornes min parmi l'ensemble des valeurs de l'attribut dans la BD public int m_tIndiceMax [] = null; // Indices des bornes max parmi l'ensemble des valeurs de l'attribut dans la BD public float m_fQualite = 0.0f; public int m_iSupportRegle = 0; public int m_iSupportCond = 0; public int m_iNombreTotalIntervalles = 0; public ReglePotentielle(int iDimension, int iNombreTotalIntervalles) { int iIndiceDimension = 0; m_iDimension = iDimension; m_iNombreTotalIntervalles = iNombreTotalIntervalles; m_tIntervalleMin = new float [m_iNombreTotalIntervalles]; m_tIntervalleMax = new float [m_iNombreTotalIntervalles]; m_tIndiceMin = new int [m_iNombreTotalIntervalles]; m_tIndiceMax = new int [m_iNombreTotalIntervalles]; m_fQualite = 0.0f; m_iSupportRegle = 0; m_iSupportCond = 0; } public int compareTo(Object o) { if ( this.m_fQualite < ((ReglePotentielle)o).m_fQualite ) return -1; else if ( this.m_fQualite == ((ReglePotentielle)o).m_fQualite ) return 0; else return 1; } public void Copier(ReglePotentielle reglePotentielle) { int iIndiceIntervalle = 0; if (reglePotentielle == null) return; if (this.m_iDimension != reglePotentielle.m_iDimension) return; for (iIndiceIntervalle=0; iIndiceIntervalle<m_iNombreTotalIntervalles; iIndiceIntervalle++) { this.m_tIntervalleMin[iIndiceIntervalle] = reglePotentielle.m_tIntervalleMin[iIndiceIntervalle]; this.m_tIntervalleMax[iIndiceIntervalle] = reglePotentielle.m_tIntervalleMax[iIndiceIntervalle]; this.m_tIndiceMin[iIndiceIntervalle] = reglePotentielle.m_tIndiceMin[iIndiceIntervalle]; this.m_tIndiceMax[iIndiceIntervalle] = reglePotentielle.m_tIndiceMax[iIndiceIntervalle]; } this.m_fQualite = reglePotentielle.m_fQualite; this.m_iSupportRegle = reglePotentielle.m_iSupportRegle; this.m_iSupportCond = reglePotentielle.m_iSupportCond; } } // Repr�sentation du sch�ma de la r�gle � optimiser : // Constituants de la r�gle : protected RefItemQualitatif [] m_tItemsQualCond = null; // Items qualificatifs � gauche de la r�gle protected RefItemQuantitatif [] m_tItemsQuantCond = null; // Items quantitatifs � gauche de la r�gle protected RefItemQualitatif [] m_tItemsQualObj = null; // Items qualificatifs � droite de la r�gle protected RefItemQuantitatif [] m_tItemsQuantObj = null; // Items quantitatifs � droite de la r�gle // Nombre d'items de chaque types : protected int m_iNombreItemsQualCond, m_iNombreItemsQuantCond, m_iNombreItemsQualObj, m_iNombreItemsQuantObj; protected int m_iDimension = 0; protected int m_iNombreTotalItems; protected int m_iNombreReglesPotentielles = 0; protected ReglePotentielle [] m_tReglesPotentielles = null; //potential rules protected ReglePotentielle m_meilleureReglePotentielle = null; //best potential rule (only one, maybe change it to an array) protected ReglePotentielle m_derniereReglePotentielleValide = null; //last valid potential rule protected DatabaseAdmin m_gestionBD = null; protected float m_fMinSupp = 0.0f; protected float m_fMinConf = 0.0f; protected float m_fMinSuppRegle = 0.0f; // Support minimal pour autoriser la r�gle (compl�te et sous sa premi�re forme sans disjonctions) protected float m_fMinSuppDisjonction = 0.0f; // Support minimal d'un sous-r�gle pour etre incorpor�e dans la r�gle finale protected int m_iNombreTransactions = 0; protected int m_iDebutIntervallesDroite = 0; // Indice du premier intervalle de la partie droite d'une r�gle potentielle protected int m_iNombreTotalIntervalles = 0; // Nombre total d'intervalles � optimiser (en tenant compte des disjonctions) protected int m_iDisjonctionGaucheCourante = 0; protected int m_iDisjonctionDroiteCourante = 0; protected int m_iNombreDisjonctionsGaucheValides = 0; protected int m_iNombreDisjonctionsDroiteValides = 0; protected boolean m_bPrendreEnCompteQuantitatifsGauche = false; protected boolean m_bPrendreEnCompteQuantitatifsDroite = false; protected int m_iSupportCumuleCond = 0; protected int m_iSupportCumuleRegle = 0; protected AssociationRule m_schemaRegleOptimale = null; // R�gle que l'algorithme doit optimiser en trouvant les meilleures bornes pour chaque intervalle // Structures de donn�es pour l'optimisation des calculs : static protected float [] m_tRandomFloat = null; // Table de r�els compris entre 0.0f et 1.0f, tir�s al�atoirement static protected short m_compteurRandomFloat = 0; protected int [] m_tLignesAPrendreEnCompte = null; // Liste des lignes dans la BD � prendre en compte lors de l'�valuation, c'est-�dire celles qui sont couvertes par les items qualitatifs gauche du sch�ma de r�gle, et qui ne contiennent pas de valeur manquante pour les items quantitatifs pr�sents dans la r�gle protected boolean [] m_tPrendreEnCompteLigneDroite = null; // Tableau indiquant pour chaque ligne de la BD si ses items qualitatifs � droite sont couverts par le sch�ma de r�gle protected boolean [] m_tLignesCouvertesGauche = null; // Tableau indiquant pour chaque ligne de la BD si ses items (qualitatifs et quantitatifs fix�s) � gauche sont couverts par le sch�ma de r�gle protected boolean [] m_tLignesCouvertesDroite = null; // Tableau indiquant pour chaque ligne de la BD si ses items (qualitatifs et quantitatifs fix�s) � gauche sont couverts par le sch�ma de r�gle protected int m_iNombreLignesAPrendreEnCompte = 0; // Nombre d'�l�ments � prendre en compte dans la liste 'm_tLignesCouvertesGauche' (la taille de ce tableau est initialis�e au nombre de lignes totales dans la BD) protected ReglePotentielle [] m_tReglesPotentiellesAEvaluer = null; // All des propositions de r�gles modifi�es et donc qui n�cessitent une r�-�valuation protected int m_iNombreReglesPotentiellesAEvaluer = 0; //the number of potential rules to evaluate static void InitialiserValeursAleatoires() { int iIndiceValeur = 0; if (m_tRandomFloat != null) return; m_tRandomFloat = new float [65536]; for (iIndiceValeur = 0; iIndiceValeur < 65536; iIndiceValeur++) m_tRandomFloat[iIndiceValeur] = (float)java.lang.Math.random(); m_compteurRandomFloat = 0; } public EvaluationBaseAlgorithm(int iNombreReglesPotentielles, DatabaseAdmin gestionBD) { m_iNombreReglesPotentielles = iNombreReglesPotentielles; m_gestionBD = gestionBD; m_fMinSupp = 0.0f; m_fMinConf = 0.0f; m_iNombreTransactions = m_gestionBD.ObtenirNombreLignes(); m_iNombreItemsQualCond = 0; m_iNombreItemsQuantCond = 0; m_iNombreItemsQualObj = 0; m_iNombreItemsQuantObj = 0; m_iDimension = 0; m_iNombreTotalItems = 0; m_schemaRegleOptimale = null; m_tReglesPotentielles = new ReglePotentielle [m_iNombreReglesPotentielles]; m_meilleureReglePotentielle = null; m_derniereReglePotentielleValide = null; m_iNombreTotalIntervalles = 0; m_iDebutIntervallesDroite = 0; m_iNombreDisjonctionsGaucheValides = 0; m_iNombreDisjonctionsDroiteValides = 0; m_bPrendreEnCompteQuantitatifsGauche = false; m_bPrendreEnCompteQuantitatifsDroite = false; m_iSupportCumuleCond = 0; m_iSupportCumuleRegle = 0; InitialiserValeursAleatoires(); m_tLignesAPrendreEnCompte = new int [m_iNombreTransactions]; m_tPrendreEnCompteLigneDroite = new boolean [m_iNombreTransactions]; m_tLignesCouvertesGauche = new boolean [m_iNombreTransactions]; m_tLignesCouvertesDroite = new boolean [m_iNombreTransactions]; m_iNombreLignesAPrendreEnCompte = 0; m_tReglesPotentiellesAEvaluer = new ReglePotentielle [m_iNombreReglesPotentielles]; m_iNombreReglesPotentiellesAEvaluer = 0; } /** * Set statistic parameters * @param fMinSuppRegle Minimun support of a rule * @param fMinConf Minimun confidence of a rule * @param fMinSuppDisjonction minimun support disjunction */ public void SpecifierParametresStatistiques(float fMinSuppRegle, float fMinConf, float fMinSuppDisjonction) { m_fMinSuppRegle = fMinSuppRegle; m_fMinSuppDisjonction = fMinSuppDisjonction; m_fMinSupp = m_fMinSuppRegle; m_fMinConf = fMinConf; } protected void VerifierEtAffecterBornesReglePotentielle(ReglePotentielle reglePotentielle, int iIndiceDimension, int iIndiceDisjonction, int iIndice1, int iIndice2) { DataColumn colonneDonnees = null; int iIndiceTemp = 0; int iIndiceMax = 0; int iIndiceIntervalle = 0; if (iIndiceDimension < m_iNombreItemsQuantCond) { colonneDonnees = m_tItemsQuantCond[ iIndiceDimension ].m_colonneDonnees; iIndiceIntervalle = (m_schemaRegleOptimale.m_iNombreDisjonctionsGauche*iIndiceDimension) + iIndiceDisjonction; } else { colonneDonnees = m_tItemsQuantObj[ iIndiceDimension-m_iNombreItemsQuantCond ].m_colonneDonnees; iIndiceIntervalle = m_iDebutIntervallesDroite + ((iIndiceDimension-m_iNombreItemsQuantCond)*m_schemaRegleOptimale.m_iNombreDisjonctionsDroite) + iIndiceDisjonction; } iIndiceMax = colonneDonnees.m_iNombreValeursReellesCorrectes - 1; // On s'assure du bon ordre des bornes : if (iIndice1 > iIndice2) { iIndiceTemp = iIndice1; iIndice1 = iIndice2; iIndice2 = iIndiceTemp; } // On v�rifie que les indices ne sortent pas des bornes autoris�es, sinon on s'y contraint : if (iIndice1 < 0) iIndice1 = 0; if (iIndice2 < 0) iIndice2 = 0; if (iIndice1 > iIndiceMax) iIndice1 = iIndiceMax; if (iIndice2 > iIndiceMax) iIndice2 = iIndiceMax; // Affectation des bornes dans la r�gle : reglePotentielle.m_tIndiceMin[iIndiceIntervalle] = iIndice1; reglePotentielle.m_tIndiceMax[iIndiceIntervalle] = iIndice2; reglePotentielle.m_tIntervalleMin[iIndiceIntervalle] = colonneDonnees.m_tValeursReellesTriees[iIndice1]; reglePotentielle.m_tIntervalleMax[iIndiceIntervalle] = colonneDonnees.m_tValeursReellesTriees[iIndice2]; } /** * Give an initial value to a potential rule * @param reglePotentielle * @param iIndiceReglePotentielle */ protected void InitialiserReglePotentielle(ReglePotentielle reglePotentielle, int iIndiceReglePotentielle) { int iAmplitudeIntervalle = 0; int iIndiceDimension = 0; int iIndiceDisjonction = 0; int iNombreValeursDomaine = 0; int iNombreDisjonctions = 0; int iIndiceValeurDomaineMin, iIndiceValeurDomaineMax = 0; DataColumn colonneDonnees = null; // Lors des passes suppl�mentaires, on conserve les intervalles d�j� trait�s de la meilleure r�gle : if ( (!m_bPrendreEnCompteQuantitatifsGauche) || (!m_bPrendreEnCompteQuantitatifsDroite) ) reglePotentielle.Copier(m_meilleureReglePotentielle); for (iIndiceDimension=0;iIndiceDimension<m_iDimension;iIndiceDimension++) { if ( ( m_bPrendreEnCompteQuantitatifsGauche && (iIndiceDimension<m_iNombreItemsQuantCond) ) ||( m_bPrendreEnCompteQuantitatifsDroite && (iIndiceDimension>=m_iNombreItemsQuantCond) ) ) { if (iIndiceDimension<m_iNombreItemsQuantCond) { colonneDonnees = m_tItemsQuantCond[ iIndiceDimension ].m_colonneDonnees; iIndiceDisjonction = m_iDisjonctionGaucheCourante; } else { colonneDonnees = m_tItemsQuantObj[ iIndiceDimension-m_iNombreItemsQuantCond ].m_colonneDonnees; iIndiceDisjonction = m_iDisjonctionDroiteCourante; } iNombreValeursDomaine = colonneDonnees.m_iNombreValeursReellesCorrectes; // Ancienne m�thode de g�n�ration totalement al�atoire d'intervalles : //iIndiceValeurDomaineMin = (int)( ((float)java.lang.Math.random()) * ((float)iNombreValeursDomaine) ); //iIndiceValeurDomaineMax = (int)( ((float)java.lang.Math.random()) * ((float)iNombreValeursDomaine) ); // Autre ancienne m�thode qui ne g�n�rait que des intervalles maximaux, ce qui n'est pas bon pour la diversit� : //iIndiceValeurDomaineMin = 0; //iIndiceValeurDomaineMax = iNombreValeursDomaine-1; // Nouvelle m�thode : // L'amplitude de l'intervalle de d�part est d'autant plus large que l'indice de la // r�gle potentielle dans la "population de r�gles" est �lev�, afin d'augmenter la // vari�t�. Cependant, un intervalle de d�part ne peut pas contenir moins de valeurs // que sp�cifi� avec le support minimal. iAmplitudeIntervalle = iNombreValeursDomaine; if (iIndiceReglePotentielle>0) iAmplitudeIntervalle -= (iIndiceReglePotentielle * (iNombreValeursDomaine - ((int)(m_fMinSupp*(float)iNombreValeursDomaine)))) / (m_iNombreReglesPotentielles-1); iIndiceValeurDomaineMin = (int)( ((float)java.lang.Math.random()) * ((float)(iNombreValeursDomaine-iAmplitudeIntervalle)) ); iIndiceValeurDomaineMax = iIndiceValeurDomaineMin + iAmplitudeIntervalle - 1; VerifierEtAffecterBornesReglePotentielle(reglePotentielle, iIndiceDimension, iIndiceDisjonction, iIndiceValeurDomaineMin, iIndiceValeurDomaineMax); } } } public void GenererReglesPotentiellesInitiales() { int iIndiceReglePotentielle = 0; ReglePotentielle reglePotentielle = null; for (iIndiceReglePotentielle=0;iIndiceReglePotentielle<m_iNombreReglesPotentielles;iIndiceReglePotentielle++) { // G�n�ration d'une r�gle sans initialisation : c'est la classe fille qui se chargera // de lui attribuer des valeurs initiales reglePotentielle = new ReglePotentielle(m_iDimension, m_iNombreTotalIntervalles); InitialiserReglePotentielle(reglePotentielle, iIndiceReglePotentielle); m_tReglesPotentielles[iIndiceReglePotentielle] = reglePotentielle; m_tReglesPotentiellesAEvaluer[iIndiceReglePotentielle] = reglePotentielle; } // Cr�ation de la r�gle potentielle repr�sentant celle qui a eu la meilleure qualit� trouv�e jusqu'alors : // creation of the potential rule with the best quality so far m_meilleureReglePotentielle = new ReglePotentielle(m_iDimension, m_iNombreTotalIntervalles); // Cr�ation d'un r�gle potentielle destin�e � m�moriser la meilleure r�gle trouv�e jusqu'alors // lors des multiples passes pour obtenir des r�gles disjonctives : m_derniereReglePotentielleValide = new ReglePotentielle(m_iDimension, m_iNombreTotalIntervalles); m_iNombreReglesPotentiellesAEvaluer = m_iNombreReglesPotentielles; EvaluerReglesPotentielles(); // On force la m�morisation de la meilleure r�gle initiale : //we keep the best initial rule m_meilleureReglePotentielle.Copier(m_tReglesPotentielles[m_iNombreReglesPotentielles-1]); } public void SpecifierSchemaRegle(AssociationRule regle) { Item item = null; ItemQualitative itemQual = null; ItemQuantitative itemQuant = null; int iIndiceItem = 0; int iNombreItemsGauche = 0; int iNombreItemsDroite = 0; int iIndiceAjoutQual = 0; int iIndiceAjoutQuant = 0; int iIndiceLigneDonnees = 0; boolean bItemsCouverts = true; int iValeurQualCourante = 0; int iIndiceDimension = 0; // On commence par stocker de mani�re plus directe (tableaux statiques) les divers // constituants de la r�gle : m_iNombreItemsQualCond = regle.CompterItemsGaucheSelonType(Item.ITEM_TYPE_QUALITATIF); m_iNombreItemsQuantCond = regle.CompterItemsGaucheSelonType(Item.ITEM_TYPE_QUANTITATIF); m_iNombreItemsQualObj = regle.CompterItemsDroiteSelonType(Item.ITEM_TYPE_QUALITATIF); m_iNombreItemsQuantObj = regle.CompterItemsDroiteSelonType(Item.ITEM_TYPE_QUANTITATIF); iNombreItemsGauche = m_iNombreItemsQualCond + m_iNombreItemsQuantCond; iNombreItemsDroite = m_iNombreItemsQualObj + m_iNombreItemsQuantObj; if (m_iNombreItemsQualCond > 0) m_tItemsQualCond = new RefItemQualitatif [m_iNombreItemsQualCond]; else m_tItemsQualCond = null; if (m_iNombreItemsQuantCond > 0) m_tItemsQuantCond = new RefItemQuantitatif [m_iNombreItemsQuantCond]; else m_tItemsQuantCond = null; if (m_iNombreItemsQualObj > 0) m_tItemsQualObj = new RefItemQualitatif [m_iNombreItemsQualObj]; else m_tItemsQualObj = null; if (m_iNombreItemsQuantObj > 0) m_tItemsQuantObj = new RefItemQuantitatif [m_iNombreItemsQuantObj]; else m_tItemsQuantObj = null; // M�morisation des items qualitatifs : iIndiceAjoutQual = 0; iIndiceAjoutQuant = 0; for (iIndiceItem=0; iIndiceItem<iNombreItemsGauche; iIndiceItem++) { item = regle.ObtenirItemGauche(iIndiceItem); if (item != null) { if (item.m_iTypeItem == Item.ITEM_TYPE_QUALITATIF) { itemQual = (ItemQualitative)item; m_tItemsQualCond[iIndiceAjoutQual] = new RefItemQualitatif(itemQual.m_attributQual.m_colonneDonnees, itemQual.m_iIndiceValeur, itemQual.ObtenirNomCompletItem()); iIndiceAjoutQual++; } else if (item.m_iTypeItem == Item.ITEM_TYPE_QUANTITATIF) { itemQuant = (ItemQuantitative)item; m_tItemsQuantCond[iIndiceAjoutQuant] = new RefItemQuantitatif(itemQuant.m_attributQuant.m_colonneDonnees); iIndiceAjoutQuant++; } } } // M�morisation des items quantitatifs : iIndiceAjoutQual = 0; iIndiceAjoutQuant = 0; for (iIndiceItem=0; iIndiceItem<iNombreItemsDroite; iIndiceItem++) { item = regle.ObtenirItemDroite(iIndiceItem); if (item != null) { if (item.m_iTypeItem == Item.ITEM_TYPE_QUALITATIF) { itemQual = (ItemQualitative)item; m_tItemsQualObj[iIndiceAjoutQual] = new RefItemQualitatif(itemQual.m_attributQual.m_colonneDonnees, itemQual.m_iIndiceValeur, itemQual.ObtenirNomCompletItem()); iIndiceAjoutQual++; } else if (item.m_iTypeItem == Item.ITEM_TYPE_QUANTITATIF) { itemQuant = (ItemQuantitative)item; m_tItemsQuantObj[iIndiceAjoutQuant] = new RefItemQuantitatif(itemQuant.m_attributQuant.m_colonneDonnees); iIndiceAjoutQuant++; } } } // M�morisation du sch�ma de la r�gle : m_schemaRegleOptimale = new AssociationRule(regle); // M�morisation d'informations sur le sch�ma de la r�gle : m_iDimension = m_iNombreItemsQuantCond + m_iNombreItemsQuantObj; m_iNombreTotalItems = m_iDimension + m_iNombreItemsQualCond + m_iNombreItemsQualObj; m_iDebutIntervallesDroite = m_schemaRegleOptimale.m_iNombreDisjonctionsGauche * m_iNombreItemsQuantCond; m_iNombreTotalIntervalles = m_schemaRegleOptimale.m_iNombreDisjonctionsGauche*m_iNombreItemsQuantCond + m_schemaRegleOptimale.m_iNombreDisjonctionsDroite*m_iNombreItemsQuantObj; m_iDisjonctionGaucheCourante = 0; m_iDisjonctionDroiteCourante = 0; m_iNombreDisjonctionsGaucheValides = 1; m_iNombreDisjonctionsDroiteValides = 1; m_bPrendreEnCompteQuantitatifsGauche = true; m_bPrendreEnCompteQuantitatifsDroite = true; m_iSupportCumuleCond = 0; m_iSupportCumuleRegle = 0; // Pour optimiser les calculs de l'�valuation d'une r�gle, on constitue un tableau qui // r�pertorie uniquement les lignes qui couvrent les items qualitatifs de la r�gle // (les autres lignes ne seront forc�ment pas couvertes ni par la r�gle, ni m�me par sa partie gauche) : m_iNombreLignesAPrendreEnCompte = 0; for (iIndiceLigneDonnees=0;iIndiceLigneDonnees<m_iNombreTransactions;iIndiceLigneDonnees++) { // D�tection des lignes couvertes par les valeurs qualitatives dans la partie GAUCHE de la r�gle : bItemsCouverts = true; iIndiceItem=0; while ( bItemsCouverts && (iIndiceItem<m_iNombreItemsQualCond) ) { iValeurQualCourante = m_tItemsQualCond[iIndiceItem].m_colonneDonnees.m_tIDQualitatif[iIndiceLigneDonnees]; bItemsCouverts = bItemsCouverts && ( iValeurQualCourante == m_tItemsQualCond[iIndiceItem].m_iIndiceValeurAttribut); iIndiceItem++; } // Et v�rification qu'elles ne contiennent pas de valeurs manquantes pour les items quantitatifs de gauche : if (bItemsCouverts) { iIndiceItem=0; while ( bItemsCouverts && (iIndiceItem<m_iNombreItemsQuantCond) ) { bItemsCouverts = (m_tItemsQuantCond[iIndiceItem].m_colonneDonnees.m_tValeurReelle[iIndiceLigneDonnees] != DatabaseAdmin.VALEUR_MANQUANTE_FLOAT ); iIndiceItem++; } } if (bItemsCouverts) { m_tLignesAPrendreEnCompte[m_iNombreLignesAPrendreEnCompte] = iIndiceLigneDonnees; m_iNombreLignesAPrendreEnCompte++; } // Test des valeurs qualitatives dans la partie DROITE de la r�gle : bItemsCouverts = true; iIndiceItem=0; while ( bItemsCouverts && (iIndiceItem<m_iNombreItemsQualObj) ) { iValeurQualCourante = m_tItemsQualObj[iIndiceItem].m_colonneDonnees.m_tIDQualitatif[iIndiceLigneDonnees]; bItemsCouverts = bItemsCouverts && ( iValeurQualCourante == m_tItemsQualObj[iIndiceItem].m_iIndiceValeurAttribut); iIndiceItem++; } // Et v�rification que la ligne ne contient pas de valeurs manquantes pour les items quantitatifs de droite : if (bItemsCouverts) { iIndiceItem=0; while ( bItemsCouverts && (iIndiceItem<m_iNombreItemsQuantObj) ) { bItemsCouverts = (m_tItemsQuantObj[iIndiceItem].m_colonneDonnees.m_tValeurReelle[iIndiceLigneDonnees] != DatabaseAdmin.VALEUR_MANQUANTE_FLOAT ); iIndiceItem++; } } m_tPrendreEnCompteLigneDroite[iIndiceLigneDonnees] = bItemsCouverts; m_tLignesCouvertesGauche[iIndiceLigneDonnees] = false; m_tLignesCouvertesDroite[iIndiceLigneDonnees] = false; } /* m_tItemsQuantCond[iIndiceItem].m_colonneDonnees.m_tValeurReelle[iIndiceLigneDonnees] m_tIndicesLignesTrieesAttributQuant */ } // Prend en compte une nouvelle disjonction et relance l'algorithme : public boolean InitierNouvellePasse() { boolean bProchainePassePrivilegieDroite = false; int [] tNouvellesLignesAPrendreEnCompte = null; int iNombreNouvellesLignesAPrendreEnCompte = 0; int iIndiceLigneDonnees = 0; int iIndiceLigne = 0; boolean bItemCondCouvertReglePotentielle = false; boolean bItemObjCouvertReglePotentielle = false; boolean bItemRegleCouvertReglePotentielle = false; boolean bPremierePasse = false; int iIndiceDimension = 0; int iIndiceIntervalle = 0; float fValeurReelle = 0.0f; int iIndiceReglePotentielle = 0; boolean bNouvelleRegleEstSolide = false; int iAncienSupportCumuleRegle = 0; int iAncienSupportCumuleCond = 0; // Si aucune disjonction ne doit appara�tre dans la r�gle, on peut arr�ter l'algorithme : if ( (m_schemaRegleOptimale.m_iNombreDisjonctionsGauche == 1) &&(m_schemaRegleOptimale.m_iNombreDisjonctionsDroite == 1) ) { m_iSupportCumuleCond = m_meilleureReglePotentielle.m_iSupportCond; m_iSupportCumuleRegle = m_meilleureReglePotentielle.m_iSupportRegle; return false; } bPremierePasse = m_bPrendreEnCompteQuantitatifsGauche && m_bPrendreEnCompteQuantitatifsDroite; // On v�rifie que la nouvelle passe a produit une r�gle de bonne qualit�, sinon on ne la prend pas en compte : bNouvelleRegleEstSolide = ( ( ((float)m_meilleureReglePotentielle.m_iSupportRegle) >= m_fMinSupp*((float)m_iNombreTransactions) ) &&( ((float)m_meilleureReglePotentielle.m_iSupportRegle) >= m_fMinConf*((float)m_meilleureReglePotentielle.m_iSupportCond) ) ); if (bNouvelleRegleEstSolide) { // On m�morise les caract�ristisques de la derni�re r�gle (cumul�e) valide, au cas o� il faille la restaurer : iAncienSupportCumuleRegle = m_iSupportCumuleRegle; iAncienSupportCumuleCond = m_iSupportCumuleCond; // On supprime de la table tous les exemples couverts par la r�gle : tNouvellesLignesAPrendreEnCompte = new int [m_iNombreTransactions]; iNombreNouvellesLignesAPrendreEnCompte = 0; // 'm_tLignesAPrendreEnCompte' contient toutes les lignes couvertes par les items qualitatifs // gauche de la r�gle, ne contient pas d'attribut quantitatif dont la ligne correspondante // pr�sente une valeur manquante, et enfin on lui retire successivement toutes les lignes // couvertes par la r�gle dont les disjonctions sont construites incr�mentalement. // 'm_tLignesCouvertesGauche' indique pour chaque ligne si elle est couverte // par l'une des disjonctions gauches jusqu'alors construites pour la r�gle // 'm_tPrendreEnCompteLigneDroite' indique pour chaque ligne si elle est couverte // par l'ensemble des items qualitatitifs de la partie droite de la r�gle, et �galement si // elle ne contient pas de valeur manquante pour l'un des attributs quantitatifs de la partie droite. for (iIndiceLigne=0; iIndiceLigne<m_iNombreLignesAPrendreEnCompte; iIndiceLigne++) { iIndiceLigneDonnees = m_tLignesAPrendreEnCompte[iIndiceLigne]; // Indice r�el de la lignes dans la BD bItemCondCouvertReglePotentielle = m_tLignesCouvertesGauche[iIndiceLigneDonnees]; bItemObjCouvertReglePotentielle = m_tLignesCouvertesDroite[iIndiceLigneDonnees]; // Test des valeurs quantitatives dans la partie gauche de la r�gle : if (m_bPrendreEnCompteQuantitatifsGauche) { bItemCondCouvertReglePotentielle = true; iIndiceDimension=0; iIndiceIntervalle = m_iDisjonctionGaucheCourante; while ( bItemCondCouvertReglePotentielle && (iIndiceDimension<m_iNombreItemsQuantCond) ) { fValeurReelle = m_tItemsQuantCond[iIndiceDimension].m_colonneDonnees.m_tValeurReelle[iIndiceLigneDonnees]; bItemCondCouvertReglePotentielle = ( fValeurReelle >= m_meilleureReglePotentielle.m_tIntervalleMin[iIndiceIntervalle] ) && ( fValeurReelle <= m_meilleureReglePotentielle.m_tIntervalleMax[iIndiceIntervalle] ); iIndiceDimension++; iIndiceIntervalle += m_schemaRegleOptimale.m_iNombreDisjonctionsGauche; } // Mise � jour du support en tenant compte de l'adjonction du nouvel intervalle, // et en faisant attention � ne pas comptabiliser d'�ventuelles zones qui se recouvrent : if ( bItemCondCouvertReglePotentielle && (!m_tLignesCouvertesGauche[iIndiceLigneDonnees]) ) m_iSupportCumuleCond++; m_tLignesCouvertesGauche[iIndiceLigneDonnees] = m_tLignesCouvertesGauche[iIndiceLigneDonnees] || bItemCondCouvertReglePotentielle; } // Test des valeurs quantitatives dans la partie droite de la r�gle if (m_bPrendreEnCompteQuantitatifsDroite) { // Tout d'abord on v�rifie la couverture, m�me si la condition n'est pas v�rifi�e // (afin de mettre � jour correctement le tableau 'm_tLignesCouvertesDroite') : bItemObjCouvertReglePotentielle = m_tPrendreEnCompteLigneDroite[iIndiceLigneDonnees]; iIndiceDimension = m_iNombreItemsQuantCond; iIndiceIntervalle = m_iDebutIntervallesDroite + m_iDisjonctionDroiteCourante; while ( bItemObjCouvertReglePotentielle && (iIndiceDimension<m_iDimension) ) { fValeurReelle = m_tItemsQuantObj[iIndiceDimension-m_iNombreItemsQuantCond].m_colonneDonnees.m_tValeurReelle[iIndiceLigneDonnees]; bItemObjCouvertReglePotentielle = ( fValeurReelle >= m_meilleureReglePotentielle.m_tIntervalleMin[iIndiceIntervalle] ) && ( fValeurReelle <= m_meilleureReglePotentielle.m_tIntervalleMax[iIndiceIntervalle] ); iIndiceDimension++; iIndiceIntervalle += m_schemaRegleOptimale.m_iNombreDisjonctionsDroite; } m_tLignesCouvertesDroite[iIndiceLigneDonnees] = m_tLignesCouvertesDroite[iIndiceLigneDonnees] || bItemObjCouvertReglePotentielle; } // La r�gle n'est couverte que si les parties gauche et droite le sont : bItemRegleCouvertReglePotentielle = bItemCondCouvertReglePotentielle && bItemObjCouvertReglePotentielle; if (bItemRegleCouvertReglePotentielle) m_iSupportCumuleRegle++; // On ne conserve que les lignes non couvertes par la r�gle : if ( (!bItemCondCouvertReglePotentielle) || (!bItemRegleCouvertReglePotentielle) ) { tNouvellesLignesAPrendreEnCompte[iNombreNouvellesLignesAPrendreEnCompte] = iIndiceLigneDonnees; iNombreNouvellesLignesAPrendreEnCompte ++; } } // On v�rifie maintenant que la r�gle cumulant les disjonctions est elle aussi valide : bNouvelleRegleEstSolide = ( ( ((float)m_iSupportCumuleRegle) >= m_fMinSuppRegle*((float)m_iNombreTransactions) ) &&( ((float)m_iSupportCumuleRegle) >= m_fMinConf*((float)m_iSupportCumuleCond) ) ); if (bNouvelleRegleEstSolide) { // On remplace l'ancien index de lignes par le nouveau, �pur� : m_tLignesAPrendreEnCompte = tNouvellesLignesAPrendreEnCompte; m_iNombreLignesAPrendreEnCompte = iNombreNouvellesLignesAPrendreEnCompte; // On prend en compte la nouvelle disjonction : if ( (m_bPrendreEnCompteQuantitatifsGauche) && (!m_bPrendreEnCompteQuantitatifsDroite) ) m_iNombreDisjonctionsGaucheValides++; if ( (m_bPrendreEnCompteQuantitatifsDroite) && (!m_bPrendreEnCompteQuantitatifsGauche) ) m_iNombreDisjonctionsDroiteValides++; // On m�morise la meilleure r�gle trouv�e jusqu'ici : m_derniereReglePotentielleValide.Copier(m_meilleureReglePotentielle); } // Sinon on ne tient pas compte de la nouvelle r�gle et on restaure l'�tat pr�c�dent : else { m_iSupportCumuleRegle = iAncienSupportCumuleRegle; m_iSupportCumuleCond = iAncienSupportCumuleCond; } } if (!bNouvelleRegleEstSolide) { // Si la derni�re r�gle g�n�r�e n'a pas permis d'am�liorer la r�gle initiale, on arr�te la recherche // de nouvelles disjonctions du c�t� o� on vient d'effectuer la pr�c�dente passe : if (m_bPrendreEnCompteQuantitatifsGauche) m_iDisjonctionGaucheCourante = m_schemaRegleOptimale.m_iNombreDisjonctionsGauche; if (m_bPrendreEnCompteQuantitatifsDroite) m_iDisjonctionDroiteCourante = m_schemaRegleOptimale.m_iNombreDisjonctionsDroite; // On restaure la derni�re r�gle valide (si celle-ci existe) : if (!bPremierePasse) m_meilleureReglePotentielle.Copier(m_derniereReglePotentielleValide); else { // Mise � jour n�cessaires si la premi�re r�gle trouv�e n'�tait pas valide : m_iSupportCumuleCond = m_meilleureReglePotentielle.m_iSupportCond; m_iSupportCumuleRegle = m_meilleureReglePotentielle.m_iSupportRegle; } } bProchainePassePrivilegieDroite = m_bPrendreEnCompteQuantitatifsGauche; if (bProchainePassePrivilegieDroite) { if (m_iDisjonctionDroiteCourante+1 < m_schemaRegleOptimale.m_iNombreDisjonctionsDroite) { m_iDisjonctionDroiteCourante++; m_bPrendreEnCompteQuantitatifsGauche = false; m_bPrendreEnCompteQuantitatifsDroite = true; } else if (m_iDisjonctionGaucheCourante+1 < m_schemaRegleOptimale.m_iNombreDisjonctionsGauche) { m_iDisjonctionGaucheCourante++; m_bPrendreEnCompteQuantitatifsGauche = true; m_bPrendreEnCompteQuantitatifsDroite = false; } else m_bPrendreEnCompteQuantitatifsGauche = m_bPrendreEnCompteQuantitatifsDroite = false; } else { if (m_iDisjonctionGaucheCourante+1 < m_schemaRegleOptimale.m_iNombreDisjonctionsGauche) { m_iDisjonctionGaucheCourante++; m_bPrendreEnCompteQuantitatifsGauche = true; m_bPrendreEnCompteQuantitatifsDroite = false; } else if (m_iDisjonctionDroiteCourante+1 < m_schemaRegleOptimale.m_iNombreDisjonctionsDroite) { m_iDisjonctionDroiteCourante++; m_bPrendreEnCompteQuantitatifsGauche = false; m_bPrendreEnCompteQuantitatifsDroite = true; } else m_bPrendreEnCompteQuantitatifsGauche = m_bPrendreEnCompteQuantitatifsDroite = false; } // On g�n�re un nouvel ensemble de r�gles potentielles pour la passe suivante : if ( m_bPrendreEnCompteQuantitatifsGauche || m_bPrendreEnCompteQuantitatifsDroite ) { // Pour les passes suivantes, on utilise un support moins �lev� pour autoris� les r�gles suppl�mentaires � �tre incorpor�es � la r�gle principale : m_fMinSupp = m_fMinSuppDisjonction; for (iIndiceReglePotentielle=0; iIndiceReglePotentielle<m_iNombreReglesPotentielles; iIndiceReglePotentielle++) { InitialiserReglePotentielle(m_tReglesPotentielles[iIndiceReglePotentielle], iIndiceReglePotentielle); m_tReglesPotentiellesAEvaluer[iIndiceReglePotentielle] = m_tReglesPotentielles[iIndiceReglePotentielle]; } m_iNombreReglesPotentiellesAEvaluer = m_iNombreReglesPotentielles; EvaluerReglesPotentielles(); m_meilleureReglePotentielle.Copier(m_tReglesPotentielles[m_iNombreReglesPotentielles-1]); return true; } return false; } /** * Evaluation of the set of potential rules in one scan of the dataset */ public void EvaluerReglesPotentielles() { ReglePotentielle reglePotentielle = null; DataColumn colonneDonnees = null; int iIndiceLigneDonnees = 0; int iIndiceLigne = 0; int iIndiceDimension = 0; int iIndiceDisjonction = 0; int iIndiceItem = 0; int iIndiceReglePotentielle = 0; short iValeurQualCourante = 0; // Valeur qualitaive lue pour un attribut sur une ligne de la BD float fValeurQuantCourante = 0; // Valeur num�rique lue pour un attribut sur une ligne de la BD boolean bItemCondCouvertReglePotentielle = false; boolean bItemRegleCouvertReglePotentielle = false; float [] tValeursReelles = null; // Tableau contenant les valeurs des attributs quantitatifs pour une ligne int iNombreDisjonctions = 0; int iIndiceIntervalle = 0; boolean bPremierePasse = false; boolean bTestPreliminaire = false; bPremierePasse = (m_bPrendreEnCompteQuantitatifsGauche && m_bPrendreEnCompteQuantitatifsDroite); // Le test pr�liminaire permet d'�viter de passer dans la plus grosse partie du calcul // dans le cas o� le 1er item quantitatif n'est pas v�rifi� : bTestPreliminaire = m_bPrendreEnCompteQuantitatifsGauche && (m_iNombreItemsQuantCond > 0); // On r�initialise les mesures de support pour chacunes des r�gles potentielles : for (iIndiceReglePotentielle=0;iIndiceReglePotentielle<m_iNombreReglesPotentiellesAEvaluer;iIndiceReglePotentielle++) { reglePotentielle = m_tReglesPotentiellesAEvaluer[iIndiceReglePotentielle]; reglePotentielle.m_iSupportCond = 0; reglePotentielle.m_iSupportRegle = 0; } tValeursReelles = new float [m_iDimension]; // On commence par �valuer la couverture des items qualitatifs, ceux-ci �tant // communs � toutes les r�gles potentielles. Pour cela, d'une part on ne parcourt que les lignes // couvertes par les items qualitatifs gauche de la r�gle. Par ailleurs, on a d�j� // pr�-calcul� la couverture droite lors du passage du sch�ma de r�gle � l'algorithme. for (iIndiceLigne = 0; iIndiceLigne < m_iNombreLignesAPrendreEnCompte; iIndiceLigne++) { // Le tableau 'm_tLignesAPrendreEnCompte' contient toutes les lignes couvertes // par la partie gauche QUALITATIVE de la r�gle, // mais a �t� d�pourvu des lignes couvertes par la r�gle en entier (items qualitatifs et quantitatifs). iIndiceLigneDonnees = m_tLignesAPrendreEnCompte[iIndiceLigne]; // Indice r�el de la lignes dans la BD // On r�pertorie les valeurs num�riques pour chaque colonne de la ligne : for (iIndiceDimension=0; iIndiceDimension<m_iNombreItemsQuantCond; iIndiceDimension++) tValeursReelles[iIndiceDimension] = m_tItemsQuantCond[iIndiceDimension].m_colonneDonnees.m_tValeurReelle[iIndiceLigneDonnees]; if (m_tPrendreEnCompteLigneDroite[iIndiceLigneDonnees]) for (iIndiceDimension=m_iNombreItemsQuantCond; iIndiceDimension<m_iDimension; iIndiceDimension++) tValeursReelles[iIndiceDimension] = m_tItemsQuantObj[iIndiceDimension-m_iNombreItemsQuantCond].m_colonneDonnees.m_tValeurReelle[iIndiceLigneDonnees]; // On �value ensuite la couverture des intervalles quantitatifs pour chacunes des regles potentielles : for (iIndiceReglePotentielle=0;iIndiceReglePotentielle<m_iNombreReglesPotentiellesAEvaluer;iIndiceReglePotentielle++) { reglePotentielle = m_tReglesPotentiellesAEvaluer[iIndiceReglePotentielle]; bItemCondCouvertReglePotentielle = true; if (bTestPreliminaire) bItemCondCouvertReglePotentielle = (tValeursReelles[0] >= reglePotentielle.m_tIntervalleMin[m_iDisjonctionGaucheCourante]) && (tValeursReelles[0] <= reglePotentielle.m_tIntervalleMax[m_iDisjonctionGaucheCourante]); if (bItemCondCouvertReglePotentielle) { // Test des valeurs quantitatives dans la partie gauche de la r�gle : if (!m_bPrendreEnCompteQuantitatifsGauche) bItemCondCouvertReglePotentielle = m_tLignesCouvertesGauche[iIndiceLigneDonnees]; else { iIndiceDimension=1; iIndiceIntervalle = m_iDisjonctionGaucheCourante + m_schemaRegleOptimale.m_iNombreDisjonctionsGauche; while ( bItemCondCouvertReglePotentielle && (iIndiceDimension<m_iNombreItemsQuantCond) ) { bItemCondCouvertReglePotentielle = ( tValeursReelles[iIndiceDimension] >= reglePotentielle.m_tIntervalleMin[iIndiceIntervalle] ) && ( tValeursReelles[iIndiceDimension] <= reglePotentielle.m_tIntervalleMax[iIndiceIntervalle] ); iIndiceDimension++; iIndiceIntervalle += m_schemaRegleOptimale.m_iNombreDisjonctionsGauche; } } if (bItemCondCouvertReglePotentielle) { reglePotentielle.m_iSupportCond++; // Test des valeurs quantitatives dans la partie droite de la r�gle // (utile uniquement si la partie gauche est couverte, afin d'augmenter le support de la r�gle, // et � condition que les items qualitatifs droits soient eux aussi couverts) if (!m_bPrendreEnCompteQuantitatifsDroite) bItemRegleCouvertReglePotentielle = (bItemCondCouvertReglePotentielle) && (m_tLignesCouvertesDroite[iIndiceLigneDonnees]); else { bItemRegleCouvertReglePotentielle = bItemCondCouvertReglePotentielle && (m_tPrendreEnCompteLigneDroite[iIndiceLigneDonnees]); iIndiceDimension = m_iNombreItemsQuantCond; iIndiceIntervalle = m_iDebutIntervallesDroite + m_iDisjonctionDroiteCourante; while ( bItemRegleCouvertReglePotentielle && (iIndiceDimension<m_iDimension) ) { bItemRegleCouvertReglePotentielle = ( tValeursReelles[iIndiceDimension] >= reglePotentielle.m_tIntervalleMin[iIndiceIntervalle] ) && ( tValeursReelles[iIndiceDimension] <= reglePotentielle.m_tIntervalleMax[iIndiceIntervalle] ); iIndiceDimension++; iIndiceIntervalle += m_schemaRegleOptimale.m_iNombreDisjonctionsDroite; } } if (bItemRegleCouvertReglePotentielle) reglePotentielle.m_iSupportRegle++; } } } } // La mesure de qualit� reste � la charge de la classe fille : for (iIndiceReglePotentielle = 0;iIndiceReglePotentielle<m_iNombreReglesPotentiellesAEvaluer;iIndiceReglePotentielle++) EvaluerQualiteReglePotentielle( m_tReglesPotentiellesAEvaluer[iIndiceReglePotentielle] ); // Tous les indices de qualit� sont maintenant � jour : m_iNombreReglesPotentiellesAEvaluer = 0; // Tri croissant par quality : Arrays.sort(m_tReglesPotentielles); // M�morisation de la meilleure r�gle potentielle : if (m_tReglesPotentielles[m_iNombreReglesPotentielles-1].m_fQualite >= m_meilleureReglePotentielle.m_fQualite) m_meilleureReglePotentielle.Copier(m_tReglesPotentielles[m_iNombreReglesPotentielles-1]); } public AssociationRule ObtenirMeilleureRegle() { Item item = null; ItemQualitative itemQual = null; ItemQuantitative itemQuant = null; int iIndiceItem = 0; int iIndiceItemQuant = 0; float fConfianceRegle = 0.0f; int iIndiceIntervalleReglePotentielle = 0; int iIndiceDisjonction = 0; if (m_schemaRegleOptimale == null) return null; // Determination des bornes optimales dans la partie gauche de la r�gle : iIndiceIntervalleReglePotentielle = 0; iIndiceItemQuant = 0; for (iIndiceItem = 0; iIndiceItem < m_schemaRegleOptimale.m_iNombreItemsGauche; iIndiceItem++) { item = m_schemaRegleOptimale.ObtenirItemGauche(iIndiceItem); if (item.m_iTypeItem == Item.ITEM_TYPE_QUANTITATIF) { itemQuant = (ItemQuantitative)item; for (iIndiceDisjonction = 0; iIndiceDisjonction < m_iNombreDisjonctionsGaucheValides; iIndiceDisjonction++) { itemQuant.m_tBornes[iIndiceDisjonction*2] = m_meilleureReglePotentielle.m_tIntervalleMin[iIndiceIntervalleReglePotentielle]; itemQuant.m_tBornes[iIndiceDisjonction*2+1] = m_meilleureReglePotentielle.m_tIntervalleMax[iIndiceIntervalleReglePotentielle]; iIndiceIntervalleReglePotentielle++; } iIndiceItemQuant++; iIndiceIntervalleReglePotentielle += m_schemaRegleOptimale.m_iNombreDisjonctionsGauche - iIndiceDisjonction; } } // Determination des bornes optimales dans la partie droite de la regle : iIndiceIntervalleReglePotentielle = this.m_iDebutIntervallesDroite; iIndiceItemQuant = m_iNombreItemsQuantCond; for (iIndiceItem=0;iIndiceItem<m_schemaRegleOptimale.m_iNombreItemsDroite;iIndiceItem++) { item = m_schemaRegleOptimale.ObtenirItemDroite(iIndiceItem); if (item.m_iTypeItem == Item.ITEM_TYPE_QUANTITATIF) { itemQuant = (ItemQuantitative)item; for (iIndiceDisjonction=0; iIndiceDisjonction<m_iNombreDisjonctionsDroiteValides; iIndiceDisjonction++) { itemQuant.m_tBornes[iIndiceDisjonction*2] = m_meilleureReglePotentielle.m_tIntervalleMin[iIndiceIntervalleReglePotentielle]; itemQuant.m_tBornes[iIndiceDisjonction*2+1] = m_meilleureReglePotentielle.m_tIntervalleMax[iIndiceIntervalleReglePotentielle]; iIndiceIntervalleReglePotentielle++; } iIndiceItemQuant++; iIndiceIntervalleReglePotentielle += m_schemaRegleOptimale.m_iNombreDisjonctionsDroite - iIndiceDisjonction; } } m_schemaRegleOptimale.m_iNombreDisjonctionsGaucheValides = this.m_iNombreDisjonctionsGaucheValides; m_schemaRegleOptimale.m_iNombreDisjonctionsDroiteValides = this.m_iNombreDisjonctionsDroiteValides; m_meilleureReglePotentielle.m_iSupportCond = m_iSupportCumuleCond; m_meilleureReglePotentielle.m_iSupportRegle = m_iSupportCumuleRegle; m_schemaRegleOptimale.AssignerNombreOccurrences( m_meilleureReglePotentielle.m_iSupportRegle ); m_schemaRegleOptimale.AssignerSupport( ((float)m_meilleureReglePotentielle.m_iSupportRegle) / ((float)m_iNombreTransactions) ); if (m_meilleureReglePotentielle.m_iSupportCond > 0) fConfianceRegle = ((float)m_meilleureReglePotentielle.m_iSupportRegle) / ((float)m_meilleureReglePotentielle.m_iSupportCond); else fConfianceRegle = 0.0f; m_schemaRegleOptimale.AssignerConfiance(fConfianceRegle); return m_schemaRegleOptimale; } public int ObtenirMeilleurSupportCourant() { return m_tReglesPotentielles[m_iNombreReglesPotentielles-1].m_iSupportRegle; } public float ObtenirMeilleurSupportRelatifCourant() { return ((float)m_tReglesPotentielles[m_iNombreReglesPotentielles-1].m_iSupportRegle / (float)m_iNombreTransactions); } public float ObtenirMeilleureConfianceCourant() { int iSupportCond = 0; int iSupportRegle = 0; iSupportCond = m_tReglesPotentielles[m_iNombreReglesPotentielles-1].m_iSupportCond; iSupportRegle = m_tReglesPotentielles[m_iNombreReglesPotentielles-1].m_iSupportRegle; if (iSupportCond>0) return ((float)iSupportRegle / (float)iSupportCond); else return 0.0f; } public float CalculerQualiteMoyenne() { int iIndiceReglePotentielle = 0; float fCumulQualite = 0.0f; fCumulQualite = 0.0f; for (iIndiceReglePotentielle = 0; iIndiceReglePotentielle < m_iNombreReglesPotentielles; iIndiceReglePotentielle++) fCumulQualite += m_tReglesPotentielles[iIndiceReglePotentielle].m_fQualite; return (fCumulQualite / (float)m_iNombreReglesPotentielles); } public float ObtenirMeilleureQualiteCourante() { return m_tReglesPotentielles[m_iNombreReglesPotentielles-1].m_fQualite; } public float ObtenirPireQualiteCourante() { return m_tReglesPotentielles[0].m_fQualite; } public void EvaluerQualiteReglePotentielle(ReglePotentielle reglePotentielle) { int iIndiceDimension = 0; int iIndiceDisjonction = 0; int iNombreDisjonctions = 0; int iIndiceIntervalle = 0; int iSupportIntervalle = 0; int iSupportMax = 0; float fTauxCouvertureDomaine1 = 0.0f; float fTauxCouvertureDomaine2 = 0.0f; DataColumn colonneDonnees = null; // 1 �re mesure de qualit� : /* individu.m_fQualite = (float)individu.m_iSupportRegle - m_fMinConf * (float)individu.m_iSupportCond; if ((float)individu.m_iSupportRegle < m_fMinSupp*(float)m_iNombreTransactions) individu.m_fQualite = -(float)m_iNombreTransactions; */ // 2nde mesure de qualit� : on pond�re par le taux de couverture du domaine de chaque valeur quantitative //calculate the gain reglePotentielle.m_fQualite = (float)reglePotentielle.m_iSupportRegle - m_fMinConf * (float)reglePotentielle.m_iSupportCond; //reglePotentielle.m_fQualite /= (float)m_iNombreTransactions; if (reglePotentielle.m_fQualite > 0.0f) { for (iIndiceDimension=0; iIndiceDimension<m_iDimension; iIndiceDimension++) { if ( ( m_bPrendreEnCompteQuantitatifsGauche && (iIndiceDimension<m_iNombreItemsQuantCond) ) ||( m_bPrendreEnCompteQuantitatifsDroite && (iIndiceDimension>=m_iNombreItemsQuantCond) ) ) { if (iIndiceDimension<m_iNombreItemsQuantCond) { iIndiceIntervalle = (iIndiceDimension*m_schemaRegleOptimale.m_iNombreDisjonctionsGauche) + m_iDisjonctionGaucheCourante; colonneDonnees = m_tItemsQuantCond[ iIndiceDimension ].m_colonneDonnees; } else { iIndiceIntervalle = m_iDebutIntervallesDroite + ((iIndiceDimension-m_iNombreItemsQuantCond)*m_schemaRegleOptimale.m_iNombreDisjonctionsDroite) + m_iDisjonctionDroiteCourante; colonneDonnees = m_tItemsQuantObj[ iIndiceDimension-m_iNombreItemsQuantCond ].m_colonneDonnees; } // Technique 2 : // - probl�me des petits �lots dont le support est < minsupp/nb intervalles et donc non trouv�s, // - tend � ne pas d�passer du support minimal, alors qu'il pourrait sans perdre de qualit� fTauxCouvertureDomaine1 = reglePotentielle.m_tIntervalleMax[iIndiceIntervalle] - reglePotentielle.m_tIntervalleMin[iIndiceIntervalle]; fTauxCouvertureDomaine1 /= (colonneDonnees.m_fValeurMax - colonneDonnees.m_fValeurMin); iSupportMax = colonneDonnees.m_iNombreValeursReellesCorrectes; if (iSupportMax > 0) { iSupportIntervalle = colonneDonnees.ObtenirSupportIntervalle(reglePotentielle.m_tIndiceMin[iIndiceIntervalle], reglePotentielle.m_tIndiceMax[iIndiceIntervalle]); fTauxCouvertureDomaine2 = ((float)iSupportIntervalle) / ((float)iSupportMax); } /* if (iIndiceDimension<m_iNombreItemsQuantCond) fTauxCouvertureDomaine2 = 1.0f; else { iSupportIntervalle = m_tItemsQuantObj[ iIndiceDimension-m_iNombreItemsQuantCond ].m_colonneDonnees.ObtenirSupportIntervalle(reglePotentielle.m_tIndiceMin[iIndiceIntervalle], reglePotentielle.m_tIndiceMax[iIndiceIntervalle]); iSupportMax = m_tItemsQuantObj[ iIndiceDimension-m_iNombreItemsQuantCond ].m_colonneDonnees.m_iNombreValeursReellesCorrectes; fTauxCouvertureDomaine2 = ((float)iSupportIntervalle) / ((float)iSupportMax); } */ reglePotentielle.m_fQualite *= (1.0f-fTauxCouvertureDomaine1) * (1.0f-fTauxCouvertureDomaine2); } } } if ((float)reglePotentielle.m_iSupportRegle < m_fMinSupp*(float)m_iNombreTransactions) reglePotentielle.m_fQualite -= (float)m_iNombreTransactions + (float)reglePotentielle.m_iSupportRegle - m_fMinSupp*(float)m_iNombreTransactions ;//) / ((float)m_iNombreTransactions); } }