Coverage Report - weka.classifiers.bayes.net.search.local.GeneticSearch
 
Classes in this File Line Coverage Branch Coverage Complexity
GeneticSearch
0%
0/151
0%
0/64
2.658
GeneticSearch$BayesNetRepresentation
0%
0/72
0%
0/58
2.658
 
 1  
 /*
 2  
  *   This program is free software: you can redistribute it and/or modify
 3  
  *   it under the terms of the GNU General Public License as published by
 4  
  *   the Free Software Foundation, either version 3 of the License, or
 5  
  *   (at your option) any later version.
 6  
  *
 7  
  *   This program is distributed in the hope that it will be useful,
 8  
  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 9  
  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 10  
  *   GNU General Public License for more details.
 11  
  *
 12  
  *   You should have received a copy of the GNU General Public License
 13  
  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 14  
  */
 15  
 
 16  
 /*
 17  
  * GeneticSearch.java
 18  
  * Copyright (C) 2004-2012 University of Waikato, Hamilton, New Zealand
 19  
  * 
 20  
  */
 21  
  
 22  
 package weka.classifiers.bayes.net.search.local;
 23  
 
 24  
 import java.util.Enumeration;
 25  
 import java.util.Random;
 26  
 import java.util.Vector;
 27  
 
 28  
 import weka.classifiers.bayes.BayesNet;
 29  
 import weka.classifiers.bayes.net.ParentSet;
 30  
 import weka.core.Instances;
 31  
 import weka.core.Option;
 32  
 import weka.core.RevisionHandler;
 33  
 import weka.core.RevisionUtils;
 34  
 import weka.core.Utils;
 35  
 
 36  
 /** 
 37  
  <!-- globalinfo-start -->
 38  
  * This Bayes Network learning algorithm uses genetic search for finding a well scoring Bayes network structure. Genetic search works by having a population of Bayes network structures and allow them to mutate and apply cross over to get offspring. The best network structure found during the process is returned.
 39  
  * <p/>
 40  
  <!-- globalinfo-end -->
 41  
  *
 42  
  <!-- options-start -->
 43  
  * Valid options are: <p/>
 44  
  * 
 45  
  * <pre> -L &lt;integer&gt;
 46  
  *  Population size</pre>
 47  
  * 
 48  
  * <pre> -A &lt;integer&gt;
 49  
  *  Descendant population size</pre>
 50  
  * 
 51  
  * <pre> -U &lt;integer&gt;
 52  
  *  Number of runs</pre>
 53  
  * 
 54  
  * <pre> -M
 55  
  *  Use mutation.
 56  
  *  (default true)</pre>
 57  
  * 
 58  
  * <pre> -C
 59  
  *  Use cross-over.
 60  
  *  (default true)</pre>
 61  
  * 
 62  
  * <pre> -O
 63  
  *  Use tournament selection (true) or maximum subpopulatin (false).
 64  
  *  (default false)</pre>
 65  
  * 
 66  
  * <pre> -R &lt;seed&gt;
 67  
  *  Random number seed</pre>
 68  
  * 
 69  
  * <pre> -mbc
 70  
  *  Applies a Markov Blanket correction to the network structure, 
 71  
  *  after a network structure is learned. This ensures that all 
 72  
  *  nodes in the network are part of the Markov blanket of the 
 73  
  *  classifier node.</pre>
 74  
  * 
 75  
  * <pre> -S [BAYES|MDL|ENTROPY|AIC|CROSS_CLASSIC|CROSS_BAYES]
 76  
  *  Score type (BAYES, BDeu, MDL, ENTROPY and AIC)</pre>
 77  
  * 
 78  
  <!-- options-end -->
 79  
  * 
 80  
  * @author Remco Bouckaert (rrb@xm.co.nz)
 81  
  * @version $Revision: 8034 $
 82  
  */
 83  0
 public class GeneticSearch 
 84  
     extends LocalScoreSearchAlgorithm {
 85  
 
 86  
     /** for serialization */
 87  
     static final long serialVersionUID = -7037070678911459757L;
 88  
   
 89  
     /** number of runs **/
 90  0
     int m_nRuns = 10;
 91  
 
 92  
         /** size of population **/
 93  0
         int m_nPopulationSize = 10;
 94  
 
 95  
         /** size of descendant population **/
 96  0
         int m_nDescendantPopulationSize = 100;
 97  
 
 98  
         /** use cross-over? **/
 99  0
         boolean m_bUseCrossOver = true;
 100  
 
 101  
         /** use mutation? **/
 102  0
         boolean m_bUseMutation = true;
 103  
         
 104  
         /** use tournament selection or take best sub-population **/
 105  0
         boolean m_bUseTournamentSelection = false;        
 106  
         
 107  
         /** random number seed **/
 108  0
         int m_nSeed = 1;
 109  
         
 110  
         /** random number generator **/
 111  0
         Random m_random = null;
 112  
 
 113  
 
 114  
         /** used in BayesNetRepresentation for efficiently determining
 115  
          * whether a number is square  
 116  
          */
 117  
         static boolean [] g_bIsSquare;
 118  
         
 119  0
         class BayesNetRepresentation implements RevisionHandler {
 120  
           
 121  
                 /** number of nodes in network **/                
 122  0
                 int m_nNodes = 0;
 123  
 
 124  
                 /** bit representation of parent sets 
 125  
                  * m_bits[iTail + iHead * m_nNodes] represents arc iTail->iHead
 126  
                  */
 127  
                 boolean [] m_bits;
 128  
                 
 129  
                 /** score of represented network structure **/
 130  0
                 double m_fScore = 0.0f;
 131  
                 
 132  
                 /** 
 133  
                  * return score of represented network structure
 134  
                  * 
 135  
                  * @return the score
 136  
                  */
 137  
                 public double getScore() {
 138  0
                         return m_fScore;
 139  
                 } // getScore
 140  
 
 141  
                 /** 
 142  
                  * c'tor
 143  
                  * 
 144  
                  * @param nNodes the number of nodes
 145  
                  */
 146  0
                 BayesNetRepresentation (int nNodes) {
 147  0
                         m_nNodes = nNodes;
 148  0
                 } // c'tor
 149  
                 
 150  
                 /** initialize with a random structure by randomly placing
 151  
                  * m_nNodes arcs.
 152  
                  */
 153  
                 public void randomInit() {
 154  
                         do {
 155  0
                                 m_bits = new boolean [m_nNodes * m_nNodes];
 156  0
                                 for (int i = 0; i < m_nNodes; i++) {
 157  
                                         int iPos;
 158  
                                         do {
 159  0
                                                 iPos = m_random.nextInt(m_nNodes * m_nNodes);
 160  0
                                         } while (isSquare(iPos));
 161  0
                                         m_bits[iPos] = true;
 162  
                                 }
 163  0
                         } while (hasCycles());
 164  0
                         calcScore();
 165  0
                 }
 166  
 
 167  
                 /** calculate score of current network representation
 168  
                  * As a side effect, the parent sets are set
 169  
                  */
 170  
                 void calcScore() {
 171  
                         // clear current network
 172  0
                         for (int iNode = 0; iNode < m_nNodes; iNode++) {
 173  0
                                 ParentSet parentSet = m_BayesNet.getParentSet(iNode);
 174  0
                                 while (parentSet.getNrOfParents() > 0) {
 175  0
                                         parentSet.deleteLastParent(m_BayesNet.m_Instances);
 176  
                                 }
 177  
                         }
 178  
                         // insert arrows
 179  0
                         for (int iNode = 0; iNode < m_nNodes; iNode++) {
 180  0
                                 ParentSet parentSet = m_BayesNet.getParentSet(iNode);
 181  0
                                 for (int iNode2 = 0; iNode2 < m_nNodes; iNode2++) {
 182  0
                                         if (m_bits[iNode2 + iNode * m_nNodes]) {
 183  0
                                                 parentSet.addParent(iNode2, m_BayesNet.m_Instances);
 184  
                                         }
 185  
                                 }
 186  
                         }
 187  
                         // calc score
 188  0
                         m_fScore = 0.0;
 189  0
                         for (int iNode = 0; iNode < m_nNodes; iNode++) {
 190  0
                                 m_fScore += calcNodeScore(iNode);
 191  
                         }
 192  0
                 } // calcScore
 193  
 
 194  
                 /** check whether there are cycles in the network
 195  
                  * 
 196  
                  * @return true if a cycle is found, false otherwise
 197  
                  */
 198  
                 public boolean hasCycles() {
 199  
                         // check for cycles
 200  0
                         boolean[] bDone = new boolean[m_nNodes];
 201  0
                         for (int iNode = 0; iNode < m_nNodes; iNode++) {
 202  
 
 203  
                                 // find a node for which all parents are 'done'
 204  0
                                 boolean bFound = false;
 205  
 
 206  0
                                 for (int iNode2 = 0; !bFound && iNode2 < m_nNodes; iNode2++) {
 207  0
                                         if (!bDone[iNode2]) {
 208  0
                                                 boolean bHasNoParents = true;
 209  0
                                                 for (int iParent = 0; iParent < m_nNodes; iParent++) {
 210  0
                                                         if (m_bits[iParent + iNode2 * m_nNodes] && !bDone[iParent]) {
 211  0
                                                                 bHasNoParents = false;
 212  
                                                         }
 213  
                                                 }
 214  0
                                                 if (bHasNoParents) {
 215  0
                                                         bDone[iNode2] = true;
 216  0
                                                         bFound = true;
 217  
                                                 }
 218  
                                         }
 219  
                                 }
 220  0
                                 if (!bFound) {
 221  0
                                         return true;
 222  
                                 }
 223  
                         }
 224  0
                         return false;
 225  
                 } // hasCycles
 226  
 
 227  
                 /** create clone of current object 
 228  
                  * @return cloned object
 229  
                  */
 230  
                 BayesNetRepresentation copy() {
 231  0
                         BayesNetRepresentation b = new BayesNetRepresentation(m_nNodes);
 232  0
                         b.m_bits = new boolean [m_bits.length];
 233  0
                         for (int i = 0; i < m_nNodes * m_nNodes; i++) {
 234  0
                                 b.m_bits[i] = m_bits[i];
 235  
                         }
 236  0
                         b.m_fScore = m_fScore;
 237  0
                         return b;                
 238  
                 } // copy
 239  
 
 240  
                 /** Apply mutation operation to BayesNet
 241  
                  * Calculate score and as a side effect sets BayesNet parent sets.
 242  
                  */
 243  
                 void mutate() {
 244  
                         // flip a bit
 245  
                         do {                                
 246  
                                 int iBit;
 247  
                                 do {
 248  0
                                         iBit = m_random.nextInt(m_nNodes * m_nNodes);
 249  0
                                 } while (isSquare(iBit));
 250  
                                 
 251  0
                                 m_bits[iBit] = !m_bits[iBit];
 252  0
                         } while (hasCycles());
 253  
 
 254  0
                         calcScore();
 255  0
                 } // mutate
 256  
 
 257  
                 /** Apply cross-over operation to BayesNet 
 258  
                  * Calculate score and as a side effect sets BayesNet parent sets.
 259  
                  * @param other BayesNetRepresentation to cross over with
 260  
                  */
 261  
                 void crossOver(BayesNetRepresentation other) {
 262  0
                         boolean [] bits = new boolean [m_bits.length];
 263  0
                         for (int i = 0; i < m_bits.length; i++) {
 264  0
                                 bits[i] = m_bits[i];
 265  
                         }
 266  0
                         int iCrossOverPoint = m_bits.length;
 267  
                         do {
 268  
                                 // restore to original state
 269  0
                                 for (int i = iCrossOverPoint; i < m_bits.length; i++) {
 270  0
                                         m_bits[i] = bits[i];
 271  
                                 }
 272  
                                 // take all bits from cross-over points onwards
 273  0
                                 iCrossOverPoint = m_random.nextInt(m_bits.length);
 274  0
                                 for (int i = iCrossOverPoint; i < m_bits.length; i++) {
 275  0
                                         m_bits[i] = other.m_bits[i];
 276  
                                 }
 277  0
                         } while (hasCycles());
 278  0
                         calcScore();
 279  0
                 } // crossOver
 280  
                                 
 281  
                 /** check if number is square and initialize g_bIsSquare structure
 282  
                  * if necessary
 283  
                  * @param nNum number to check (should be below m_nNodes * m_nNodes)
 284  
                  * @return true if number is square
 285  
                  */
 286  
                 boolean isSquare(int nNum) {
 287  0
                         if (g_bIsSquare == null || g_bIsSquare.length < nNum) {
 288  0
                                 g_bIsSquare = new boolean [m_nNodes * m_nNodes];
 289  0
                                 for (int i = 0; i < m_nNodes; i++) {
 290  0
                                         g_bIsSquare[i * m_nNodes + i] = true;
 291  
                                 }
 292  
                         }
 293  0
                         return g_bIsSquare[nNum];
 294  
                 } // isSquare
 295  
 
 296  
                 /**
 297  
                  * Returns the revision string.
 298  
                  * 
 299  
                  * @return                the revision
 300  
                  */
 301  
                 public String getRevision() {
 302  0
                   return RevisionUtils.extract("$Revision: 8034 $");
 303  
                 }
 304  
         } // class BayesNetRepresentation 
 305  
                     
 306  
         /**
 307  
          * search determines the network structure/graph of the network
 308  
          * with a genetic search algorithm.
 309  
          * 
 310  
          * @param bayesNet the network to use
 311  
          * @param instances the data to use
 312  
          * @throws Exception if population size doesn fit or neither cross-over or mutation was chosen
 313  
          */
 314  
         protected void search(BayesNet bayesNet, Instances instances) throws Exception {
 315  
                 // sanity check
 316  0
                 if (getDescendantPopulationSize() < getPopulationSize()) {
 317  0
                         throw new Exception ("Descendant PopulationSize should be at least Population Size");
 318  
                 }
 319  0
                 if (!getUseCrossOver() && !getUseMutation()) {
 320  0
                         throw new Exception ("At least one of mutation or cross-over should be used");
 321  
                 }
 322  
                 
 323  0
                 m_random = new Random(m_nSeed);
 324  
 
 325  
                 // keeps track of best structure found so far 
 326  
                 BayesNet bestBayesNet;
 327  
                 // keeps track of score pf best structure found so far 
 328  0
                 double fBestScore = 0.0;        
 329  0
                 for (int iAttribute = 0; iAttribute < instances.numAttributes(); iAttribute++) {
 330  0
                         fBestScore += calcNodeScore(iAttribute);
 331  
                 }
 332  
 
 333  
                 // initialize bestBayesNet
 334  0
                 bestBayesNet = new BayesNet();
 335  0
                 bestBayesNet.m_Instances = instances;
 336  0
                 bestBayesNet.initStructure();
 337  0
                 copyParentSets(bestBayesNet, bayesNet);
 338  
                 
 339  
                 
 340  
         // initialize population        
 341  0
                 BayesNetRepresentation  [] population = new BayesNetRepresentation [getPopulationSize()];
 342  0
         for (int i = 0; i < getPopulationSize(); i++) {
 343  0
                 population[i] = new BayesNetRepresentation (instances.numAttributes());
 344  0
                         population[i].randomInit();
 345  0
                         if (population[i].getScore() > fBestScore) {
 346  0
                                 copyParentSets(bestBayesNet, bayesNet);
 347  0
                                 fBestScore = population[i].getScore();
 348  
                                 
 349  
                         }
 350  
         }
 351  
         
 352  
         // go do the search        
 353  0
         for (int iRun = 0; iRun < m_nRuns; iRun++) {
 354  
                 // create descendants
 355  0
                         BayesNetRepresentation  [] descendantPopulation = new BayesNetRepresentation  [getDescendantPopulationSize()];
 356  0
                         for (int i = 0; i < getDescendantPopulationSize(); i++) {
 357  0
                                 descendantPopulation[i] = population[m_random.nextInt(getPopulationSize())].copy();
 358  0
                                 if (getUseMutation()) {
 359  0
                                         if (getUseCrossOver() && m_random.nextBoolean()) {
 360  0
                                                 descendantPopulation[i].crossOver(population[m_random.nextInt(getPopulationSize())]);                                                
 361  
                                         } else {
 362  0
                                                 descendantPopulation[i].mutate();                                                                
 363  
                                         }
 364  
                                 } else {
 365  
                                         // use crossover
 366  0
                                         descendantPopulation[i].crossOver(population[m_random.nextInt(getPopulationSize())]);
 367  
                                 }
 368  
 
 369  0
                                 if (descendantPopulation[i].getScore() > fBestScore) {
 370  0
                                         copyParentSets(bestBayesNet, bayesNet);
 371  0
                                         fBestScore = descendantPopulation[i].getScore();
 372  
                                 }
 373  
                         }
 374  
                         // select new population
 375  0
                         boolean [] bSelected = new boolean [getDescendantPopulationSize()];
 376  0
                         for (int i = 0; i < getPopulationSize(); i++) {
 377  0
                                 int iSelected = 0;
 378  0
                                 if (m_bUseTournamentSelection) {
 379  
                                         // use tournament selection
 380  0
                                         iSelected = m_random.nextInt(getDescendantPopulationSize());
 381  0
                                         while (bSelected[iSelected]) {
 382  0
                                                 iSelected = (iSelected + 1) % getDescendantPopulationSize();
 383  
                                         }
 384  0
                                         int iSelected2 =  m_random.nextInt(getDescendantPopulationSize());
 385  0
                                         while (bSelected[iSelected2]) {
 386  0
                                                 iSelected2 = (iSelected2 + 1) % getDescendantPopulationSize();
 387  
                                         }
 388  0
                                         if (descendantPopulation[iSelected2].getScore() > descendantPopulation[iSelected].getScore()) {
 389  0
                                                 iSelected = iSelected2;
 390  
                                         }
 391  0
                                 } else {
 392  
                                         // find best scoring network in population
 393  0
                                         while (bSelected[iSelected]) {
 394  0
                                                 iSelected++;
 395  
                                         }
 396  0
                                         double fScore = descendantPopulation[iSelected].getScore();
 397  0
                                         for (int j = 0; j < getDescendantPopulationSize(); j++) {
 398  0
                                                 if (!bSelected[j] && descendantPopulation[j].getScore() > fScore) {
 399  0
                                                         fScore = descendantPopulation[j].getScore();
 400  0
                                                         iSelected = j;
 401  
                                                 }
 402  
                                         }
 403  
                                 }
 404  0
                                 population[i] = descendantPopulation[iSelected];
 405  0
                                 bSelected[iSelected] = true;
 406  
                         }
 407  
         }
 408  
         
 409  
         // restore current network to best network
 410  0
                 copyParentSets(bayesNet, bestBayesNet);
 411  
                 
 412  
                 // free up memory
 413  0
                 bestBayesNet = null;
 414  0
     } // search
 415  
 
 416  
 
 417  
         /** copyParentSets copies parent sets of source to dest BayesNet
 418  
          * @param dest destination network
 419  
          * @param source source network
 420  
          */
 421  
         void copyParentSets(BayesNet dest, BayesNet source) {
 422  0
                 int nNodes = source.getNrOfNodes();
 423  
                 // clear parent set first
 424  0
                 for (int iNode = 0; iNode < nNodes; iNode++) {
 425  0
                         dest.getParentSet(iNode).copy(source.getParentSet(iNode));
 426  
                 }                
 427  0
         } // CopyParentSets
 428  
 
 429  
     /**
 430  
     * @return number of runs
 431  
     */
 432  
     public int getRuns() {
 433  0
         return m_nRuns;
 434  
     } // getRuns
 435  
 
 436  
     /**
 437  
      * Sets the number of runs
 438  
      * @param nRuns The number of runs to set
 439  
      */
 440  
     public void setRuns(int nRuns) {
 441  0
         m_nRuns = nRuns;
 442  0
     } // setRuns
 443  
 
 444  
         /**
 445  
          * Returns an enumeration describing the available options.
 446  
          *
 447  
          * @return an enumeration of all the available options.
 448  
          */
 449  
         public Enumeration listOptions() {
 450  0
                 Vector newVector = new Vector(7);
 451  
 
 452  0
                 newVector.addElement(new Option("\tPopulation size", "L", 1, "-L <integer>"));
 453  0
                 newVector.addElement(new Option("\tDescendant population size", "A", 1, "-A <integer>"));
 454  0
                 newVector.addElement(new Option("\tNumber of runs", "U", 1, "-U <integer>"));
 455  0
                 newVector.addElement(new Option("\tUse mutation.\n\t(default true)", "M", 0, "-M"));
 456  0
                 newVector.addElement(new Option("\tUse cross-over.\n\t(default true)", "C", 0, "-C"));
 457  0
                 newVector.addElement(new Option("\tUse tournament selection (true) or maximum subpopulatin (false).\n\t(default false)", "O", 0, "-O"));
 458  0
                 newVector.addElement(new Option("\tRandom number seed", "R", 1, "-R <seed>"));
 459  
 
 460  0
                 Enumeration enu = super.listOptions();
 461  0
                 while (enu.hasMoreElements()) {
 462  0
                         newVector.addElement(enu.nextElement());
 463  
                 }
 464  0
                 return newVector.elements();
 465  
         } // listOptions
 466  
 
 467  
         /**
 468  
          * Parses a given list of options. <p/>
 469  
          *
 470  
          <!-- options-start -->
 471  
          * Valid options are: <p/>
 472  
          * 
 473  
          * <pre> -L &lt;integer&gt;
 474  
          *  Population size</pre>
 475  
          * 
 476  
          * <pre> -A &lt;integer&gt;
 477  
          *  Descendant population size</pre>
 478  
          * 
 479  
          * <pre> -U &lt;integer&gt;
 480  
          *  Number of runs</pre>
 481  
          * 
 482  
          * <pre> -M
 483  
          *  Use mutation.
 484  
          *  (default true)</pre>
 485  
          * 
 486  
          * <pre> -C
 487  
          *  Use cross-over.
 488  
          *  (default true)</pre>
 489  
          * 
 490  
          * <pre> -O
 491  
          *  Use tournament selection (true) or maximum subpopulatin (false).
 492  
          *  (default false)</pre>
 493  
          * 
 494  
          * <pre> -R &lt;seed&gt;
 495  
          *  Random number seed</pre>
 496  
          * 
 497  
          * <pre> -mbc
 498  
          *  Applies a Markov Blanket correction to the network structure, 
 499  
          *  after a network structure is learned. This ensures that all 
 500  
          *  nodes in the network are part of the Markov blanket of the 
 501  
          *  classifier node.</pre>
 502  
          * 
 503  
          * <pre> -S [BAYES|MDL|ENTROPY|AIC|CROSS_CLASSIC|CROSS_BAYES]
 504  
          *  Score type (BAYES, BDeu, MDL, ENTROPY and AIC)</pre>
 505  
          * 
 506  
          <!-- options-end -->
 507  
          *
 508  
          * @param options the list of options as an array of strings
 509  
          * @throws Exception if an option is not supported
 510  
          */
 511  
         public void setOptions(String[] options) throws Exception {
 512  0
                 String sPopulationSize = Utils.getOption('L', options);
 513  0
                 if (sPopulationSize.length() != 0) {
 514  0
                         setPopulationSize(Integer.parseInt(sPopulationSize));
 515  
                 }
 516  0
                 String sDescendantPopulationSize = Utils.getOption('A', options);
 517  0
                 if (sDescendantPopulationSize.length() != 0) {
 518  0
                         setDescendantPopulationSize(Integer.parseInt(sDescendantPopulationSize));
 519  
                 }
 520  0
                 String sRuns = Utils.getOption('U', options);
 521  0
                 if (sRuns.length() != 0) {
 522  0
                         setRuns(Integer.parseInt(sRuns));
 523  
                 }
 524  0
                 String sSeed = Utils.getOption('R', options);
 525  0
                 if (sSeed.length() != 0) {
 526  0
                         setSeed(Integer.parseInt(sSeed));
 527  
                 }
 528  0
                 setUseMutation(Utils.getFlag('M', options));
 529  0
                 setUseCrossOver(Utils.getFlag('C', options));
 530  0
                 setUseTournamentSelection(Utils.getFlag('O', options));
 531  
                 
 532  0
                 super.setOptions(options);
 533  0
         } // setOptions
 534  
 
 535  
         /**
 536  
          * Gets the current settings of the search algorithm.
 537  
          *
 538  
          * @return an array of strings suitable for passing to setOptions
 539  
          */
 540  
         public String[] getOptions() {
 541  0
                 String[] superOptions = super.getOptions();
 542  0
                 String[] options = new String[11 + superOptions.length];
 543  0
                 int current = 0;
 544  
                 
 545  0
                 options[current++] = "-L";
 546  0
                 options[current++] = "" + getPopulationSize();
 547  
 
 548  0
                 options[current++] = "-A";
 549  0
                 options[current++] = "" + getDescendantPopulationSize();
 550  
 
 551  0
                 options[current++] = "-U";
 552  0
                 options[current++] = "" + getRuns();
 553  
 
 554  0
                 options[current++] = "-R";
 555  0
                 options[current++] = "" + getSeed();
 556  
 
 557  0
                 if (getUseMutation()) {
 558  0
                   options[current++] = "-M";
 559  
                 }
 560  0
                 if (getUseCrossOver()) {
 561  0
                   options[current++] = "-C";
 562  
                 }
 563  0
                 if (getUseTournamentSelection()) {
 564  0
                   options[current++] = "-O";
 565  
                 }
 566  
 
 567  
                 // insert options from parent class
 568  0
                 for (int iOption = 0; iOption < superOptions.length; iOption++) {
 569  0
                         options[current++] = superOptions[iOption];
 570  
                 }
 571  
 
 572  
                 // Fill up rest with empty strings, not nulls!
 573  0
                 while (current < options.length) {
 574  0
                         options[current++] = "";
 575  
                 }
 576  0
                 return options;
 577  
         } // getOptions
 578  
 
 579  
         /**
 580  
          * @return whether cross-over is used
 581  
          */
 582  
         public boolean getUseCrossOver() {
 583  0
                 return m_bUseCrossOver;
 584  
         }
 585  
 
 586  
         /**
 587  
          * @return whether mutation is used
 588  
          */
 589  
         public boolean getUseMutation() {
 590  0
                 return m_bUseMutation;
 591  
         }
 592  
 
 593  
         /**
 594  
          * @return descendant population size
 595  
          */
 596  
         public int getDescendantPopulationSize() {
 597  0
                 return m_nDescendantPopulationSize;
 598  
         }
 599  
 
 600  
         /**
 601  
          * @return population size
 602  
          */
 603  
         public int getPopulationSize() {
 604  0
                 return m_nPopulationSize;
 605  
         }
 606  
 
 607  
         /**
 608  
          * @param bUseCrossOver sets whether cross-over is used
 609  
          */
 610  
         public void setUseCrossOver(boolean bUseCrossOver) {
 611  0
                 m_bUseCrossOver = bUseCrossOver;
 612  0
         }
 613  
 
 614  
         /**
 615  
          * @param bUseMutation sets whether mutation is used
 616  
          */
 617  
         public void setUseMutation(boolean bUseMutation) {
 618  0
                 m_bUseMutation = bUseMutation;
 619  0
         }
 620  
 
 621  
         /**
 622  
          * @return whether Tournament Selection (true) or Maximum Sub-Population (false) should be used
 623  
          */
 624  
         public boolean getUseTournamentSelection() {
 625  0
                 return m_bUseTournamentSelection;
 626  
         }
 627  
 
 628  
         /**
 629  
          * @param bUseTournamentSelection sets whether Tournament Selection or Maximum Sub-Population should be used
 630  
          */
 631  
         public void setUseTournamentSelection(boolean bUseTournamentSelection) {
 632  0
                 m_bUseTournamentSelection = bUseTournamentSelection;
 633  0
         }
 634  
 
 635  
         /**
 636  
          * @param iDescendantPopulationSize sets descendant population size
 637  
          */
 638  
         public void setDescendantPopulationSize(int iDescendantPopulationSize) {
 639  0
                 m_nDescendantPopulationSize = iDescendantPopulationSize;
 640  0
         }
 641  
 
 642  
         /**
 643  
          * @param iPopulationSize sets population size
 644  
          */
 645  
         public void setPopulationSize(int iPopulationSize) {
 646  0
                 m_nPopulationSize = iPopulationSize;
 647  0
         }
 648  
 
 649  
         /**
 650  
         * @return random number seed
 651  
         */
 652  
         public int getSeed() {
 653  0
                 return m_nSeed;
 654  
         } // getSeed
 655  
 
 656  
         /**
 657  
          * Sets the random number seed
 658  
          * @param nSeed The number of the seed to set
 659  
          */
 660  
         public void setSeed(int nSeed) {
 661  0
                 m_nSeed = nSeed;
 662  0
         } // setSeed
 663  
 
 664  
         /**
 665  
          * This will return a string describing the classifier.
 666  
          * @return The string.
 667  
          */
 668  
         public String globalInfo() {
 669  0
                 return "This Bayes Network learning algorithm uses genetic search for finding a well scoring " +
 670  
                 "Bayes network structure. Genetic search works by having a population of Bayes network structures " +
 671  
                 "and allow them to mutate and apply cross over to get offspring. The best network structure " +
 672  
                 "found during the process is returned.";
 673  
         } // globalInfo
 674  
         
 675  
         /**
 676  
          * @return a string to describe the Runs option.
 677  
          */
 678  
         public String runsTipText() {
 679  0
           return "Sets the number of generations of Bayes network structure populations.";
 680  
         } // runsTipText
 681  
         
 682  
         /**
 683  
          * @return a string to describe the Seed option.
 684  
          */
 685  
         public String seedTipText() {
 686  0
           return "Initialization value for random number generator." +
 687  
           " Setting the seed allows replicability of experiments.";
 688  
         } // seedTipText
 689  
 
 690  
         /**
 691  
          * @return a string to describe the Population Size option.
 692  
          */
 693  
         public String populationSizeTipText() {
 694  0
           return "Sets the size of the population of network structures that is selected each generation.";
 695  
         } // populationSizeTipText
 696  
 
 697  
         /**
 698  
          * @return a string to describe the Descendant Population Size option.
 699  
          */
 700  
         public String descendantPopulationSizeTipText() {
 701  0
           return "Sets the size of the population of descendants that is created each generation.";
 702  
         } // descendantPopulationSizeTipText
 703  
 
 704  
         /**
 705  
          * @return a string to describe the Use Mutation option.
 706  
          */
 707  
         public String useMutationTipText() {
 708  0
                 return "Determines whether mutation is allowed. Mutation flips a bit in the bit " +
 709  
                         "representation of the network structure. At least one of mutation or cross-over " +
 710  
                         "should be used.";
 711  
         } // useMutationTipText
 712  
 
 713  
         /**
 714  
          * @return a string to describe the Use Cross-Over option.
 715  
          */
 716  
         public String useCrossOverTipText() {
 717  0
                 return "Determines whether cross-over is allowed. Cross over combined the bit " +
 718  
                         "representations of network structure by taking a random first k bits of one" +
 719  
                         "and adding the remainder of the other. At least one of mutation or cross-over " +
 720  
                         "should be used.";
 721  
         } // useCrossOverTipText
 722  
 
 723  
         /**
 724  
          * @return a string to describe the Use Tournament Selection option.
 725  
          */
 726  
         public String useTournamentSelectionTipText() {
 727  0
                 return "Determines the method of selecting a population. When set to true, tournament " +
 728  
                         "selection is used (pick two at random and the highest is allowed to continue). " +
 729  
                         "When set to false, the top scoring network structures are selected.";
 730  
         } // useTournamentSelectionTipText
 731  
 
 732  
         /**
 733  
          * Returns the revision string.
 734  
          * 
 735  
          * @return                the revision
 736  
          */
 737  
         public String getRevision() {
 738  0
           return RevisionUtils.extract("$Revision: 8034 $");
 739  
         }
 740  
 } // GeneticSearch