source: tags/MetisMQIDemo/src/main/java/weka/classifiers/bayes/net/search/global/GeneticSearch.java

Last change on this file was 29, checked in by gnappo, 15 years ago

Taggata versione per la demo e aggiunto branch.

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