| 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 |  * LAGDHillClimber.java | 
|---|
| 19 |  * Copyright (C) 2005 Manuel Neubach | 
|---|
| 20 |  *  | 
|---|
| 21 |  */ | 
|---|
| 22 |  | 
|---|
| 23 | package weka.classifiers.bayes.net.search.local; | 
|---|
| 24 |  | 
|---|
| 25 | import weka.classifiers.bayes.BayesNet; | 
|---|
| 26 | import weka.core.Instances; | 
|---|
| 27 | import weka.core.Option; | 
|---|
| 28 | import weka.core.RevisionUtils; | 
|---|
| 29 | import weka.core.Utils; | 
|---|
| 30 |  | 
|---|
| 31 | import java.util.Enumeration; | 
|---|
| 32 | import java.util.Vector; | 
|---|
| 33 |  | 
|---|
| 34 | /**  | 
|---|
| 35 |  <!-- globalinfo-start --> | 
|---|
| 36 |  * This Bayes Network learning algorithm uses a Look Ahead Hill Climbing algorithm called LAGD Hill Climbing. Unlike Greedy Hill Climbing it doesn't calculate a best greedy operation (adding, deleting or reversing an arc) but a sequence of nrOfLookAheadSteps operations, which leads to a network structure whose score is most likely higher in comparison to the network obtained by performing a sequence of nrOfLookAheadSteps greedy operations. The search is not restricted by an order on the variables (unlike K2). The difference with B and B2 is that this hill climber also considers arrows part of the naive Bayes structure for deletion. | 
|---|
| 37 |  * <p/> | 
|---|
| 38 |  <!-- globalinfo-end --> | 
|---|
| 39 |  * | 
|---|
| 40 |  <!-- options-start --> | 
|---|
| 41 |  * Valid options are: <p/> | 
|---|
| 42 |  *  | 
|---|
| 43 |  * <pre> -L <nr of look ahead steps> | 
|---|
| 44 |  *  Look Ahead Depth</pre> | 
|---|
| 45 |  *  | 
|---|
| 46 |  * <pre> -G <nr of good operations> | 
|---|
| 47 |  *  Nr of Good Operations</pre> | 
|---|
| 48 |  *  | 
|---|
| 49 |  * <pre> -P <nr of parents> | 
|---|
| 50 |  *  Maximum number of parents</pre> | 
|---|
| 51 |  *  | 
|---|
| 52 |  * <pre> -R | 
|---|
| 53 |  *  Use arc reversal operation. | 
|---|
| 54 |  *  (default false)</pre> | 
|---|
| 55 |  *  | 
|---|
| 56 |  * <pre> -N | 
|---|
| 57 |  *  Initial structure is empty (instead of Naive Bayes)</pre> | 
|---|
| 58 |  *  | 
|---|
| 59 |  * <pre> -mbc | 
|---|
| 60 |  *  Applies a Markov Blanket correction to the network structure,  | 
|---|
| 61 |  *  after a network structure is learned. This ensures that all  | 
|---|
| 62 |  *  nodes in the network are part of the Markov blanket of the  | 
|---|
| 63 |  *  classifier node.</pre> | 
|---|
| 64 |  *  | 
|---|
| 65 |  * <pre> -S [BAYES|MDL|ENTROPY|AIC|CROSS_CLASSIC|CROSS_BAYES] | 
|---|
| 66 |  *  Score type (BAYES, BDeu, MDL, ENTROPY and AIC)</pre> | 
|---|
| 67 |  *  | 
|---|
| 68 |  <!-- options-end --> | 
|---|
| 69 |  *  | 
|---|
| 70 |  * @author Manuel Neubach | 
|---|
| 71 |  * @version $Revision: 1.7 $ | 
|---|
| 72 |  */ | 
|---|
| 73 | public class LAGDHillClimber  | 
|---|
| 74 |     extends HillClimber { | 
|---|
| 75 |    | 
|---|
| 76 |     /** for serialization */ | 
|---|
| 77 |     static final long serialVersionUID = 7217437499439184344L; | 
|---|
| 78 |  | 
|---|
| 79 |     /** Number of Look Ahead Steps **/ | 
|---|
| 80 |     int m_nNrOfLookAheadSteps = 2; | 
|---|
| 81 |  | 
|---|
| 82 |     /** Number of Good Operations per Step **/ | 
|---|
| 83 |     int m_nNrOfGoodOperations = 5; | 
|---|
| 84 |  | 
|---|
| 85 |    /** | 
|---|
| 86 |      * search determines the network structure/graph of the network | 
|---|
| 87 |      *  | 
|---|
| 88 |      * @param bayesNet the network | 
|---|
| 89 |      * @param instances the data to use | 
|---|
| 90 |      * @throws Exception if something goes wrong | 
|---|
| 91 |      */ | 
|---|
| 92 |    protected void search(BayesNet bayesNet, Instances instances) throws Exception { | 
|---|
| 93 |         int k=m_nNrOfLookAheadSteps;  // Number of Look Ahead Steps | 
|---|
| 94 |         int l=m_nNrOfGoodOperations; // Number of Good Operations per step | 
|---|
| 95 |         lookAheadInGoodDirectionsSearch(bayesNet, instances, k, l); | 
|---|
| 96 |    } // search | 
|---|
| 97 |  | 
|---|
| 98 |  | 
|---|
| 99 |    /** | 
|---|
| 100 |     * lookAheadInGoodDirectionsSearch determines the network structure/graph of the network | 
|---|
| 101 |     * with best score according to LAGD Hill Climbing | 
|---|
| 102 |     *  | 
|---|
| 103 |     * @param bayesNet the network | 
|---|
| 104 |     * @param instances the data to use | 
|---|
| 105 |     * @param nrOfLookAheadSteps | 
|---|
| 106 |     * @param nrOfGoodOperations | 
|---|
| 107 |     * @throws Exception if something goes wrong | 
|---|
| 108 |     */ | 
|---|
| 109 |     protected void lookAheadInGoodDirectionsSearch(BayesNet bayesNet, Instances instances, int nrOfLookAheadSteps, int nrOfGoodOperations) throws Exception { | 
|---|
| 110 |          System.out.println("Initializing Cache"); | 
|---|
| 111 |          initCache(bayesNet, instances); | 
|---|
| 112 |  | 
|---|
| 113 |          while (nrOfLookAheadSteps>1) {          | 
|---|
| 114 |             System.out.println("Look Ahead Depth: "+nrOfLookAheadSteps); | 
|---|
| 115 |             boolean legalSequence = true; | 
|---|
| 116 |             double sequenceDeltaScore = 0; | 
|---|
| 117 |             Operation [] bestOperation=new Operation [nrOfLookAheadSteps]; | 
|---|
| 118 |           | 
|---|
| 119 |             bestOperation = getOptimalOperations(bayesNet, instances, nrOfLookAheadSteps, nrOfGoodOperations); | 
|---|
| 120 |             for (int i = 0; i < nrOfLookAheadSteps; i++) { | 
|---|
| 121 |                if (bestOperation [i] == null) { | 
|---|
| 122 |                   legalSequence=false; | 
|---|
| 123 |                } else { | 
|---|
| 124 |                   sequenceDeltaScore += bestOperation [i].m_fDeltaScore; | 
|---|
| 125 |                } | 
|---|
| 126 |             } | 
|---|
| 127 |             while (legalSequence && sequenceDeltaScore > 0) { | 
|---|
| 128 |                System.out.println("Next Iteration.........................."); | 
|---|
| 129 |                for (int i = 0; i < nrOfLookAheadSteps; i++) { | 
|---|
| 130 |                   performOperation(bayesNet, instances,bestOperation [i]); | 
|---|
| 131 |                } | 
|---|
| 132 |                bestOperation = getOptimalOperations(bayesNet, instances, nrOfLookAheadSteps, nrOfGoodOperations); | 
|---|
| 133 |                sequenceDeltaScore = 0; | 
|---|
| 134 |                for (int i = 0; i < nrOfLookAheadSteps; i++) { | 
|---|
| 135 |                   if (bestOperation [i] != null) { | 
|---|
| 136 |                      System.out.println(bestOperation [i].m_nOperation + " " + bestOperation [i].m_nHead + " " + bestOperation [i].m_nTail); | 
|---|
| 137 |                      sequenceDeltaScore += bestOperation [i].m_fDeltaScore; | 
|---|
| 138 |                   } else { | 
|---|
| 139 |                      legalSequence = false; | 
|---|
| 140 |  | 
|---|
| 141 |                   } | 
|---|
| 142 |                   System.out.println("DeltaScore: "+sequenceDeltaScore); | 
|---|
| 143 |                } | 
|---|
| 144 |             } | 
|---|
| 145 |             --nrOfLookAheadSteps; | 
|---|
| 146 |          } | 
|---|
| 147 |  | 
|---|
| 148 |          /** last steps with greedy HC **/           | 
|---|
| 149 |          Operation oOperation = getOptimalOperation(bayesNet, instances); | 
|---|
| 150 |          while ((oOperation != null) && (oOperation.m_fDeltaScore > 0)) { | 
|---|
| 151 |             performOperation(bayesNet, instances, oOperation); | 
|---|
| 152 |             System.out.println("Performing last greedy steps"); | 
|---|
| 153 |             oOperation = getOptimalOperation(bayesNet, instances); | 
|---|
| 154 |          }                | 
|---|
| 155 |          // free up memory | 
|---|
| 156 |          m_Cache = null; | 
|---|
| 157 |     } // lookAheadInGoodDirectionsSearch | 
|---|
| 158 |  | 
|---|
| 159 |     /** | 
|---|
| 160 |       * getAntiOperation determines the Operation, which is needed to cancel oOperation | 
|---|
| 161 |       *  | 
|---|
| 162 |       * @param oOperation Operation to cancel | 
|---|
| 163 |       * @return antiOperation to oOperation | 
|---|
| 164 |       * @throws Exception if something goes wrong | 
|---|
| 165 |       */ | 
|---|
| 166 |     protected Operation getAntiOperation(Operation oOperation) throws Exception { | 
|---|
| 167 |         if (oOperation.m_nOperation == Operation.OPERATION_ADD) | 
|---|
| 168 |            return (new Operation (oOperation.m_nTail, oOperation.m_nHead, Operation.OPERATION_DEL)); | 
|---|
| 169 |         else { | 
|---|
| 170 |            if (oOperation.m_nOperation == Operation.OPERATION_DEL) | 
|---|
| 171 |               return (new Operation (oOperation.m_nTail, oOperation.m_nHead, Operation.OPERATION_ADD)); | 
|---|
| 172 |            else { | 
|---|
| 173 |               return (new Operation (oOperation.m_nHead, oOperation.m_nTail, Operation.OPERATION_REVERSE)); | 
|---|
| 174 |            } | 
|---|
| 175 |          } | 
|---|
| 176 |     } // getAntiOperation | 
|---|
| 177 |  | 
|---|
| 178 |  | 
|---|
| 179 |     /** | 
|---|
| 180 |       * getGoodOperations determines the nrOfGoodOperations best Operations, which are considered for | 
|---|
| 181 |       * the calculation of an optimal operationsequence | 
|---|
| 182 |       * @param bayesNet Bayes network to apply operation on | 
|---|
| 183 |       * @param instances data set to learn from | 
|---|
| 184 |       * @param nrOfGoodOperations number of good operations to consider | 
|---|
| 185 |       * @return good operations to consider | 
|---|
| 186 |       * @throws Exception if something goes wrong | 
|---|
| 187 |       **/ | 
|---|
| 188 |     protected Operation [] getGoodOperations(BayesNet bayesNet, Instances instances, int nrOfGoodOperations) throws Exception { | 
|---|
| 189 |                 Operation [] goodOperations=new Operation [nrOfGoodOperations]; | 
|---|
| 190 |                 for (int i = 0; i < nrOfGoodOperations; i++) { | 
|---|
| 191 |                    goodOperations [i] = getOptimalOperation(bayesNet, instances); | 
|---|
| 192 |                    if (goodOperations[i] != null) { | 
|---|
| 193 |                       m_Cache.put(goodOperations [i], -1E100); | 
|---|
| 194 |                    } else i=nrOfGoodOperations; | 
|---|
| 195 |                 } | 
|---|
| 196 |                 for (int i = 0; i < nrOfGoodOperations; i++) { | 
|---|
| 197 |                    if (goodOperations[i] != null) { | 
|---|
| 198 |                       if (goodOperations [i].m_nOperation!=Operation.OPERATION_REVERSE) { | 
|---|
| 199 |                          m_Cache.put(goodOperations [i], goodOperations [i].m_fDeltaScore); | 
|---|
| 200 |                       } else { | 
|---|
| 201 |                          m_Cache.put(goodOperations [i], goodOperations [i].m_fDeltaScore - m_Cache.m_fDeltaScoreAdd[goodOperations[i].m_nHead] [goodOperations [i].m_nTail]); | 
|---|
| 202 |                       } | 
|---|
| 203 |                    } else i=nrOfGoodOperations; | 
|---|
| 204 |                 } | 
|---|
| 205 |                 return goodOperations; | 
|---|
| 206 |     } // getGoodOperations | 
|---|
| 207 |  | 
|---|
| 208 |     /** | 
|---|
| 209 |       * getOptimalOperations determines an optimal operationsequence in respect of the parameters  | 
|---|
| 210 |       * nrOfLookAheadSteps and nrOfGoodOperations | 
|---|
| 211 |       * @param bayesNet Bayes network to apply operation on | 
|---|
| 212 |       * @param instances data set to learn from | 
|---|
| 213 |       * @param nrOfLookAheadSteps number of lood ahead steps to use | 
|---|
| 214 |       * @param nrOfGoodOperations number of good operations to consider | 
|---|
| 215 |       * @return optimal sequence of operations in respect to nrOfLookAheadSteps and nrOfGoodOperations | 
|---|
| 216 |       * @throws Exception if something goes wrong | 
|---|
| 217 |       **/ | 
|---|
| 218 |     protected Operation [] getOptimalOperations(BayesNet bayesNet, Instances instances, int nrOfLookAheadSteps, int nrOfGoodOperations) throws Exception { | 
|---|
| 219 |        if (nrOfLookAheadSteps == 1) { // Abbruch der Rekursion | 
|---|
| 220 |           Operation [] bestOperation = new Operation [1]; | 
|---|
| 221 |           bestOperation [0] = getOptimalOperation(bayesNet, instances); | 
|---|
| 222 |           return(bestOperation);  // Abbruch der Rekursion | 
|---|
| 223 |        } else { | 
|---|
| 224 |           double bestDeltaScore = 0; | 
|---|
| 225 |           double currentDeltaScore = 0; | 
|---|
| 226 |           Operation [] bestOperation = new Operation [nrOfLookAheadSteps]; | 
|---|
| 227 |           Operation [] goodOperations = new Operation [nrOfGoodOperations]; | 
|---|
| 228 |           Operation [] tempOperation = new Operation [nrOfLookAheadSteps-1]; | 
|---|
| 229 |           goodOperations = getGoodOperations(bayesNet, instances, nrOfGoodOperations); | 
|---|
| 230 |           for (int i = 0; i < nrOfGoodOperations; i++) { | 
|---|
| 231 |            if (goodOperations[i] != null) { | 
|---|
| 232 |              performOperation(bayesNet, instances, goodOperations [i]); | 
|---|
| 233 |              tempOperation = getOptimalOperations(bayesNet, instances, nrOfLookAheadSteps-1, nrOfGoodOperations); // rekursiver Abstieg | 
|---|
| 234 |              currentDeltaScore = goodOperations [i].m_fDeltaScore; | 
|---|
| 235 |              for (int j = 0; j < nrOfLookAheadSteps-1; j++) { | 
|---|
| 236 |                 if (tempOperation [j] != null) { | 
|---|
| 237 |                    currentDeltaScore += tempOperation [j].m_fDeltaScore; | 
|---|
| 238 |                 } | 
|---|
| 239 |              } | 
|---|
| 240 |              performOperation(bayesNet, instances, getAntiOperation(goodOperations [i])); | 
|---|
| 241 |                       if (currentDeltaScore > bestDeltaScore) { | 
|---|
| 242 |                         bestDeltaScore = currentDeltaScore; | 
|---|
| 243 |                         bestOperation [0] = goodOperations [i]; | 
|---|
| 244 |                         for (int j = 1; j < nrOfLookAheadSteps; j++) { | 
|---|
| 245 |                           bestOperation [j] = tempOperation [j-1]; | 
|---|
| 246 |                         } | 
|---|
| 247 |                     } | 
|---|
| 248 |             } else i=nrOfGoodOperations; | 
|---|
| 249 |            } | 
|---|
| 250 |            return(bestOperation); | 
|---|
| 251 |        } | 
|---|
| 252 |     } // getOptimalOperations | 
|---|
| 253 |  | 
|---|
| 254 |  | 
|---|
| 255 |         /** | 
|---|
| 256 |          * Sets the max number of parents | 
|---|
| 257 |          * | 
|---|
| 258 |          * @param nMaxNrOfParents the max number of parents | 
|---|
| 259 |          */ | 
|---|
| 260 |         public void setMaxNrOfParents(int nMaxNrOfParents) { | 
|---|
| 261 |           m_nMaxNrOfParents = nMaxNrOfParents; | 
|---|
| 262 |         }  | 
|---|
| 263 |  | 
|---|
| 264 |         /** | 
|---|
| 265 |          * Gets the max number of parents. | 
|---|
| 266 |          * | 
|---|
| 267 |          * @return the max number of parents | 
|---|
| 268 |          */ | 
|---|
| 269 |         public int getMaxNrOfParents() { | 
|---|
| 270 |           return m_nMaxNrOfParents; | 
|---|
| 271 |         }  | 
|---|
| 272 |  | 
|---|
| 273 |         /** | 
|---|
| 274 |          * Sets the number of look-ahead steps | 
|---|
| 275 |          * | 
|---|
| 276 |          * @param nNrOfLookAheadSteps the number of look-ahead steps | 
|---|
| 277 |          */ | 
|---|
| 278 |         public void setNrOfLookAheadSteps(int nNrOfLookAheadSteps) { | 
|---|
| 279 |           m_nNrOfLookAheadSteps = nNrOfLookAheadSteps; | 
|---|
| 280 |         }  | 
|---|
| 281 |  | 
|---|
| 282 |         /** | 
|---|
| 283 |          * Gets the number of look-ahead steps | 
|---|
| 284 |          * | 
|---|
| 285 |          * @return the number of look-ahead step | 
|---|
| 286 |          */ | 
|---|
| 287 |         public int getNrOfLookAheadSteps() { | 
|---|
| 288 |           return m_nNrOfLookAheadSteps; | 
|---|
| 289 |         }  | 
|---|
| 290 |  | 
|---|
| 291 |         /** | 
|---|
| 292 |          * Sets the number of "good operations" | 
|---|
| 293 |          * | 
|---|
| 294 |          * @param nNrOfGoodOperations the number of "good operations" | 
|---|
| 295 |          */ | 
|---|
| 296 |         public void setNrOfGoodOperations(int nNrOfGoodOperations) { | 
|---|
| 297 |           m_nNrOfGoodOperations = nNrOfGoodOperations; | 
|---|
| 298 |         }  | 
|---|
| 299 |  | 
|---|
| 300 |         /** | 
|---|
| 301 |          * Gets the number of "good operations" | 
|---|
| 302 |          * | 
|---|
| 303 |          * @return the number of "good operations" | 
|---|
| 304 |          */ | 
|---|
| 305 |         public int getNrOfGoodOperations() { | 
|---|
| 306 |           return m_nNrOfGoodOperations; | 
|---|
| 307 |         }  | 
|---|
| 308 |  | 
|---|
| 309 |  | 
|---|
| 310 |         /** | 
|---|
| 311 |          * Returns an enumeration describing the available options. | 
|---|
| 312 |          * | 
|---|
| 313 |          * @return an enumeration of all the available options. | 
|---|
| 314 |          */ | 
|---|
| 315 |         public Enumeration listOptions() { | 
|---|
| 316 |                 Vector newVector = new Vector(); | 
|---|
| 317 |  | 
|---|
| 318 |                 newVector.addElement(new Option("\tLook Ahead Depth", "L", 2, "-L <nr of look ahead steps>")); | 
|---|
| 319 |                 newVector.addElement(new Option("\tNr of Good Operations", "G", 5, "-G <nr of good operations>")); | 
|---|
| 320 |  | 
|---|
| 321 |                 Enumeration enm = super.listOptions(); | 
|---|
| 322 |                 while (enm.hasMoreElements()) { | 
|---|
| 323 |                         newVector.addElement(enm.nextElement()); | 
|---|
| 324 |                 } | 
|---|
| 325 |                 return newVector.elements(); | 
|---|
| 326 |         } // listOptions | 
|---|
| 327 |  | 
|---|
| 328 |         /** | 
|---|
| 329 |          * Parses a given list of options. Valid options are:<p> | 
|---|
| 330 |          * | 
|---|
| 331 |          <!-- options-start --> | 
|---|
| 332 |          * Valid options are: <p/> | 
|---|
| 333 |          *  | 
|---|
| 334 |          * <pre> -L <nr of look ahead steps> | 
|---|
| 335 |          *  Look Ahead Depth</pre> | 
|---|
| 336 |          *  | 
|---|
| 337 |          * <pre> -G <nr of good operations> | 
|---|
| 338 |          *  Nr of Good Operations</pre> | 
|---|
| 339 |          *  | 
|---|
| 340 |          * <pre> -P <nr of parents> | 
|---|
| 341 |          *  Maximum number of parents</pre> | 
|---|
| 342 |          *  | 
|---|
| 343 |          * <pre> -R | 
|---|
| 344 |          *  Use arc reversal operation. | 
|---|
| 345 |          *  (default false)</pre> | 
|---|
| 346 |          *  | 
|---|
| 347 |          * <pre> -N | 
|---|
| 348 |          *  Initial structure is empty (instead of Naive Bayes)</pre> | 
|---|
| 349 |          *  | 
|---|
| 350 |          * <pre> -mbc | 
|---|
| 351 |          *  Applies a Markov Blanket correction to the network structure,  | 
|---|
| 352 |          *  after a network structure is learned. This ensures that all  | 
|---|
| 353 |          *  nodes in the network are part of the Markov blanket of the  | 
|---|
| 354 |          *  classifier node.</pre> | 
|---|
| 355 |          *  | 
|---|
| 356 |          * <pre> -S [BAYES|MDL|ENTROPY|AIC|CROSS_CLASSIC|CROSS_BAYES] | 
|---|
| 357 |          *  Score type (BAYES, BDeu, MDL, ENTROPY and AIC)</pre> | 
|---|
| 358 |          *  | 
|---|
| 359 |          <!-- options-end --> | 
|---|
| 360 |          * | 
|---|
| 361 |          * @param options the list of options as an array of strings | 
|---|
| 362 |          * @throws Exception if an option is not supported | 
|---|
| 363 |          */ | 
|---|
| 364 |         public void setOptions(String[] options) throws Exception { | 
|---|
| 365 |                 String sNrOfLookAheadSteps = Utils.getOption('L', options); | 
|---|
| 366 |                 if (sNrOfLookAheadSteps.length() != 0) { | 
|---|
| 367 |                   setNrOfLookAheadSteps(Integer.parseInt(sNrOfLookAheadSteps)); | 
|---|
| 368 |                 } else { | 
|---|
| 369 |                   setNrOfLookAheadSteps(2); | 
|---|
| 370 |                 } | 
|---|
| 371 |  | 
|---|
| 372 |                 String sNrOfGoodOperations = Utils.getOption('G', options); | 
|---|
| 373 |                 if (sNrOfGoodOperations.length() != 0) { | 
|---|
| 374 |                   setNrOfGoodOperations(Integer.parseInt(sNrOfGoodOperations)); | 
|---|
| 375 |                 } else { | 
|---|
| 376 |                   setNrOfGoodOperations(5); | 
|---|
| 377 |                 } | 
|---|
| 378 |                  | 
|---|
| 379 |                 super.setOptions(options); | 
|---|
| 380 |         } // setOptions | 
|---|
| 381 |  | 
|---|
| 382 |         /** | 
|---|
| 383 |          * Gets the current settings of the search algorithm. | 
|---|
| 384 |          * | 
|---|
| 385 |          * @return an array of strings suitable for passing to setOptions | 
|---|
| 386 |          */ | 
|---|
| 387 |         public String[] getOptions() { | 
|---|
| 388 |                 String[] superOptions = super.getOptions(); | 
|---|
| 389 |                 String[] options = new String[9 + superOptions.length]; | 
|---|
| 390 |                 int current = 0; | 
|---|
| 391 |  | 
|---|
| 392 |                 options[current++] = "-L"; | 
|---|
| 393 |                 options[current++] = "" + m_nNrOfLookAheadSteps; | 
|---|
| 394 |                  | 
|---|
| 395 |                 options[current++] = "-G"; | 
|---|
| 396 |                 options[current++] = "" + m_nNrOfGoodOperations; | 
|---|
| 397 |  | 
|---|
| 398 |                 // insert options from parent class | 
|---|
| 399 |                 for (int iOption = 0; iOption < superOptions.length; iOption++) { | 
|---|
| 400 |                         options[current++] = superOptions[iOption]; | 
|---|
| 401 |                 } | 
|---|
| 402 |  | 
|---|
| 403 |                 // Fill up rest with empty strings, not nulls! | 
|---|
| 404 |                 while (current < options.length) { | 
|---|
| 405 |                         options[current++] = ""; | 
|---|
| 406 |                 } | 
|---|
| 407 |                 return options; | 
|---|
| 408 |         } // getOptions | 
|---|
| 409 |  | 
|---|
| 410 |  | 
|---|
| 411 |         /** | 
|---|
| 412 |          * This will return a string describing the search algorithm. | 
|---|
| 413 |          * @return The string. | 
|---|
| 414 |          */ | 
|---|
| 415 |         public String globalInfo() { | 
|---|
| 416 |           return "This Bayes Network learning algorithm uses a Look Ahead Hill Climbing algorithm called LAGD Hill Climbing." + | 
|---|
| 417 |           " Unlike Greedy Hill Climbing it doesn't calculate a best greedy operation (adding, deleting or reversing an arc) " +  | 
|---|
| 418 |           "but a sequence of nrOfLookAheadSteps operations, which leads to a network structure whose score is most likely " + | 
|---|
| 419 |           "higher in comparison to the network obtained by performing a sequence of nrOfLookAheadSteps greedy operations. " + | 
|---|
| 420 |           "The search is not restricted by an order " + | 
|---|
| 421 |           "on the variables (unlike K2). The difference with B and B2 is that this hill " + | 
|---|
| 422 |           "climber also considers arrows part of the naive Bayes structure for deletion."; | 
|---|
| 423 |         } // globalInfo | 
|---|
| 424 |  | 
|---|
| 425 |         /** | 
|---|
| 426 |          * @return a string to describe the Number of Look Ahead Steps option. | 
|---|
| 427 |          */ | 
|---|
| 428 |         public String nrOfLookAheadStepsTipText() { | 
|---|
| 429 |           return "Sets the Number of Look Ahead Steps. 'nrOfLookAheadSteps = 2' means that all network structures in a " + | 
|---|
| 430 |           "distance of 2 (from the current network structure) are taken into account for the decision which arcs to add, " + | 
|---|
| 431 |           "remove or reverse. 'nrOfLookAheadSteps = 1' results in Greedy Hill Climbing." ; | 
|---|
| 432 |         } // nrOfLookAheadStepsTipText | 
|---|
| 433 |  | 
|---|
| 434 |         /** | 
|---|
| 435 |          * @return a string to describe the Number of Good Operations option. | 
|---|
| 436 |          */ | 
|---|
| 437 |         public String nrOfGoodOperationsTipText() { | 
|---|
| 438 |           return "Sets the Number of Good Operations per Look Ahead Step. 'nrOfGoodOperations = 5' means that for the next " + | 
|---|
| 439 |           "Look Ahead Step only the 5 best Operations (adding, deleting or reversing an arc) are taken into account for the " + | 
|---|
| 440 |           "calculation of the best sequence consisting of nrOfLookAheadSteps operations." ; | 
|---|
| 441 |         } // nrOfGoodOperationsTipText | 
|---|
| 442 |  | 
|---|
| 443 |         /** | 
|---|
| 444 |          * Returns the revision string. | 
|---|
| 445 |          *  | 
|---|
| 446 |          * @return              the revision | 
|---|
| 447 |          */ | 
|---|
| 448 |         public String getRevision() { | 
|---|
| 449 |           return RevisionUtils.extract("$Revision: 1.7 $"); | 
|---|
| 450 |         } | 
|---|
| 451 |  | 
|---|
| 452 | } // LAGDHillClimber | 
|---|