~ubuntu-branches/ubuntu/precise/weka/precise

« back to all changes in this revision

Viewing changes to weka/datagenerators/classifiers/classification/BayesNet.java

  • Committer: Bazaar Package Importer
  • Author(s): Soeren Sonnenburg
  • Date: 2008-02-24 09:18:45 UTC
  • Revision ID: james.westby@ubuntu.com-20080224091845-1l8zy6fm6xipbzsr
Tags: upstream-3.5.7+tut1
ImportĀ upstreamĀ versionĀ 3.5.7+tut1

Show diffs side-by-side

added added

removed removed

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