source: src/main/java/weka/core/TestInstances.java @ 14

Last change on this file since 14 was 4, checked in by gnappo, 14 years ago

Import di weka.

File size: 51.4 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 * TestInstances.java
19 * Copyright (C) 2006 University of Waikato, Hamilton, New Zealand
20 */
21
22package weka.core;
23
24import weka.core.Capabilities.Capability;
25
26import java.io.Serializable;
27import java.util.Enumeration;
28import java.util.Random;
29import java.util.StringTokenizer;
30import java.util.Vector;
31import java.util.ArrayList;
32
33/**
34 * Generates artificial datasets for testing. In case of Multi-Instance data
35 * the settings for the number of attributes applies to the data inside
36 * the bag. Originally based on code from the CheckClassifier.<p/>
37 *
38 <!-- options-start -->
39 * Valid options are: <p/>
40 *
41 * <pre> -relation &lt;name&gt;
42 *  The name of the data set.</pre>
43 *
44 * <pre> -seed &lt;num&gt;
45 *  The seed value.</pre>
46 *
47 * <pre> -num-instances &lt;num&gt;
48 *  The number of instances in the datasets (default 20).</pre>
49 *
50 * <pre> -class-type &lt;num&gt;
51 *  The class type, see constants in weka.core.Attribute
52 *  (default 1=nominal).</pre>
53 *
54 * <pre> -class-values &lt;num&gt;
55 *  The number of classes to generate (for nominal classes only)
56 *  (default 2).</pre>
57 *
58 * <pre> -class-index &lt;num&gt;
59 *  The class index, with -1=last, (default -1).</pre>
60 *
61 * <pre> -no-class
62 *  Doesn't include a class attribute in the output.</pre>
63 *
64 * <pre> -nominal &lt;num&gt;
65 *  The number of nominal attributes (default 1).</pre>
66 *
67 * <pre> -nominal-values &lt;num&gt;
68 *  The number of values for nominal attributes (default 2).</pre>
69 *
70 * <pre> -numeric &lt;num&gt;
71 *  The number of numeric attributes (default 0).</pre>
72 *
73 * <pre> -string &lt;num&gt;
74 *  The number of string attributes (default 0).</pre>
75 *
76 * <pre> -words &lt;comma-separated-list&gt;
77 *  The words to use in string attributes.</pre>
78 *
79 * <pre> -word-separators &lt;chars&gt;
80 *  The word separators to use in string attributes.</pre>
81 *
82 * <pre> -date &lt;num&gt;
83 *  The number of date attributes (default 0).</pre>
84 *
85 * <pre> -relational &lt;num&gt;
86 *  The number of relational attributes (default 0).</pre>
87 *
88 * <pre> -relational-nominal &lt;num&gt;
89 *  The number of nominal attributes in a rel. attribute (default 1).</pre>
90 *
91 * <pre> -relational-nominal-values &lt;num&gt;
92 *  The number of values for nominal attributes in a rel. attribute (default 2).</pre>
93 *
94 * <pre> -relational-numeric &lt;num&gt;
95 *  The number of numeric attributes in a rel. attribute (default 0).</pre>
96 *
97 * <pre> -relational-string &lt;num&gt;
98 *  The number of string attributes in a rel. attribute (default 0).</pre>
99 *
100 * <pre> -relational-date &lt;num&gt;
101 *  The number of date attributes in a rel. attribute (default 0).</pre>
102 *
103 * <pre> -num-instances-relational &lt;num&gt;
104 *  The number of instances in relational/bag attributes (default 10).</pre>
105 *
106 * <pre> -multi-instance
107 *  Generates multi-instance data.</pre>
108 *
109 * <pre> -W &lt;classname&gt;
110 *  The Capabilities handler to base the dataset on.
111 *  The other parameters can be used to override the ones
112 *  determined from the handler. Additional parameters for
113 *  handler can be passed on after the '--'.</pre>
114 *
115 <!-- options-end -->
116 *
117 * @author FracPete (fracpete at waikato dot ac dot nz)
118 * @version $Revision: 5987 $
119 * @see weka.classifiers.CheckClassifier
120 */
121public class TestInstances 
122  implements Cloneable, Serializable, OptionHandler, RevisionHandler {
123
124  /** for serialization */
125  private static final long serialVersionUID = -6263968936330390469L;
126
127  /** can be used for settting the class attribute index to last
128   * @see #setClassIndex(int) */
129  public final static int CLASS_IS_LAST = -1;
130 
131  /** can be used to avoid generating a class attribute
132   * @see #setClassIndex(int) */
133  public final static int NO_CLASS = -2;
134
135  /** the default list of words used in strings */
136  public final static String[] DEFAULT_WORDS = {"The", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog"};
137
138  /** the default word separators used in strings */
139  public final static String DEFAULT_SEPARATORS = " ";
140 
141  /** for generating String attributes/classes */
142  protected String[] m_Words = DEFAULT_WORDS;
143 
144  /** for generating String attributes/classes */
145  protected String m_WordSeparators = DEFAULT_SEPARATORS;
146 
147  /** the name of the relation */
148  protected String m_Relation = "Testdata";
149 
150  /** the seed value */
151  protected int m_Seed = 1;
152 
153  /** the random number generator */
154  protected Random m_Random = new Random(m_Seed);
155 
156  /** the number of instances */
157  protected int m_NumInstances = 20;
158 
159  /** the class type */
160  protected int m_ClassType = Attribute.NOMINAL;
161 
162  /** the number of classes (in case of NOMINAL class) */
163  protected int m_NumClasses = 2;
164
165  /** the class index (-1 is LAST, -2 means no class)
166   * @see #CLASS_IS_LAST
167   * @see #NO_CLASS */
168  protected int m_ClassIndex = CLASS_IS_LAST;
169 
170  /** the number of nominal attributes */
171  protected int m_NumNominal = 1;
172 
173  /** the number of values for nominal attributes */
174  protected int m_NumNominalValues = 2;
175 
176  /** the number of numeric attributes */
177  protected int m_NumNumeric = 0;
178 
179  /** the number of string attributes */
180  protected int m_NumString = 0;
181 
182  /** the number of date attributes */
183  protected int m_NumDate = 0;
184 
185  /** the number of relational attributes */
186  protected int m_NumRelational = 0;
187 
188  /** the number of nominal attributes in a relational attribute */
189  protected int m_NumRelationalNominal = 1;
190 
191  /** the number of values for nominal attributes in relational attributes */
192  protected int m_NumRelationalNominalValues = 2;
193 
194  /** the number of numeric attributes in a relational attribute */
195  protected int m_NumRelationalNumeric = 0;
196 
197  /** the number of string attributes in a relational attribute */
198  protected int m_NumRelationalString = 0;
199 
200  /** the number of date attributes in a relational attribute */
201  protected int m_NumRelationalDate = 0;
202 
203  /** whether to generate Multi-Instance data or not */
204  protected boolean m_MultiInstance = false;
205 
206  /** the number of instances in relational attributes (applies also for bags
207   * in multi-instance) */
208  protected int m_NumInstancesRelational = 10;
209 
210  /** the format of the multi-instance data */
211  protected Instances[] m_RelationalFormat = null;
212 
213  /** the format of the multi-instance data of the class */
214  protected Instances m_RelationalClassFormat = null;
215 
216  /** the generated data */
217  protected Instances m_Data = null;
218 
219  /** the CapabilitiesHandler to get the Capabilities from */
220  protected CapabilitiesHandler m_Handler = null;
221
222  /**
223   * the default constructor
224   */
225  public TestInstances() {
226    super();
227   
228    setRelation("Testdata");
229    setSeed(1);
230    setNumInstances(20);
231    setClassType(Attribute.NOMINAL);
232    setNumClasses(2);
233    setClassIndex(CLASS_IS_LAST);
234    setNumNominal(1);
235    setNumNominalValues(2);
236    setNumNumeric(0);
237    setNumString(0);
238    setNumDate(0);
239    setNumRelational(0);
240    setNumRelationalNominal(1);
241    setNumRelationalNominalValues(2);
242    setNumRelationalNumeric(0);
243    setNumRelationalString(0);
244    setNumRelationalDate(0);
245    setNumInstancesRelational(10);
246    setMultiInstance(false);
247    setWords(arrayToList(DEFAULT_WORDS));
248    setWordSeparators(DEFAULT_SEPARATORS);
249  }
250 
251  /**
252   * creates a clone of the current object
253   *
254   * @return            a clone of the current object
255   */
256  public Object clone() {
257    TestInstances     result;
258   
259    result = new TestInstances();
260    result.assign(this);
261   
262    return result;
263  }
264 
265  /**
266   * updates itself with all the settings from the given TestInstances
267   * object
268   *
269   * @param t           the object to get the settings from
270   */
271  public void assign(TestInstances t) {
272    setRelation(t.getRelation());
273    setSeed(t.getSeed());
274    setNumInstances(t.getNumInstances());
275    setClassType(t.getClassType());
276    setNumClasses(t.getNumClasses());
277    setClassIndex(t.getClassIndex());
278    setNumNominal(t.getNumNominal());
279    setNumNominalValues(t.getNumNominalValues());
280    setNumNumeric(t.getNumNumeric());
281    setNumString(t.getNumString());
282    setNumDate(t.getNumDate());
283    setNumRelational(t.getNumRelational());
284    setNumRelationalNominal(t.getNumRelationalNominal());
285    setNumRelationalNominalValues(t.getNumRelationalNominalValues());
286    setNumRelationalNumeric(t.getNumRelationalNumeric());
287    setNumRelationalString(t.getNumRelationalString());
288    setNumRelationalDate(t.getNumRelationalDate());
289    setMultiInstance(t.getMultiInstance());
290    for (int i = 0; i < t.getNumRelational(); i++)
291      setRelationalFormat(i, t.getRelationalFormat(i));
292    setRelationalClassFormat(t.getRelationalClassFormat());
293    setNumInstancesRelational(t.getNumInstancesRelational());
294    setWords(t.getWords());
295    setWordSeparators(t.getWordSeparators());
296  }
297 
298  /**
299   * Returns an enumeration describing the available options.
300   *
301   * @return an enumeration of all the available options.
302   */
303  public Enumeration listOptions() {
304    Vector<Option> result = new Vector<Option>();
305   
306    result.add(new Option(
307        "\tThe name of the data set.",
308        "relation", 1, "-relation <name>"));
309   
310    result.add(new Option(
311        "\tThe seed value.",
312        "seed", 1, "-seed <num>"));
313   
314    result.add(new Option(
315        "\tThe number of instances in the datasets (default 20).",
316        "num-instances", 1, "-num-instances <num>"));
317   
318    result.add(new Option(
319        "\tThe class type, see constants in weka.core.Attribute\n"
320        + "\t(default 1=nominal).",
321        "class-type", 1, "-class-type <num>"));
322   
323    result.add(new Option(
324        "\tThe number of classes to generate (for nominal classes only)\n"
325        + "\t(default 2).",
326        "class-values", 1, "-class-values <num>"));
327   
328    result.add(new Option(
329        "\tThe class index, with -1=last, (default -1).",
330        "class-index", 1, "-class-index <num>"));
331   
332    result.add(new Option(
333        "\tDoesn't include a class attribute in the output.",
334        "no-class", 0, "-no-class"));
335
336    result.add(new Option(
337        "\tThe number of nominal attributes (default 1).",
338        "nominal", 1, "-nominal <num>"));
339   
340    result.add(new Option(
341        "\tThe number of values for nominal attributes (default 2).",
342        "nominal-values", 1, "-nominal-values <num>"));
343   
344    result.add(new Option(
345        "\tThe number of numeric attributes (default 0).",
346        "numeric", 1, "-numeric <num>"));
347   
348    result.add(new Option(
349        "\tThe number of string attributes (default 0).",
350        "string", 1, "-string <num>"));
351   
352    result.add(new Option(
353        "\tThe words to use in string attributes.",
354        "words", 1, "-words <comma-separated-list>"));
355   
356    result.add(new Option(
357        "\tThe word separators to use in string attributes.",
358        "word-separators", 1, "-word-separators <chars>"));
359   
360    result.add(new Option(
361        "\tThe number of date attributes (default 0).",
362        "date", 1, "-date <num>"));
363   
364    result.add(new Option(
365        "\tThe number of relational attributes (default 0).",
366        "relational", 1, "-relational <num>"));
367   
368    result.add(new Option(
369        "\tThe number of nominal attributes in a rel. attribute (default 1).",
370        "relational-nominal", 1, "-relational-nominal <num>"));
371   
372    result.add(new Option(
373        "\tThe number of values for nominal attributes in a rel. attribute (default 2).",
374        "relational-nominal-values", 1, "-relational-nominal-values <num>"));
375   
376    result.add(new Option(
377        "\tThe number of numeric attributes in a rel. attribute (default 0).",
378        "relational-numeric", 1, "-relational-numeric <num>"));
379   
380    result.add(new Option(
381        "\tThe number of string attributes in a rel. attribute (default 0).",
382        "relational-string", 1, "-relational-string <num>"));
383   
384    result.add(new Option(
385        "\tThe number of date attributes in a rel. attribute (default 0).",
386        "relational-date", 1, "-relational-date <num>"));
387   
388    result.add(new Option(
389        "\tThe number of instances in relational/bag attributes (default 10).",
390        "num-instances-relational", 1, "-num-instances-relational <num>"));
391   
392    result.add(new Option(
393        "\tGenerates multi-instance data.",
394        "multi-instance", 0, "-multi-instance"));
395
396    result.add(new Option(
397        "\tThe Capabilities handler to base the dataset on.\n"
398        + "\tThe other parameters can be used to override the ones\n"
399        + "\tdetermined from the handler. Additional parameters for\n"
400        + "\thandler can be passed on after the '--'.",
401        "W", 1, "-W <classname>"));
402   
403    return result.elements();
404  }
405 
406  /**
407   * Parses a given list of options. <p/>
408   *
409   <!-- options-start -->
410   * Valid options are: <p/>
411   *
412   * <pre> -relation &lt;name&gt;
413   *  The name of the data set.</pre>
414   *
415   * <pre> -seed &lt;num&gt;
416   *  The seed value.</pre>
417   *
418   * <pre> -num-instances &lt;num&gt;
419   *  The number of instances in the datasets (default 20).</pre>
420   *
421   * <pre> -class-type &lt;num&gt;
422   *  The class type, see constants in weka.core.Attribute
423   *  (default 1=nominal).</pre>
424   *
425   * <pre> -class-values &lt;num&gt;
426   *  The number of classes to generate (for nominal classes only)
427   *  (default 2).</pre>
428   *
429   * <pre> -class-index &lt;num&gt;
430   *  The class index, with -1=last, (default -1).</pre>
431   *
432   * <pre> -no-class
433   *  Doesn't include a class attribute in the output.</pre>
434   *
435   * <pre> -nominal &lt;num&gt;
436   *  The number of nominal attributes (default 1).</pre>
437   *
438   * <pre> -nominal-values &lt;num&gt;
439   *  The number of values for nominal attributes (default 2).</pre>
440   *
441   * <pre> -numeric &lt;num&gt;
442   *  The number of numeric attributes (default 0).</pre>
443   *
444   * <pre> -string &lt;num&gt;
445   *  The number of string attributes (default 0).</pre>
446   *
447   * <pre> -words &lt;comma-separated-list&gt;
448   *  The words to use in string attributes.</pre>
449   *
450   * <pre> -word-separators &lt;chars&gt;
451   *  The word separators to use in string attributes.</pre>
452   *
453   * <pre> -date &lt;num&gt;
454   *  The number of date attributes (default 0).</pre>
455   *
456   * <pre> -relational &lt;num&gt;
457   *  The number of relational attributes (default 0).</pre>
458   *
459   * <pre> -relational-nominal &lt;num&gt;
460   *  The number of nominal attributes in a rel. attribute (default 1).</pre>
461   *
462   * <pre> -relational-nominal-values &lt;num&gt;
463   *  The number of values for nominal attributes in a rel. attribute (default 2).</pre>
464   *
465   * <pre> -relational-numeric &lt;num&gt;
466   *  The number of numeric attributes in a rel. attribute (default 0).</pre>
467   *
468   * <pre> -relational-string &lt;num&gt;
469   *  The number of string attributes in a rel. attribute (default 0).</pre>
470   *
471   * <pre> -relational-date &lt;num&gt;
472   *  The number of date attributes in a rel. attribute (default 0).</pre>
473   *
474   * <pre> -num-instances-relational &lt;num&gt;
475   *  The number of instances in relational/bag attributes (default 10).</pre>
476   *
477   * <pre> -multi-instance
478   *  Generates multi-instance data.</pre>
479   *
480   * <pre> -W &lt;classname&gt;
481   *  The Capabilities handler to base the dataset on.
482   *  The other parameters can be used to override the ones
483   *  determined from the handler. Additional parameters for
484   *  handler can be passed on after the '--'.</pre>
485   *
486   <!-- options-end -->
487   *
488   * @param options the list of options as an array of strings
489   * @throws Exception if an option is not supported
490   */
491  public void setOptions(String[] options) throws Exception {
492    String                      tmpStr;
493    Class                       cls;
494    CapabilitiesHandler         handler;
495    boolean                     initialized;
496   
497    initialized = false;
498
499    tmpStr = Utils.getOption('W', options);
500    if (tmpStr.length() > 0) {
501      cls = Class.forName(tmpStr);
502      if (ClassDiscovery.hasInterface(CapabilitiesHandler.class, cls)) {
503        initialized = true;
504        handler = (CapabilitiesHandler) cls.newInstance();
505        if (handler instanceof OptionHandler)
506          ((OptionHandler) handler).setOptions(Utils.partitionOptions(options));
507        setHandler(handler);
508        // initialize
509        this.assign(forCapabilities(handler.getCapabilities()));
510      }
511      else {
512        throw new IllegalArgumentException("Class '" + tmpStr + "' is not a CapabilitiesHandler!");
513      }
514    }
515
516    tmpStr = Utils.getOption("relation", options);
517    if (tmpStr.length() != 0)
518      setRelation(tmpStr);
519    else if (!initialized)
520      setRelation("Testdata");
521   
522    tmpStr = Utils.getOption("seed", options);
523    if (tmpStr.length() != 0)
524      setSeed(Integer.parseInt(tmpStr));
525    else if (!initialized)
526      setSeed(1);
527   
528    tmpStr = Utils.getOption("num-instances", options);
529    if (tmpStr.length() != 0)
530      setNumInstances(Integer.parseInt(tmpStr));
531    else if (!initialized)
532      setNumInstances(20);
533   
534    setNoClass(Utils.getFlag("no-class", options));
535   
536    if (!getNoClass()) {
537      tmpStr = Utils.getOption("class-type", options);
538      if (tmpStr.length() != 0)
539        setClassType(Integer.parseInt(tmpStr));
540      else if (!initialized)
541        setClassType(Attribute.NOMINAL);
542
543      tmpStr = Utils.getOption("class-values", options);
544      if (tmpStr.length() != 0)
545        setNumClasses(Integer.parseInt(tmpStr));
546      else if (!initialized)
547        setNumClasses(2);
548
549      tmpStr = Utils.getOption("class-index", options);
550      if (tmpStr.length() != 0)
551        setClassIndex(Integer.parseInt(tmpStr));
552      else if (!initialized)
553        setClassIndex(-1);
554    }
555   
556    tmpStr = Utils.getOption("nominal", options);
557    if (tmpStr.length() != 0)
558      setNumNominal(Integer.parseInt(tmpStr));
559    else if (!initialized)
560      setNumNominal(1);
561   
562    tmpStr = Utils.getOption("nominal-values", options);
563    if (tmpStr.length() != 0)
564      setNumNominalValues(Integer.parseInt(tmpStr));
565    else if (!initialized)
566      setNumNominalValues(2);
567   
568    tmpStr = Utils.getOption("numeric", options);
569    if (tmpStr.length() != 0)
570      setNumNumeric(Integer.parseInt(tmpStr));
571    else if (!initialized)
572      setNumNumeric(0);
573   
574    tmpStr = Utils.getOption("string", options);
575    if (tmpStr.length() != 0)
576      setNumString(Integer.parseInt(tmpStr));
577    else if (!initialized)
578      setNumString(0);
579   
580    tmpStr = Utils.getOption("words", options);
581    if (tmpStr.length() != 0)
582      setWords(tmpStr);
583    else if (!initialized)
584      setWords(arrayToList(DEFAULT_WORDS));
585   
586    if (Utils.getOptionPos("word-separators", options) > -1) {
587      tmpStr = Utils.getOption("word-separators", options);
588      setWordSeparators(tmpStr);
589    }
590    else if (!initialized) {
591      setWordSeparators(DEFAULT_SEPARATORS);
592    }
593   
594    tmpStr = Utils.getOption("date", options);
595    if (tmpStr.length() != 0)
596      setNumDate(Integer.parseInt(tmpStr));
597    else if (!initialized)
598      setNumDate(0);
599   
600    tmpStr = Utils.getOption("relational", options);
601    if (tmpStr.length() != 0)
602      setNumRelational(Integer.parseInt(tmpStr));
603    else if (!initialized)
604      setNumRelational(0);
605   
606    tmpStr = Utils.getOption("relational-nominal", options);
607    if (tmpStr.length() != 0)
608      setNumRelationalNominal(Integer.parseInt(tmpStr));
609    else if (!initialized)
610      setNumRelationalNominal(1);
611   
612    tmpStr = Utils.getOption("relational-nominal-values", options);
613    if (tmpStr.length() != 0)
614      setNumRelationalNominalValues(Integer.parseInt(tmpStr));
615    else if (!initialized)
616      setNumRelationalNominalValues(2);
617   
618    tmpStr = Utils.getOption("relational-numeric", options);
619    if (tmpStr.length() != 0)
620      setNumRelationalNumeric(Integer.parseInt(tmpStr));
621    else if (!initialized)
622      setNumRelationalNumeric(0);
623   
624    tmpStr = Utils.getOption("relational-string", options);
625    if (tmpStr.length() != 0)
626      setNumRelationalString(Integer.parseInt(tmpStr));
627    else if (!initialized)
628      setNumRelationalString(0);
629   
630    tmpStr = Utils.getOption("num-instances-relational", options);
631    if (tmpStr.length() != 0)
632      setNumInstancesRelational(Integer.parseInt(tmpStr));
633    else if (!initialized)
634      setNumInstancesRelational(10);
635   
636    if (!initialized)
637      setMultiInstance(Utils.getFlag("multi-instance", options));
638  }
639 
640  /**
641   * Gets the current settings of this object.
642   *
643   * @return an array of strings suitable for passing to setOptions
644   */
645  public String[] getOptions() {
646    Vector<String>      result;
647    String[]    options;
648    int         i;
649
650    result = new Vector<String>();
651   
652    result.add("-relation");
653    result.add(getRelation());
654   
655    result.add("-seed");
656    result.add("" + getSeed());
657   
658    result.add("-num-instances");
659    result.add("" + getNumInstances());
660   
661    if (getNoClass()) {
662      result.add("-no-class");
663    }
664    else {
665      result.add("-class-type");
666      result.add("" + getClassType());
667     
668      result.add("-class-values");
669      result.add("" + getNumClasses());
670     
671      result.add("-class-index");
672      result.add("" + getClassIndex());
673    }
674   
675    result.add("-nominal");
676    result.add("" + getNumNominal());
677   
678    result.add("-nominal-values");
679    result.add("" + getNumNominalValues());
680   
681    result.add("-numeric");
682    result.add("" + getNumNumeric());
683   
684    result.add("-string");
685    result.add("" + getNumString());
686   
687    result.add("-words");
688    result.add("" + getWords());
689   
690    result.add("-word-separators");
691    result.add("" + getWordSeparators());
692   
693    result.add("-date");
694    result.add("" + getNumDate());
695   
696    result.add("-relational");
697    result.add("" + getNumRelational());
698   
699    result.add("-relational-nominal");
700    result.add("" + getNumRelationalNominal());
701   
702    result.add("-relational-nominal-values");
703    result.add("" + getNumRelationalNominalValues());
704   
705    result.add("-relational-numeric");
706    result.add("" + getNumRelationalNumeric());
707   
708    result.add("-relational-string");
709    result.add("" + getNumRelationalString());
710   
711    result.add("-relational-date");
712    result.add("" + getNumRelationalDate());
713   
714    result.add("-num-instances-relational");
715    result.add("" + getNumInstancesRelational());
716
717    if (getMultiInstance())
718      result.add("-multi-instance");
719
720    if (getHandler() != null) {
721      result.add("-W");
722      result.add(getHandler().getClass().getName());
723      if (getHandler() instanceof OptionHandler) {
724        result.add("--");
725        options = ((OptionHandler) getHandler()).getOptions();
726        for (i = 0; i < options.length; i++)
727          result.add(options[i]);
728      }
729    }
730   
731    return (String[]) result.toArray(new String[result.size()]);
732  }
733 
734  /**
735   * sets the name of the relation
736   *
737   * @param value       the name of the relation
738   */
739  public void setRelation(String value) {
740    m_Relation = value;
741  }
742 
743  /**
744   * returns the current name of the relation
745   *
746   * @return            the name of the relation
747   */
748  public String getRelation() {
749    return m_Relation;
750  }
751 
752  /**
753   * sets the seed value for the random number generator
754   *
755   * @param value       the seed
756   */
757  public void setSeed(int value) {
758    m_Seed   = value;
759    m_Random = new Random(m_Seed);
760  }
761 
762  /**
763   * returns the current seed value
764   *
765   * @return            the seed value
766   */
767  public int getSeed() {
768    return m_Seed;
769  }
770 
771  /**
772   * sets the number of instances to produce
773   *
774   * @param value       the number of instances
775   */
776  public void setNumInstances(int value) {
777    m_NumInstances = value;
778  }
779 
780  /**
781   * returns the current number of instances to produce
782   *
783   * @return the number of instances
784   */
785  public int getNumInstances() {
786    return m_NumInstances;
787  }
788 
789  /**
790   * sets the class attribute type
791   *
792   * @param value       the class attribute type
793   */
794  public void setClassType(int value) {
795    m_ClassType = value;
796    m_RelationalClassFormat = null;
797  }
798 
799  /**
800   * returns the current class type
801   *
802   * @return the class attribute type
803   */
804  public int getClassType() {
805    return m_ClassType;
806  }
807 
808  /**
809   * sets the number of classes
810   *
811   * @param value       the number of classes
812   */
813  public void setNumClasses(int value) {
814    m_NumClasses = value;
815  }
816 
817  /**
818   * returns the current number of classes
819   *
820   * @return the number of classes
821   */
822  public int getNumClasses() {
823    return m_NumClasses;
824  }
825 
826  /**
827   * sets the class index (0-based)
828   *
829   * @param value       the class index
830   * @see #CLASS_IS_LAST
831   * @see #NO_CLASS
832   */
833  public void setClassIndex(int value) {
834    m_ClassIndex = value;
835  }
836 
837  /**
838   * returns the current class index (0-based), -1 is last attribute
839   *
840   * @return            the class index
841   * @see #CLASS_IS_LAST
842   * @see #NO_CLASS
843   */
844  public int getClassIndex() {
845    return m_ClassIndex;
846  }
847 
848  /**
849   * whether to have no class, e.g., for clusterers; otherwise the class
850   * attribute index is set to last
851   *
852   * @param value whether to have no class
853   * @see #CLASS_IS_LAST
854   * @see #NO_CLASS
855   */
856  public void setNoClass(boolean value) {
857    if (value)
858      setClassIndex(NO_CLASS);
859    else
860      setClassIndex(CLASS_IS_LAST);
861  }
862 
863  /**
864   * whether no class attribute is generated
865   *
866   * @return            true if no class attribute is generated
867   */
868  public boolean getNoClass() {
869    return (getClassIndex() == NO_CLASS);
870  }
871 
872  /**
873   * sets the number of nominal attributes
874   *
875   * @param value       the number of nominal attributes
876   */
877  public void setNumNominal(int value) {
878    m_NumNominal = value;
879  }
880 
881  /**
882   * returns the current number of nominal attributes
883   *
884   * @return            the number of nominal attributes
885   */
886  public int getNumNominal() {
887    return m_NumNominal;
888  }
889 
890  /**
891   * sets the number of values for nominal attributes
892   *
893   * @param value       the number of values
894   */
895  public void setNumNominalValues(int value) {
896    m_NumNominalValues = value;
897  }
898 
899  /**
900   * returns the current number of values for nominal attributes
901   *
902   * @return            the number of values
903   */
904  public int getNumNominalValues() {
905    return m_NumNominalValues;
906  }
907 
908  /**
909   * sets the number of numeric attributes
910   *
911   * @param value       the number of numeric attributes
912   */
913  public void setNumNumeric(int value) {
914    m_NumNumeric = value;
915  }
916 
917  /**
918   * returns the current number of numeric attributes
919   *
920   * @return            the number of numeric attributes
921   */
922  public int getNumNumeric() {
923    return m_NumNumeric;
924  }
925 
926  /**
927   * sets the number of string attributes
928   *
929   * @param value       the number of string attributes
930   */
931  public void setNumString(int value) {
932    m_NumString = value;
933  }
934 
935  /**
936   * returns the current number of string attributes
937   *
938   * @return            the number of string attributes
939   */
940  public int getNumString() {
941    return m_NumString;
942  }
943
944  /**
945   * turns the comma-separated list into an array
946   *
947   * @param value       the list to process
948   * @return            the list as array
949   */
950  protected static String[] listToArray(String value) {
951    StringTokenizer     tok;
952    Vector<String>              list;
953   
954    list = new Vector<String>();
955    tok = new StringTokenizer(value, ",");
956    while (tok.hasMoreTokens())
957      list.add(tok.nextToken());
958   
959    return (String[]) list.toArray(new String[list.size()]);
960  }
961 
962  /**
963   * turns the array into a comma-separated list
964   *
965   * @param value       the array to process
966   * @return            the array as list
967   */
968  protected static String arrayToList(String[] value) {
969    String      result;
970    int         i;
971   
972    result = "";
973   
974    for (i = 0; i < value.length; i++) {
975      if (i > 0)
976        result += ",";
977      result += value[i];
978    }
979   
980    return result;
981  }
982 
983  /**
984   * Sets the comma-separated list of words to use for generating strings. The
985   * list must contain at least 2 words, otherwise an exception will be thrown.
986   *
987   * @param value                       the list of words
988   * @throws IllegalArgumentException   if not at least 2 words are provided
989   */
990  public void setWords(String value) {
991    if (listToArray(value).length < 2)
992      throw new IllegalArgumentException("At least 2 words must be provided!");
993   
994    m_Words = listToArray(value);
995  }
996 
997  /**
998   * returns the words used for assembling strings in a comma-separated list.
999   *
1000   * @return            the words as comma-separated list
1001   */
1002  public String getWords() {
1003    return arrayToList(m_Words);
1004  }
1005
1006  /**
1007   * sets the word separators (chars) to use for assembling strings.
1008   *
1009   * @param value       the characters to use as separators
1010   */
1011  public void setWordSeparators(String value) {
1012    m_WordSeparators = value;
1013  }
1014 
1015  /**
1016   * returns the word separators (chars) to use for assembling strings.
1017   *
1018   * @return            the current separators
1019   */
1020  public String getWordSeparators() {
1021    return m_WordSeparators;
1022  }
1023 
1024  /**
1025   * sets the number of date attributes
1026   *
1027   * @param value       the number of date attributes
1028   */
1029  public void setNumDate(int value) {
1030    m_NumDate = value;
1031  }
1032 
1033  /**
1034   * returns the current number of date attributes
1035   *
1036   * @return            the number of date attributes
1037   */
1038  public int getNumDate() {
1039    return m_NumDate;
1040  }
1041 
1042  /**
1043   * sets the number of relational attributes
1044   *
1045   * @param value       the number of relational attributes
1046   */
1047  public void setNumRelational(int value) {
1048    m_NumRelational = value;
1049    m_RelationalFormat = new Instances[value];
1050  }
1051 
1052  /**
1053   * returns the current number of relational attributes
1054   *
1055   * @return            the number of relational attributes
1056   */
1057  public int getNumRelational() {
1058    return m_NumRelational;
1059  }
1060 
1061  /**
1062   * sets the number of nominal attributes in a relational attribute
1063   *
1064   * @param value       the number of nominal attributes
1065   */
1066  public void setNumRelationalNominal(int value) {
1067    m_NumRelationalNominal = value;
1068  }
1069 
1070  /**
1071   * returns the current number of nominal attributes in a relational attribute
1072   *
1073   * @return            the number of nominal attributes
1074   */
1075  public int getNumRelationalNominal() {
1076    return m_NumRelationalNominal;
1077  }
1078 
1079  /**
1080   * sets the number of values for nominal attributes in a relational attribute
1081   *
1082   * @param value       the number of values
1083   */
1084  public void setNumRelationalNominalValues(int value) {
1085    m_NumRelationalNominalValues = value;
1086  }
1087 
1088  /**
1089   * returns the current number of values for nominal attributes in a relational attribute
1090   *
1091   * @return            the number of values
1092   */
1093  public int getNumRelationalNominalValues() {
1094    return m_NumRelationalNominalValues;
1095  }
1096 
1097  /**
1098   * sets the number of numeric attributes in a relational attribute
1099   *
1100   * @param value       the number of numeric attributes
1101   */
1102  public void setNumRelationalNumeric(int value) {
1103    m_NumRelationalNumeric = value;
1104  }
1105 
1106  /**
1107   * returns the current number of numeric attributes in a relational attribute
1108   *
1109   * @return            the number of numeric attributes
1110   */
1111  public int getNumRelationalNumeric() {
1112    return m_NumRelationalNumeric;
1113  }
1114 
1115  /**
1116   * sets the number of string attributes in a relational attribute
1117   *
1118   * @param value       the number of string attributes
1119   */
1120  public void setNumRelationalString(int value) {
1121    m_NumRelationalString = value;
1122  }
1123 
1124  /**
1125   * returns the current number of string attributes in a relational attribute
1126   *
1127   * @return            the number of string attributes
1128   */
1129  public int getNumRelationalString() {
1130    return m_NumRelationalString;
1131  }
1132 
1133  /**
1134   * sets the number of date attributes in a relational attribute
1135   *
1136   * @param value       the number of date attributes
1137   */
1138  public void setNumRelationalDate(int value) {
1139    m_NumRelationalDate = value;
1140  }
1141 
1142  /**
1143   * returns the current number of date attributes in a relational attribute
1144   *
1145   * @return            the number of date attributes
1146   */
1147  public int getNumRelationalDate() {
1148    return m_NumRelationalDate;
1149  }
1150 
1151  /**
1152   * sets the number of instances in relational/bag attributes to produce
1153   *
1154   * @param value       the number of instances
1155   */
1156  public void setNumInstancesRelational(int value) {
1157    m_NumInstancesRelational = value;
1158  }
1159 
1160  /**
1161   * returns the current number of instances in relational/bag attributes to produce
1162   *
1163   * @return            the number of instances
1164   */
1165  public int getNumInstancesRelational() {
1166    return m_NumInstancesRelational;
1167  }
1168
1169  /**
1170   * sets whether multi-instance data should be generated (with a fixed
1171   * data structure)
1172   *
1173   * @param value       whether multi-instance data is generated
1174   */
1175  public void setMultiInstance(boolean value) {
1176    m_MultiInstance = value;
1177  }
1178 
1179  /**
1180   * Gets whether multi-instance data (with a fixed structure) is generated
1181   *
1182   * @return            true if multi-instance data is generated
1183   */
1184  public boolean getMultiInstance() {
1185    return m_MultiInstance;
1186  }
1187 
1188  /**
1189   * sets the structure for the bags for the relational attribute
1190   *
1191   * @param index       the index of the relational attribute
1192   * @param value       the new structure
1193   */
1194  public void setRelationalFormat(int index, Instances value) {
1195    if (value != null)
1196      m_RelationalFormat[index] = new Instances(value, 0);
1197    else
1198      m_RelationalFormat[index] = null;
1199  }
1200 
1201  /**
1202   * returns the format for the specified relational attribute, can be null
1203   *
1204   * @param index       the index of the relational attribute
1205   * @return            the current structure
1206   */
1207  public Instances getRelationalFormat(int index) {
1208    return m_RelationalFormat[index];
1209  }
1210
1211  /**
1212   * sets the structure for the relational class attribute
1213   *
1214   * @param value       the structure for the relational attribute
1215   */
1216  public void setRelationalClassFormat(Instances value) {
1217    if (value != null)
1218      m_RelationalClassFormat = new Instances(value, 0);
1219    else
1220      m_RelationalClassFormat = null;
1221  }
1222 
1223  /**
1224   * returns the current strcuture of the relational class attribute, can
1225   * be null
1226   *
1227   * @return            the relational structure of the class attribute
1228   */
1229  public Instances getRelationalClassFormat() {
1230    return m_RelationalClassFormat;
1231  }
1232 
1233  /**
1234   * returns the overall number of attributes (incl. class, if that is also
1235   * generated)
1236   *
1237   * @return            the overall number of attributes
1238   */
1239  public int getNumAttributes() {
1240    int         result;
1241   
1242    result = m_NumNominal + m_NumNumeric + m_NumString + m_NumDate + m_NumRelational;
1243   
1244    if (!getNoClass())
1245      result++;
1246     
1247    return result;
1248  }
1249 
1250  /**
1251   * returns the current dataset, can be null
1252   *
1253   * @return            the current dataset
1254   */
1255  public Instances getData() {
1256    return m_Data;
1257  }
1258 
1259  /**
1260   * sets the Capabilities handler to generate the data for
1261   *
1262   * @param value       the handler to generate the data for
1263   */
1264  public void setHandler(CapabilitiesHandler value) {
1265    m_Handler = value;
1266  }
1267 
1268  /**
1269   * returns the current set CapabilitiesHandler to generate the dataset
1270   * for, can be null
1271   *
1272   * @return            the handler to generate the data for
1273   */
1274  public CapabilitiesHandler getHandler() {
1275    return m_Handler;
1276  }
1277 
1278  /**
1279   * creates a new Attribute of the given type
1280   *
1281   * @param index the index of the current attribute (0-based)
1282   * @param attType the attribute type (NUMERIC, NOMINAL, etc.)
1283   * @return the configured attribute
1284   * @throws Exception if something goes wrong, e.g., an unknown attribute type
1285   *
1286   * @see Attribute#type()
1287   * @see #CLASS_IS_LAST
1288   * @see #NO_CLASS
1289   */
1290  protected Attribute generateAttribute(int index, int attType) throws Exception {
1291    Attribute     result;
1292    String        name;
1293    int           valIndex;
1294    int           nomCount;
1295    String        prefix;
1296   
1297    result = null;
1298
1299    // determine name and start-index
1300    if (index == CLASS_IS_LAST) {
1301      valIndex = 0;
1302      name     = "Class";
1303      prefix   = "class";
1304      nomCount = getNumClasses();
1305    }
1306    else {
1307      valIndex = index;
1308      nomCount = getNumNominalValues();
1309      prefix   = "att" + (valIndex + 1) + "val";
1310     
1311      switch (attType) {
1312        case Attribute.NOMINAL:
1313          name = "Nominal" + (valIndex + 1);
1314          break;
1315         
1316        case Attribute.NUMERIC:
1317          name = "Numeric" + (valIndex + 1);
1318          break;
1319         
1320        case Attribute.STRING:
1321          name = "String" + (valIndex + 1);
1322          break;
1323         
1324        case Attribute.DATE:
1325          name = "Date" + (valIndex + 1);
1326          break;
1327         
1328        case Attribute.RELATIONAL:
1329          name = "Relational" + (valIndex + 1);
1330          break;
1331         
1332        default:
1333          throw new IllegalArgumentException("Attribute type '" + attType + "' unknown!");
1334      }
1335    }
1336   
1337    switch (attType) {
1338      case Attribute.NOMINAL:
1339        ArrayList<String> nomStrings = new ArrayList<String>(valIndex + 1);
1340        for (int j = 0; j < nomCount; j++)
1341          nomStrings.add(prefix + (j + 1));
1342        result = new Attribute(name, nomStrings);
1343        break;
1344       
1345      case Attribute.NUMERIC:
1346        result = new Attribute(name);
1347        break;
1348       
1349      case Attribute.STRING:
1350        result = new Attribute(name, (ArrayList<String>) null);
1351        break;
1352       
1353      case Attribute.DATE:
1354        result = new Attribute(name, "yyyy-mm-dd");
1355        break;
1356       
1357      case Attribute.RELATIONAL:
1358        Instances rel;
1359        if (index == CLASS_IS_LAST)
1360          rel = getRelationalClassFormat();
1361        else
1362          rel = getRelationalFormat(index);
1363       
1364        if (rel == null) {
1365          TestInstances dataset = new TestInstances();
1366          dataset.setNumNominal(getNumRelationalNominal());
1367          dataset.setNumNominalValues(getNumRelationalNominalValues());
1368          dataset.setNumNumeric(getNumRelationalNumeric());
1369          dataset.setNumString(getNumRelationalString());
1370          dataset.setNumDate(getNumRelationalDate());
1371          dataset.setNumInstances(0);
1372          dataset.setClassType(Attribute.NOMINAL);  // dummy to avoid endless recursion, will be deleted anyway
1373          rel = new Instances(dataset.generate());
1374          if (!getNoClass()) {
1375            int clsIndex = rel.classIndex();
1376            rel.setClassIndex(-1);
1377            rel.deleteAttributeAt(clsIndex);
1378          }
1379        }
1380        result = new Attribute(name, rel);
1381        break;
1382       
1383      default:
1384        throw new IllegalArgumentException("Attribute type '" + attType + "' unknown!");
1385    }
1386   
1387    return result;
1388  }
1389 
1390  /**
1391   * Generates the class value
1392   *
1393   * @param data        the dataset to work on
1394   * @return            the new class value
1395   * @throws Exception  if something goes wrong
1396   */
1397  protected double generateClassValue(Instances data) throws Exception {
1398    double result = Double.NaN;
1399   
1400    switch (m_ClassType) {
1401      case Attribute.NUMERIC:
1402        result = m_Random.nextFloat() * 0.25
1403            + Math.abs(m_Random.nextInt())
1404            % Math.max(2, m_NumNominal);
1405        break;
1406       
1407      case Attribute.NOMINAL:
1408        result = Math.abs(m_Random.nextInt()) % data.numClasses();
1409        break;
1410       
1411      case Attribute.STRING:
1412        String str = "";
1413        for (int n = 0; n < m_Words.length; n++) {
1414          if ( (n > 0) && (m_WordSeparators.length() != 0) )
1415            str += m_WordSeparators.charAt(m_Random.nextInt(m_WordSeparators.length()));
1416          str += m_Words[m_Random.nextInt(m_Words.length)];
1417        }
1418        result = data.classAttribute().addStringValue(str);
1419        break;
1420       
1421      case Attribute.DATE:
1422        result = data.classAttribute().parseDate(
1423                (2000 + m_Random.nextInt(100)) + "-01-01");
1424        break;
1425       
1426      case Attribute.RELATIONAL:
1427        if (getRelationalClassFormat() != null) {
1428          result = data.classAttribute().addRelation(getRelationalClassFormat());
1429        }
1430        else {
1431          TestInstances dataset = new TestInstances();
1432          dataset.setNumNominal(getNumRelationalNominal());
1433          dataset.setNumNominalValues(getNumRelationalNominalValues());
1434          dataset.setNumNumeric(getNumRelationalNumeric());
1435          dataset.setNumString(getNumRelationalString());
1436          dataset.setNumDate(getNumRelationalDate());
1437          dataset.setNumInstances(getNumInstancesRelational());
1438          dataset.setClassType(Attribute.NOMINAL);  // dummy to avoid endless recursion, will be deleted anyway
1439          Instances rel = new Instances(dataset.generate());
1440          int clsIndex = rel.classIndex();
1441          rel.setClassIndex(-1);
1442          rel.deleteAttributeAt(clsIndex);
1443          result = data.classAttribute().addRelation(rel);
1444        }
1445        break;
1446    }
1447   
1448    return result;
1449  }
1450 
1451  /**
1452   * Generates a new value for the specified attribute. The classValue
1453   * might be used in the process.
1454   *
1455   * @param data          the dataset to work on
1456   * @param index         the index of the attribute
1457   * @param classVal      the class value for the current instance, might be
1458   *                      used in the calculation
1459   * @return              the new attribute value
1460   * @throws Exception    if something goes wrong
1461   */
1462  protected double generateAttributeValue(Instances data, int index, double classVal) throws Exception {
1463    double result = Double.NaN;
1464   
1465    switch (data.attribute(index).type()) {
1466      case Attribute.NUMERIC:
1467        result = classVal * 4 + m_Random.nextFloat() * 1 - 0.5;
1468        break;
1469       
1470      case Attribute.NOMINAL:
1471        if (m_Random.nextFloat() < 0.2) {
1472          result = Math.abs(m_Random.nextInt())
1473          % data.attribute(index).numValues();
1474        } else {
1475          result = ((int)classVal) % data.attribute(index).numValues();
1476        }
1477        //result = m_Random.nextInt(data.attribute(index).numValues());
1478        break;
1479       
1480      case Attribute.STRING:
1481        String str = "";
1482        for (int n = 0; n < m_Words.length; n++) {
1483          if ( (n > 0) && (m_WordSeparators.length() != 0) )
1484            str += m_WordSeparators.charAt(m_Random.nextInt(m_WordSeparators.length()));
1485          str += m_Words[m_Random.nextInt(m_Words.length)];
1486        }
1487        result = data.attribute(index).addStringValue(str);
1488        break;
1489       
1490      case Attribute.DATE:
1491        result = data.attribute(index).parseDate(
1492                (2000 + m_Random.nextInt(100)) + "-01-01");
1493        break;
1494       
1495      case Attribute.RELATIONAL:
1496        Instances rel = new Instances(data.attribute(index).relation(), 0);
1497        for (int n = 0; n < getNumInstancesRelational(); n++) {
1498          Instance inst = new DenseInstance(rel.numAttributes());
1499          inst.setDataset(data);
1500          for (int i = 0; i < rel.numAttributes(); i++) {
1501            inst.setValue(i, generateAttributeValue(rel, i, 0));
1502          }
1503          rel.add(inst);
1504        }
1505        result = data.attribute(index).addRelation(rel);
1506        break;
1507    }
1508   
1509    return result;
1510  }
1511 
1512  /**
1513   * generates a new dataset.
1514   *
1515   * @return            the generated data
1516   * @throws Exception  if something goes wrong
1517   */
1518  public Instances generate() throws Exception {
1519    if (getMultiInstance()) {
1520      TestInstances bag = (TestInstances) this.clone();
1521      bag.setMultiInstance(false);
1522      bag.setNumInstances(0);
1523      bag.setSeed(m_Random.nextInt());
1524      Instances bagFormat = bag.generate();
1525      bagFormat.setClassIndex(-1);
1526      bagFormat.deleteAttributeAt(bagFormat.numAttributes() - 1);
1527
1528      // generate multi-instance structure
1529      TestInstances structure = new TestInstances();
1530      structure.setSeed(m_Random.nextInt());
1531      structure.setNumNominal(1);
1532      structure.setNumRelational(1);
1533      structure.setRelationalFormat(0, bagFormat);
1534      structure.setClassType(getClassType());
1535      structure.setNumClasses(getNumClasses());
1536      structure.setRelationalClassFormat(getRelationalClassFormat());
1537      structure.setNumInstances(getNumInstances());
1538      m_Data = structure.generate();
1539     
1540      // generate bags
1541      bag.setNumInstances(getNumInstancesRelational());
1542      for (int i = 0; i < getNumInstances(); i++) {
1543        bag.setSeed(m_Random.nextInt());
1544        Instances bagData = new Instances(bag.generate());
1545        bagData.setClassIndex(-1);
1546        bagData.deleteAttributeAt(bagData.numAttributes() - 1);
1547        double val = m_Data.attribute(1).addRelation(bagData);
1548        m_Data.instance(i).setValue(1, val);
1549      }
1550    }
1551    else {
1552      // initialize
1553      int clsIndex = m_ClassIndex;
1554      if (clsIndex == CLASS_IS_LAST)
1555        clsIndex = getNumAttributes() - 1;
1556
1557      // generate attributes
1558      ArrayList<Attribute> attributes = new ArrayList<Attribute>(getNumAttributes());
1559      // Add Nominal attributes
1560      for (int i = 0; i < getNumNominal(); i++)
1561        attributes.add(generateAttribute(i, Attribute.NOMINAL));
1562     
1563      // Add m_Numeric attributes
1564      for (int i = 0; i < getNumNumeric(); i++)
1565        attributes.add(generateAttribute(i, Attribute.NUMERIC));
1566     
1567      // Add some String attributes...
1568      for (int i = 0; i < getNumString(); i++)
1569        attributes.add(generateAttribute(i, Attribute.STRING));
1570     
1571      // Add some Date attributes...
1572      for (int i = 0; i < getNumDate(); i++)
1573        attributes.add(generateAttribute(i, Attribute.DATE));
1574     
1575      // Add some Relational attributes...
1576      for (int i = 0; i < getNumRelational(); i++)
1577        attributes.add(generateAttribute(i, Attribute.RELATIONAL));
1578     
1579      // Add class attribute
1580      if (clsIndex != NO_CLASS)
1581        attributes.add(clsIndex, generateAttribute(CLASS_IS_LAST, getClassType()));
1582     
1583      m_Data = new Instances(getRelation(), attributes, getNumInstances());
1584      m_Data.setClassIndex(clsIndex);
1585
1586      // generate instances
1587      for (int i = 0; i < getNumInstances(); i++) {
1588        Instance current = new DenseInstance(getNumAttributes());
1589        current.setDataset(m_Data);
1590
1591        // class
1592        double classVal;
1593        if (clsIndex != NO_CLASS) {
1594          classVal = generateClassValue(m_Data);
1595          current.setClassValue(classVal);
1596        }
1597        else {
1598          classVal = m_Random.nextFloat();
1599        }
1600       
1601        // other attributes
1602        for (int n = 0; n < getNumAttributes(); n++) {
1603          if (clsIndex == n)
1604            continue;
1605         
1606          current.setValue(n, generateAttributeValue(m_Data, n, classVal));
1607        }
1608       
1609        m_Data.add(current);
1610      }
1611    }
1612
1613    if (m_Data.classIndex() == NO_CLASS)
1614      m_Data.setClassIndex(-1);
1615   
1616    return getData();
1617  }
1618 
1619  /**
1620   * returns a TestInstances instance setup already for the the given
1621   * capabilities.
1622   *
1623   * @param c           the capabilities to base the TestInstances on
1624   * @return            the configured TestInstances object
1625   */
1626  public static TestInstances forCapabilities(Capabilities c) {
1627    TestInstances       result;
1628   
1629    result = new TestInstances();
1630   
1631    // multi-instance?
1632    if (c.getOwner() instanceof MultiInstanceCapabilitiesHandler) {
1633      Capabilities multi = (Capabilities) ((MultiInstanceCapabilitiesHandler) c.getOwner()).getMultiInstanceCapabilities().clone();
1634      multi.setOwner(null);  // otherwise recursive!
1635      result = forCapabilities(multi);
1636      result.setMultiInstance(true);
1637    }
1638    else  {
1639      // class
1640      if (c.handles(Capability.NO_CLASS))
1641        result.setClassIndex(NO_CLASS);
1642      else if (c.handles(Capability.NOMINAL_CLASS))
1643        result.setClassType(Attribute.NOMINAL);
1644      else if (c.handles(Capability.BINARY_CLASS))
1645        result.setClassType(Attribute.NOMINAL);
1646      else if (c.handles(Capability.NUMERIC_CLASS))
1647        result.setClassType(Attribute.NUMERIC);
1648      else if (c.handles(Capability.DATE_CLASS))
1649        result.setClassType(Attribute.DATE);
1650      else if (c.handles(Capability.STRING_CLASS))
1651        result.setClassType(Attribute.STRING);
1652      else if (c.handles(Capability.RELATIONAL_CLASS))
1653        result.setClassType(Attribute.RELATIONAL);
1654
1655      // # of classes
1656      if (c.handles(Capability.UNARY_CLASS))
1657        result.setNumClasses(1);
1658      if (c.handles(Capability.BINARY_CLASS))
1659        result.setNumClasses(2);
1660      if (c.handles(Capability.NOMINAL_CLASS))
1661        result.setNumClasses(4);
1662     
1663      // attributes
1664      if (c.handles(Capability.NOMINAL_ATTRIBUTES)) {
1665        result.setNumNominal(1);
1666        result.setNumRelationalNominal(1);
1667      }
1668      else {
1669        result.setNumNominal(0);
1670        result.setNumRelationalNominal(0);
1671      }
1672
1673      if (c.handles(Capability.NUMERIC_ATTRIBUTES)) {
1674        result.setNumNumeric(1);
1675        result.setNumRelationalNumeric(1);
1676      }
1677      else {
1678        result.setNumNumeric(0);
1679        result.setNumRelationalNumeric(0);
1680      }
1681
1682      if (c.handles(Capability.DATE_ATTRIBUTES)) {
1683        result.setNumDate(1);
1684        result.setNumRelationalDate(1);
1685      }
1686      else {
1687        result.setNumDate(0);
1688        result.setNumRelationalDate(0);
1689      }
1690     
1691      if (c.handles(Capability.STRING_ATTRIBUTES)) {
1692        result.setNumString(1);
1693        result.setNumRelationalString(1);
1694      }
1695      else {
1696        result.setNumString(0);
1697        result.setNumRelationalString(0);
1698      }
1699     
1700      if (c.handles(Capability.RELATIONAL_ATTRIBUTES))
1701        result.setNumRelational(1);
1702      else
1703        result.setNumRelational(0);
1704    }
1705   
1706    return result;
1707  }
1708 
1709  /**
1710   * returns a string representation of the object
1711   *
1712   * @return            a string representation of the object
1713   */
1714  public String toString() {
1715    String      result;
1716   
1717    result = "";
1718    result += "Relation: " + getRelation() + "\n";
1719    result += "Seed: " + getSeed() + "\n";
1720    result += "# Instances: " + getNumInstances() + "\n";
1721    result += "ClassType: " + getClassType() + "\n";
1722    result += "# Classes: " + getNumClasses() + "\n";
1723    result += "Class index: " + getClassIndex() + "\n";
1724    result += "# Nominal: " +     getNumNominal() + "\n";
1725    result += "# Nominal values: " + getNumNominalValues() + "\n";
1726    result += "# Numeric: " + getNumNumeric() + "\n";
1727    result += "# String: " + getNumString() + "\n";
1728    result += "# Date: " + getNumDate() + "\n";
1729    result += "# Relational: " + getNumRelational() + "\n";
1730    result += "  - # Nominal: " +     getNumRelationalNominal() + "\n";
1731    result += "  - # Nominal values: " + getNumRelationalNominalValues() + "\n";
1732    result += "  - # Numeric: " + getNumRelationalNumeric() + "\n";
1733    result += "  - # String: " + getNumRelationalString() + "\n";
1734    result += "  - # Date: " + getNumRelationalDate() + "\n";
1735    result += "  - # Instances: " + getNumInstancesRelational() + "\n";
1736    result += "Multi-Instance: " + getMultiInstance() + "\n";
1737    result += "Words: " + getWords() + "\n";
1738    result += "Word separators: " + getWordSeparators() + "\n";
1739   
1740    return result;
1741  }
1742 
1743  /**
1744   * Returns the revision string.
1745   *
1746   * @return            the revision
1747   */
1748  public String getRevision() {
1749    return RevisionUtils.extract("$Revision: 5987 $");
1750  }
1751 
1752  /**
1753   * for running the class from commandline, prints the generated data
1754   * to stdout
1755   *
1756   * @param args        the commandline parameters
1757   * @throws Exception  if something goes wrong
1758   */
1759  public static void main(String[] args) throws Exception {
1760    TestInstances inst;
1761   
1762    inst = new TestInstances();
1763
1764    // help requested?
1765    if (Utils.getFlag("h", args) || Utils.getFlag("help", args)) {
1766      StringBuffer result = new StringBuffer();
1767      result.append("\nTest data generator options:\n\n");
1768
1769      result.append("-h|-help\n\tprints this help\n");
1770     
1771      Enumeration enm = inst.listOptions();
1772      while (enm.hasMoreElements()) {
1773        Option option = (Option) enm.nextElement();
1774        result.append(option.synopsis() + "\n" + option.description() + "\n");
1775      }
1776
1777      System.out.println(result);
1778      System.exit(0);
1779    }
1780   
1781    // generate data
1782    inst.setOptions(args);
1783    System.out.println(inst.generate());
1784  }
1785}
Note: See TracBrowser for help on using the repository browser.