source: tags/MetisMQIDemo/src/main/java/weka/datagenerators/classifiers/classification/BayesNet.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: 15.8 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 * BayesNet.java
19 * Copyright (C) 2005 University of Waikato, Hamilton, New Zealand
20 *
21 */
22
23package weka.datagenerators.classifiers.classification;
24
25import weka.classifiers.bayes.net.BayesNetGenerator;
26import weka.core.Instance; 
27import weka.core.DenseInstance;
28import weka.core.Instances;
29import weka.core.Option;
30import weka.core.RevisionUtils;
31import weka.core.Utils;
32import weka.datagenerators.ClassificationGenerator;
33
34import java.util.Enumeration;
35import java.util.Vector;
36
37/**
38 <!-- globalinfo-start -->
39 * Generates random instances based on a Bayes network.
40 * <p/>
41 <!-- globalinfo-end -->
42 *
43 <!-- options-start -->
44 * Valid options are: <p/>
45 *
46 * <pre> -h
47 *  Prints this help.</pre>
48 *
49 * <pre> -o &lt;file&gt;
50 *  The name of the output file, otherwise the generated data is
51 *  printed to stdout.</pre>
52 *
53 * <pre> -r &lt;name&gt;
54 *  The name of the relation.</pre>
55 *
56 * <pre> -d
57 *  Whether to print debug informations.</pre>
58 *
59 * <pre> -S
60 *  The seed for random function (default 1)</pre>
61 *
62 * <pre> -n &lt;num&gt;
63 *  The number of examples to generate (default 100)</pre>
64 *
65 * <pre> -A &lt;num&gt;
66 *  The number of arcs to use. (default 20)</pre>
67 *
68 * <pre> -C &lt;num&gt;
69 *  The cardinality of the attributes and the class. (default 2)</pre>
70 *
71 <!-- options-end -->
72 *
73 * @author FracPete (fracpete at waikato dot ac dot nz)
74 * @version $Revision: 5987 $
75 * @see BayesNetGenerator
76 */
77
78public class BayesNet
79  extends ClassificationGenerator {
80 
81  /** for serialization */
82  static final long serialVersionUID = -796118162379901512L;
83 
84  /** the bayesian net generator, that produces the actual data */
85  protected BayesNetGenerator m_Generator;
86
87  /**
88   * initializes the generator
89   */
90  public BayesNet() {
91    super();
92
93    setNumAttributes(defaultNumAttributes());
94    setNumArcs(defaultNumArcs());
95    setCardinality(defaultCardinality());
96  }
97 
98  /**
99   * Returns a string describing this data generator.
100   *
101   * @return a description of the data generator suitable for
102   * displaying in the explorer/experimenter gui
103   */
104  public String globalInfo() {
105    return 
106        "Generates random instances based on a Bayes network.";
107  }
108
109 /**
110   * Returns an enumeration describing the available options.
111   *
112   * @return an enumeration of all the available options
113   */
114  public Enumeration listOptions() {
115    Vector result = enumToVector(super.listOptions());
116
117    result.add(new Option(
118              "\tThe number of arcs to use. (default " 
119              + defaultNumArcs() + ")",
120              "A", 1, "-A <num>"));
121
122    result.add(new Option(
123              "\tThe cardinality of the attributes and the class. (default " 
124              + defaultCardinality() + ")",
125              "C", 1, "-C <num>"));
126
127    return result.elements();
128  }
129
130  /**
131   * Parses a list of options for this object. <p/>
132   *
133   <!-- options-start -->
134   * Valid options are: <p/>
135   *
136   * <pre> -h
137   *  Prints this help.</pre>
138   *
139   * <pre> -o &lt;file&gt;
140   *  The name of the output file, otherwise the generated data is
141   *  printed to stdout.</pre>
142   *
143   * <pre> -r &lt;name&gt;
144   *  The name of the relation.</pre>
145   *
146   * <pre> -d
147   *  Whether to print debug informations.</pre>
148   *
149   * <pre> -S
150   *  The seed for random function (default 1)</pre>
151   *
152   * <pre> -n &lt;num&gt;
153   *  The number of examples to generate (default 100)</pre>
154   *
155   * <pre> -A &lt;num&gt;
156   *  The number of arcs to use. (default 20)</pre>
157   *
158   * <pre> -C &lt;num&gt;
159   *  The cardinality of the attributes and the class. (default 2)</pre>
160   *
161   <!-- options-end -->
162   *
163   * @param options the list of options as an array of strings
164   * @throws Exception if an option is not supported
165   */
166  public void setOptions(String[] options) throws Exception {
167    String        tmpStr;
168    Vector        list;
169
170    super.setOptions(options);
171
172    list = new Vector();
173
174    list.add("-N");
175    list.add("" + getNumAttributes());
176
177    list.add("-M");
178    list.add("" + getNumExamples());
179   
180    list.add("-S");
181    list.add("" + getSeed());
182   
183    list.add("-A");
184    tmpStr = Utils.getOption('A', options);
185    if (tmpStr.length() != 0)
186      list.add(tmpStr);
187    else
188      list.add("" + defaultNumArcs());
189
190    list.add("-C");
191    tmpStr = Utils.getOption('C', options);
192    if (tmpStr.length() != 0)
193      list.add(tmpStr);
194    else
195      list.add("" + defaultCardinality());
196
197    setGeneratorOptions(list);
198  }
199
200  /**
201   * Gets the current settings of the datagenerator.
202   *
203   * @return an array of strings suitable for passing to setOptions
204   */
205  public String[] getOptions() {
206    Vector        result;
207    String[]      options;
208    int           i;
209   
210    result  = new Vector();
211    options = removeBlacklist(super.getOptions());
212    for (i = 0; i < options.length; i++)
213      result.add(options[i]);
214
215    // determine options from generator
216    options = getGenerator().getOptions();
217
218    try {
219      result.add("-A");
220      result.add(Utils.getOption('A', options));
221    }
222    catch (Exception e) {
223      e.printStackTrace();
224    }
225
226    try {
227      result.add("-C");
228      result.add(Utils.getOption('C', options));
229    }
230    catch (Exception e) {
231      e.printStackTrace();
232    }
233   
234    return (String[]) result.toArray(new String[result.size()]);
235  }
236
237  /**
238   * sets the given options of the BayesNetGenerator
239   *
240   * @param generator the generator to set the options for
241   * @param options the options to set
242   */
243  protected void setGeneratorOptions(
244      BayesNetGenerator generator, Vector options) {
245
246    try {
247      generator.setOptions(
248          (String[]) options.toArray(new String[options.size()]));
249    }
250    catch (Exception e) {
251      e.printStackTrace();
252    }
253  }
254
255  /**
256   * returns the actual datagenerator
257   *
258   * @return the actual datagenerator
259   */
260  protected BayesNetGenerator getGenerator() {
261    if (m_Generator == null)
262      m_Generator = new BayesNetGenerator();
263
264    return m_Generator;
265  }
266
267  /**
268   * sets the given options of the BayesNetGenerator
269   *
270   * @param options the options to set
271   */
272  protected void setGeneratorOptions(Vector options) {
273    setGeneratorOptions(getGenerator(), options);
274  }
275
276  /**
277   * sets a specific option/value of the generator (option must be w/o
278   * then '-')
279   * @param generator       the generator to set the option for
280   * @param option          the option to set
281   * @param value           the new value for the option
282   */
283  protected void setGeneratorOption( BayesNetGenerator generator, 
284                                     String option, String value ) {
285
286    String[]      options;
287    Vector        list;
288    int           i;
289
290    try {
291      // get options and remove specific option
292      options = generator.getOptions();
293      Utils.getOption(option, options);
294
295      // add option and set the new options
296      list = new Vector();
297      for (i = 0; i < options.length; i++) {
298        if (options[i].length() != 0)
299          list.add(options[i]);
300      }
301      list.add("-" + option);
302      list.add(value);
303      setGeneratorOptions(generator, list);
304    }
305    catch (Exception e) {
306      e.printStackTrace();
307    }
308  }
309
310  /**
311   * sets a specific option/value of the generator (option must be w/o
312   * then '-')
313   * @param option          the option to set
314   * @param value           the new value for the option
315   */
316  protected void setGeneratorOption(String option, String value) {
317    setGeneratorOption(getGenerator(), option, value);
318  }
319
320  /**
321   * returns the default number of attributes
322   *
323   * @return the default number of attributes
324   */
325  protected int defaultNumAttributes() {
326    return 10;
327  }
328
329  /**
330   * Sets the number of attributes the dataset should have.
331   * @param numAttributes the new number of attributes
332   */
333  public void setNumAttributes(int numAttributes) {
334    setGeneratorOption("N", "" + numAttributes);
335  }
336
337  /**
338   * Gets the number of attributes that should be produced.
339   * @return the number of attributes that should be produced
340   */
341  public int getNumAttributes() { 
342    int       result;
343   
344    result = -1;
345    try {
346      result = Integer.parseInt(
347          Utils.getOption('N', getGenerator().getOptions()));
348    }
349    catch (Exception e) {
350      e.printStackTrace();
351      result = -1;
352    }
353
354    return result;
355  }
356 
357  /**
358   * Returns the tip text for this property
359   *
360   * @return tip text for this property suitable for
361   *         displaying in the explorer/experimenter gui
362   */
363  public String numAttributesTipText() {
364    return "The number of attributes the generated data will contain (including class attribute), ie the number of nodes in the bayesian net.";
365  }
366
367  /**
368   * returns the default cardinality
369   *
370   * @return the default cardinality
371   */
372  protected int defaultCardinality() {
373    return 2;
374  }
375
376  /**
377   * Sets the cardinality of the attributes (incl class attribute)
378   * @param value the cardinality
379   */
380  public void setCardinality(int value) { 
381    setGeneratorOption("C", "" + value);
382  }
383
384  /**
385   * Gets the cardinality of the attributes (incl class attribute)
386   * @return the cardinality of the attributes
387   */
388  public int getCardinality() { 
389    int       result;
390   
391    result = -1;
392    try {
393      result = Integer.parseInt(
394          Utils.getOption('C', getGenerator().getOptions()));
395    }
396    catch (Exception e) {
397      e.printStackTrace();
398      result = -1;
399    }
400
401    return result;
402  }
403 
404  /**
405   * Returns the tip text for this property
406   *
407   * @return tip text for this property suitable for
408   *         displaying in the explorer/experimenter gui
409   */
410  public String cardinalityTipText() {
411    return "The cardinality of the attributes, incl the class attribute.";
412  }
413
414  /**
415   * returns the default number of arcs
416   *
417   * @return the default number of arcs
418   */
419  protected int defaultNumArcs() {
420    return 20;
421  }
422
423  /**
424   * Sets the number of arcs for the bayesian net
425   * @param value the number of arcs
426   */
427  public void setNumArcs(int value) {
428    int       nodes;
429    int       minArcs;
430    int       maxArcs;
431
432    nodes   = getNumAttributes();
433    minArcs = nodes - 1;
434    maxArcs = nodes * (nodes - 1) / 2;
435   
436    if (value > maxArcs)
437      throw new IllegalArgumentException(
438          "Number of arcs should be at most nodes * (nodes - 1) / 2 = " 
439          + maxArcs + " instead of " + value + " (nodes = numAttributes)!");
440    else if (value < minArcs)
441      throw new IllegalArgumentException(
442          "Number of arcs should be at least (nodes - 1) = " + minArcs
443          + " instead of " + value + " (nodes = numAttributes)!");
444    else
445      setGeneratorOption("A", "" + value);
446  }
447
448  /**
449   * Gets the number of arcs for the bayesian net
450   * @return the number of arcs
451   */
452  public int getNumArcs() { 
453    int       result;
454   
455    result = -1;
456    try {
457      result = Integer.parseInt(
458          Utils.getOption('A', getGenerator().getOptions()));
459    }
460    catch (Exception e) {
461      e.printStackTrace();
462      result = -1;
463    }
464
465    return result;
466  }
467 
468  /**
469   * Returns the tip text for this property
470   *
471   * @return tip text for this property suitable for
472   *         displaying in the explorer/experimenter gui
473   */
474  public String numArcsTipText() {
475    return "The number of arcs in the bayesian net, at most: n * (n - 1) / 2 and at least: (n - 1); with n = numAttributes";
476  }
477
478  /**
479   * Sets the number of examples, given by option.
480   * @param numExamples the new number of examples
481   */
482  public void setNumExamples(int numExamples) { 
483    super.setNumExamples(numExamples);
484    setGeneratorOption("M", "" + numExamples);
485  }
486
487  /**
488   * Gets the number of examples, given by option.
489   * @return the number of examples, given by option
490   */
491  public int getNumExamples() { 
492    int       result;
493   
494    result = -1;
495    try {
496      result = Integer.parseInt(
497          Utils.getOption('M', getGenerator().getOptions()));
498    }
499    catch (Exception e) {
500      e.printStackTrace();
501      result = -1;
502    }
503
504    return result;
505  }
506
507  /**
508   * Return if single mode is set for the given data generator
509   * mode depends on option setting and or generator type.
510   *
511   * @return single mode flag
512   * @throws Exception if mode is not set yet
513   */
514  public boolean getSingleModeFlag() throws Exception {
515    return false;
516  }
517
518  /**
519   * Initializes the format for the dataset produced.
520   * Must be called before the generateExample or generateExamples
521   * methods are used.
522   * Re-initializes the random number generator with the given seed.
523   *
524   * @return the format for the dataset
525   * @throws Exception if the generating of the format failed
526   * @see  #getSeed()
527   */
528  public Instances defineDataFormat() throws Exception {
529    BayesNetGenerator   bng;
530
531    bng = new BayesNetGenerator();
532    bng.setOptions(getGenerator().getOptions());
533    setGeneratorOption(bng, "M", "1");
534    bng.generateRandomNetwork();
535    bng.generateInstances();
536    bng.m_Instances.renameAttribute(0, "class");
537    bng.m_Instances.setRelationName(getRelationNameToUse());
538   
539    return bng.m_Instances;
540  }
541
542  /**
543   * Generates one example of the dataset.
544   *
545   * @return the generated example
546   * @throws Exception if the format of the dataset is not yet defined
547   * @throws Exception if the generator only works with generateExamples
548   * which means in non single mode
549   */
550  public Instance generateExample() throws Exception {
551    throw new Exception("Cannot generate examples one-by-one!");
552  }
553
554  /**
555   * Generates all examples of the dataset. Re-initializes the random number
556   * generator with the given seed, before generating instances.
557   *
558   * @return the generated dataset
559   * @throws Exception if the format of the dataset is not yet defined
560   * @throws Exception if the generator only works with generateExample,
561   * which means in single mode
562   * @see   #getSeed()
563   */
564  public Instances generateExamples() throws Exception {
565    getGenerator().setOptions(getGenerator().getOptions());
566    getGenerator().generateRandomNetwork();
567    getGenerator().generateInstances();
568    getGenerator().m_Instances.renameAttribute(0, "class");
569    getGenerator().m_Instances.setRelationName(getRelationNameToUse());
570   
571    return getGenerator().m_Instances;
572  }
573
574  /**
575   * Generates a comment string that documentates the data generator.
576   * By default this string is added at the beginning of the produced output
577   * as ARFF file type, next after the options.
578   *
579   * @return string contains info about the generated rules
580   */
581  public String generateStart () {
582    return "";
583  }
584
585  /**
586   * Generates a comment string that documentats the data generator.
587   * By default this string is added at the end of theproduces output
588   * as ARFF file type.
589   *
590   * @return string contains info about the generated rules
591   * @throws Exception if the generating of the documentaion fails
592   */
593  public String generateFinished() throws Exception {
594    return "";
595  }
596 
597  /**
598   * Returns the revision string.
599   *
600   * @return            the revision
601   */
602  public String getRevision() {
603    return RevisionUtils.extract("$Revision: 5987 $");
604  }
605
606  /**
607   * Main method for executing this class.
608   *
609   * @param args should contain arguments for the data producer:
610   */
611  public static void main(String[] args) {
612    runDataGenerator(new BayesNet(), args);
613  }
614}
Note: See TracBrowser for help on using the repository browser.