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

« back to all changes in this revision

Viewing changes to weka/datagenerators/clusterers/SubspaceClusterDefinition.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
 * SubspaceClusterDefinition.java
 
19
 * Copyright (C) 2005 University of Waikato, Hamilton, New Zealand
 
20
 *
 
21
 */
 
22
 
 
23
package weka.datagenerators.clusterers;
 
24
 
 
25
import weka.core.Option;
 
26
import weka.core.Range;
 
27
import weka.core.SelectedTag;
 
28
import weka.core.Utils;
 
29
import weka.datagenerators.ClusterDefinition;
 
30
import weka.datagenerators.ClusterGenerator;
 
31
 
 
32
import java.util.Enumeration;
 
33
import java.util.Random;
 
34
import java.util.StringTokenizer;
 
35
import java.util.Vector;
 
36
 
 
37
/**
 
38
 <!-- globalinfo-start -->
 
39
 * A single cluster for the SubspaceCluster datagenerator
 
40
 * <p/>
 
41
 <!-- globalinfo-end -->
 
42
 *
 
43
 <!-- options-start -->
 
44
 * Valid options are: <p/>
 
45
 * 
 
46
 * <pre> -A &lt;range&gt;
 
47
 *  Generates randomly distributed instances in the cluster.</pre>
 
48
 * 
 
49
 * <pre> -U &lt;range&gt;
 
50
 *  Generates uniformly distributed instances in the cluster.</pre>
 
51
 * 
 
52
 * <pre> -G &lt;range&gt;
 
53
 *  Generates gaussian distributed instances in the cluster.</pre>
 
54
 * 
 
55
 * <pre> -D &lt;num&gt;,&lt;num&gt;
 
56
 *  The attribute min/max (-A and -U) or mean/stddev (-G) for
 
57
 *  the cluster.</pre>
 
58
 * 
 
59
 * <pre> -N &lt;num&gt;..&lt;num&gt;
 
60
 *  The range of number of instances per cluster (default 1..50).</pre>
 
61
 * 
 
62
 * <pre> -I
 
63
 *  Uses integer instead of continuous values (default continuous).</pre>
 
64
 * 
 
65
 <!-- options-end -->
 
66
 *
 
67
 * @author  Gabi Schmidberger (gabi@cs.waikato.ac.nz)
 
68
 * @author  FracPete (fracpete at waikato dot ac dot nz)
 
69
 * @version $Revision: 1.4 $
 
70
 * @see SubspaceCluster
 
71
 */
 
72
public class SubspaceClusterDefinition 
 
73
  extends ClusterDefinition {
 
74
 
 
75
  /** for serialization */
 
76
  static final long serialVersionUID = 3135678125044007231L;
 
77
  
 
78
  /** cluster type */
 
79
  protected int m_clustertype;
 
80
 
 
81
  /** cluster subtypes */
 
82
  protected int m_clustersubtype;
 
83
 
 
84
  /** number of attributes the cluster is defined for */
 
85
  protected int m_numClusterAttributes;
 
86
 
 
87
  /** number of instances for this cluster */
 
88
  protected int m_numInstances;
 
89
 
 
90
  /** minimal number of instances for this cluster */
 
91
  protected int m_MinInstNum;
 
92
 
 
93
  /** maximal number of instances for this cluster */
 
94
  protected int m_MaxInstNum;
 
95
 
 
96
  /** range of atttributes */
 
97
  protected Range m_AttrIndexRange;
 
98
 
 
99
  /** attributes of this cluster */
 
100
  protected boolean[] m_attributes;
 
101
 
 
102
  /** global indices of the attributes of the cluster */
 
103
  protected int[] m_attrIndices;
 
104
 
 
105
  /** ranges of each attribute (min); not used if gaussian */
 
106
  protected double[] m_minValue;
 
107
 
 
108
  /** ranges of each attribute (max); not used if gaussian */
 
109
  protected double[] m_maxValue;
 
110
 
 
111
  /** mean ; only used if gaussian */
 
112
  protected double[] m_meanValue;
 
113
  
 
114
  /** standarddev; only used if gaussian */
 
115
  protected double[] m_stddevValue;
 
116
 
 
117
  /**
 
118
   * initializes the cluster, without a parent cluster (necessary for GOE)
 
119
   */
 
120
  public SubspaceClusterDefinition() {
 
121
    super();
 
122
  }
 
123
 
 
124
  /**
 
125
   * initializes the cluster with default values
 
126
   *
 
127
   * @param parent    the datagenerator this cluster belongs to
 
128
   */
 
129
  public SubspaceClusterDefinition(ClusterGenerator parent) {
 
130
    super(parent);
 
131
  }
 
132
 
 
133
  /**
 
134
   * sets the default values
 
135
   * 
 
136
   * @throws Exception if setting of defaults fails
 
137
   */
 
138
  protected void setDefaults() throws Exception {
 
139
    setClusterType(defaultClusterType());
 
140
    setClusterSubType(defaultClusterSubType());
 
141
    setMinInstNum(defaultMinInstNum());
 
142
    setMaxInstNum(defaultMaxInstNum());
 
143
    setAttrIndexRange(defaultAttrIndexRange());
 
144
    m_numClusterAttributes = 1;
 
145
    setValuesList(defaultValuesList());
 
146
  }
 
147
 
 
148
  
 
149
  /**
 
150
   * Returns a string describing this data generator.
 
151
   *
 
152
   * @return a description of the data generator suitable for
 
153
   * displaying in the explorer/experimenter gui
 
154
   */
 
155
  public String globalInfo() {
 
156
    return "A single cluster for the SubspaceCluster datagenerator";
 
157
  }
 
158
  /**
 
159
   * Returns an enumeration describing the available options.
 
160
   *
 
161
   * @return an enumeration of all the available options
 
162
   */
 
163
  public Enumeration listOptions() {
 
164
    Vector result = new Vector();
 
165
 
 
166
    result.addElement(new Option(
 
167
          "\tGenerates randomly distributed instances in the cluster.",
 
168
          "A", 1, "-A <range>"));
 
169
 
 
170
    result.addElement(new Option(
 
171
          "\tGenerates uniformly distributed instances in the cluster.",
 
172
          "U", 1, "-U <range>"));
 
173
 
 
174
    result.addElement(new Option(
 
175
          "\tGenerates gaussian distributed instances in the cluster.",
 
176
          "G", 1, "-G <range>"));
 
177
 
 
178
    result.addElement(new Option(
 
179
          "\tThe attribute min/max (-A and -U) or mean/stddev (-G) for\n"
 
180
          + "\tthe cluster.",
 
181
          "D", 1, "-D <num>,<num>"));
 
182
 
 
183
    result.addElement(new Option(
 
184
          "\tThe range of number of instances per cluster (default "
 
185
          + defaultMinInstNum() + ".." + defaultMaxInstNum() + ").",
 
186
          "N", 1, "-N <num>..<num>"));
 
187
 
 
188
    result.addElement(new Option(
 
189
          "\tUses integer instead of continuous values (default continuous).",
 
190
          "I", 0, "-I"));
 
191
 
 
192
    return result.elements();
 
193
  }
 
194
 
 
195
  /**
 
196
   * Parses a list of options for this object. <p/>
 
197
   *
 
198
   <!-- options-start -->
 
199
   * Valid options are: <p/>
 
200
   * 
 
201
   * <pre> -A &lt;range&gt;
 
202
   *  Generates randomly distributed instances in the cluster.</pre>
 
203
   * 
 
204
   * <pre> -U &lt;range&gt;
 
205
   *  Generates uniformly distributed instances in the cluster.</pre>
 
206
   * 
 
207
   * <pre> -G &lt;range&gt;
 
208
   *  Generates gaussian distributed instances in the cluster.</pre>
 
209
   * 
 
210
   * <pre> -D &lt;num&gt;,&lt;num&gt;
 
211
   *  The attribute min/max (-A and -U) or mean/stddev (-G) for
 
212
   *  the cluster.</pre>
 
213
   * 
 
214
   * <pre> -N &lt;num&gt;..&lt;num&gt;
 
215
   *  The range of number of instances per cluster (default 1..50).</pre>
 
216
   * 
 
217
   * <pre> -I
 
218
   *  Uses integer instead of continuous values (default continuous).</pre>
 
219
   * 
 
220
   <!-- options-end -->
 
221
   *
 
222
   * @param options the list of options as an array of strings
 
223
   * @throws Exception if an option is not supported
 
224
   */
 
225
  public void setOptions(String[] options) throws Exception {
 
226
    String        tmpStr;
 
227
    String        fromToStr;
 
228
    int           typeCount;
 
229
 
 
230
    typeCount = 0;
 
231
    fromToStr = "";
 
232
 
 
233
    tmpStr = Utils.getOption('A', options);
 
234
    if (tmpStr.length() != 0) {
 
235
      fromToStr = tmpStr;
 
236
      setClusterType(
 
237
          new SelectedTag(
 
238
            SubspaceCluster.UNIFORM_RANDOM, SubspaceCluster.TAGS_CLUSTERTYPE));
 
239
      typeCount++;
 
240
    }
 
241
 
 
242
    tmpStr = Utils.getOption('U', options);
 
243
    if (tmpStr.length() != 0) {
 
244
      fromToStr = tmpStr;
 
245
      setClusterType(
 
246
          new SelectedTag(
 
247
            SubspaceCluster.TOTAL_UNIFORM, SubspaceCluster.TAGS_CLUSTERTYPE));
 
248
      typeCount++;
 
249
    }
 
250
 
 
251
    tmpStr = Utils.getOption('G', options);
 
252
    if (tmpStr.length() != 0) {
 
253
      fromToStr = tmpStr;
 
254
      setClusterType(
 
255
          new SelectedTag(
 
256
            SubspaceCluster.GAUSSIAN, SubspaceCluster.TAGS_CLUSTERTYPE));
 
257
      typeCount++;
 
258
    }
 
259
 
 
260
    // default is uniform/random
 
261
    if (typeCount == 0)
 
262
      setClusterType(
 
263
          new SelectedTag(
 
264
            SubspaceCluster.UNIFORM_RANDOM, SubspaceCluster.TAGS_CLUSTERTYPE));
 
265
    else if (typeCount > 1)
 
266
      throw new Exception("Only one cluster type can be specified!");
 
267
 
 
268
    setAttrIndexRange(fromToStr);
 
269
    
 
270
    tmpStr = Utils.getOption('D', options);
 
271
    if (isGaussian()) {
 
272
      if (tmpStr.length() != 0)
 
273
        setMeanStddev(tmpStr);
 
274
      else
 
275
        setMeanStddev(defaultMeanStddev());
 
276
    }
 
277
    else {
 
278
      if (tmpStr.length() != 0)
 
279
        setValuesList(tmpStr);
 
280
      else
 
281
        setValuesList(defaultValuesList());
 
282
    }
 
283
 
 
284
    tmpStr = Utils.getOption('N', options);
 
285
    if (tmpStr.length() != 0)
 
286
      setInstNums(tmpStr);
 
287
    else
 
288
      setInstNums(defaultMinInstNum() + ".." + defaultMaxInstNum());
 
289
 
 
290
    if (Utils.getFlag('I', options))
 
291
      setClusterSubType(
 
292
          new SelectedTag(
 
293
            SubspaceCluster.INTEGER, SubspaceCluster.TAGS_CLUSTERSUBTYPE));
 
294
    else
 
295
      setClusterSubType(
 
296
          new SelectedTag(
 
297
            SubspaceCluster.CONTINUOUS, SubspaceCluster.TAGS_CLUSTERSUBTYPE));
 
298
  }
 
299
 
 
300
  /**
 
301
   * Gets the current settings of the datagenerator BIRCHCluster.
 
302
   *
 
303
   * @return an array of strings suitable for passing to setOptions
 
304
   */
 
305
  public String[] getOptions() {
 
306
    Vector        result;
 
307
 
 
308
    result  = new Vector();
 
309
 
 
310
    if (isRandom()) {
 
311
      result.add("-A");
 
312
      result.add("" + getAttrIndexRange());
 
313
      result.add("-D");
 
314
      result.add("" + getValuesList());
 
315
    }
 
316
    else if (isUniform()) {
 
317
      result.add("-U");
 
318
      result.add("" + getAttrIndexRange());
 
319
      result.add("-D");
 
320
      result.add("" + getValuesList());
 
321
    }
 
322
    else if (isGaussian()) {
 
323
      result.add("-G");
 
324
      result.add("" + getAttrIndexRange());
 
325
      result.add("-D");
 
326
      result.add("" + getMeanStddev());
 
327
    }
 
328
 
 
329
    result.add("-N"); 
 
330
    result.add("" + getInstNums());
 
331
 
 
332
    if (m_clustersubtype == SubspaceCluster.INTEGER)
 
333
      result.add("-I");
 
334
 
 
335
    return (String[]) result.toArray(new String[result.size()]);
 
336
  }
 
337
 
 
338
  /**
 
339
   * Make a string from the attribues list.
 
340
   * 
 
341
   * @return the attributes as string
 
342
   */
 
343
  public String attributesToString() {
 
344
    StringBuffer text = new StringBuffer();
 
345
    int j = 0;
 
346
    for (int i = 0; i < m_attributes.length; i++) {
 
347
      if (m_attributes[i]) {
 
348
        if (isGaussian()) {
 
349
          text.append(" Attribute: " + i);
 
350
          text.append(" Mean: "+ m_meanValue[j]);
 
351
          text.append(" StdDev: "+m_stddevValue[j]+"\n%");
 
352
        } 
 
353
        else {
 
354
          text.append(" Attribute: " + i);
 
355
          text.append(" Range: "+ m_minValue[j]);
 
356
          text.append(" - "+m_maxValue[j]+"\n%");
 
357
        }
 
358
        j++;
 
359
      }
 
360
    }
 
361
    return text.toString();
 
362
  }
 
363
 
 
364
  /**
 
365
   * Make a string from the cluster features.
 
366
   * 
 
367
   * @return the cluster features as string
 
368
   */
 
369
  public String toString() {
 
370
    StringBuffer text = new StringBuffer();
 
371
    text.append("attributes " + attributesToString() + "\n");
 
372
    text.append("number of instances " + getInstNums()); 
 
373
    return text.toString();
 
374
  }
 
375
 
 
376
  /**
 
377
   * sets the parent datagenerator this cluster belongs to
 
378
   * @param parent      the parent datagenerator
 
379
   */
 
380
  public void setParent(SubspaceCluster parent) {
 
381
    super.setParent(parent);
 
382
    m_AttrIndexRange.setUpper(getParent().getNumAttributes());
 
383
  }
 
384
 
 
385
  /**
 
386
   * returns the default attribute index range
 
387
   * 
 
388
   * @return the default attribute index range
 
389
   */
 
390
  protected String defaultAttrIndexRange() {
 
391
    return "1";
 
392
  }
 
393
 
 
394
  /**
 
395
   * Sets which attributes are used in the cluster
 
396
   * attributes among the selection will be discretized.
 
397
   *
 
398
   * @param rangeList a string representing the list of attributes. Since
 
399
   * the string will typically come from a user, attributes are indexed from
 
400
   * 1. <br/>
 
401
   * eg: first-3,5,6-last
 
402
   */
 
403
  public void setAttrIndexRange(String rangeList) {
 
404
    m_numClusterAttributes = 0; 
 
405
    if (m_AttrIndexRange == null)
 
406
      m_AttrIndexRange = new Range();
 
407
    m_AttrIndexRange.setRanges(rangeList);
 
408
 
 
409
    if (getParent() != null) {
 
410
      m_AttrIndexRange.setUpper(getParent().getNumAttributes());
 
411
      m_attributes = new boolean [getParent().getNumAttributes()];
 
412
      for (int i = 0; i < m_attributes.length; i++) {
 
413
        if (m_AttrIndexRange.isInRange(i)) {
 
414
          m_numClusterAttributes++;
 
415
          m_attributes[i] = true; 
 
416
        } 
 
417
        else {
 
418
          m_attributes[i] = false; 
 
419
        }
 
420
      }
 
421
 
 
422
      //store translation from attr in cluster to attr in whole dataset
 
423
      m_attrIndices = new int[m_numClusterAttributes];
 
424
      int clusterI = -1;
 
425
      for (int i = 0; i < m_attributes.length; i++) {
 
426
        if (m_AttrIndexRange.isInRange(i)) {
 
427
          clusterI++;
 
428
          m_attrIndices[clusterI] = i;
 
429
        }
 
430
      }
 
431
    }
 
432
  }
 
433
 
 
434
  /**
 
435
   * returns the attribute range(s).
 
436
   * 
 
437
   * @return the attribute range(s).
 
438
   */
 
439
  public String getAttrIndexRange() {
 
440
    return m_AttrIndexRange.getRanges();
 
441
  }
 
442
  
 
443
  /**
 
444
   * Returns the tip text for this property
 
445
   * @return tip text for this property suitable for
 
446
   * displaying in the explorer/experimenter gui
 
447
   */
 
448
  public String attrIndexRangeTipText() {
 
449
    return "The attribute range(s).";
 
450
  }
 
451
 
 
452
  public boolean[] getAttributes() {
 
453
    return m_attributes;
 
454
  }
 
455
 
 
456
  public double[] getMinValue() {
 
457
    return m_minValue;
 
458
  }
 
459
 
 
460
  public double[] getMaxValue() {
 
461
    return m_maxValue;
 
462
  }
 
463
 
 
464
  public double[] getMeanValue() {
 
465
    return m_meanValue;
 
466
  }
 
467
 
 
468
  public double[] getStddevValue() {
 
469
    return m_stddevValue;
 
470
  }
 
471
 
 
472
  public int getNumInstances () { 
 
473
    return m_numInstances; 
 
474
  }
 
475
 
 
476
  /**
 
477
   * returns the default cluster type
 
478
   * 
 
479
   * @return the default cluster type
 
480
   */
 
481
  protected SelectedTag defaultClusterType() {
 
482
    return new SelectedTag(
 
483
        SubspaceCluster.UNIFORM_RANDOM, SubspaceCluster.TAGS_CLUSTERTYPE);
 
484
  }
 
485
  
 
486
  /**
 
487
   * Gets the cluster type.
 
488
   *
 
489
   * @return the cluster type
 
490
   * @see SubspaceCluster#TAGS_CLUSTERTYPE
 
491
   */
 
492
  public SelectedTag getClusterType() {
 
493
    return new SelectedTag(m_clustertype, SubspaceCluster.TAGS_CLUSTERTYPE);
 
494
  }
 
495
  
 
496
  /**
 
497
   * Sets the cluster type.
 
498
   *
 
499
   * @param value the new cluster type.
 
500
   * @see SubspaceCluster#TAGS_CLUSTERTYPE
 
501
   */
 
502
  public void setClusterType(SelectedTag value) {
 
503
    if (value.getTags() == SubspaceCluster.TAGS_CLUSTERTYPE)
 
504
      m_clustertype = value.getSelectedTag().getID();
 
505
  }
 
506
  
 
507
  /**
 
508
   * Returns the tip text for this property
 
509
   * @return tip text for this property suitable for
 
510
   * displaying in the explorer/experimenter gui
 
511
   */
 
512
  public String clusterTypeTipText() {
 
513
    return "The type of cluster to use.";
 
514
  }
 
515
 
 
516
  /**
 
517
   * returns the default cluster sub type
 
518
   * 
 
519
   * @return the default cluster sub type
 
520
   */
 
521
  protected SelectedTag defaultClusterSubType() {
 
522
    return new SelectedTag(
 
523
        SubspaceCluster.CONTINUOUS, SubspaceCluster.TAGS_CLUSTERSUBTYPE);
 
524
  }
 
525
  
 
526
  /**
 
527
   * Gets the cluster sub type.
 
528
   *
 
529
   * @return the cluster sub type
 
530
   * @see SubspaceCluster#TAGS_CLUSTERSUBTYPE
 
531
   */
 
532
  public SelectedTag getClusterSubType() {
 
533
    return new SelectedTag(
 
534
                  m_clustersubtype, SubspaceCluster.TAGS_CLUSTERSUBTYPE);
 
535
  }
 
536
  
 
537
  /**
 
538
   * Sets the cluster sub type.
 
539
   *
 
540
   * @param value the new cluster sub type.
 
541
   * @see SubspaceCluster#TAGS_CLUSTERSUBTYPE
 
542
   */
 
543
  public void setClusterSubType(SelectedTag value) {
 
544
    if (value.getTags() == SubspaceCluster.TAGS_CLUSTERSUBTYPE)
 
545
      m_clustersubtype = value.getSelectedTag().getID();
 
546
  }
 
547
  
 
548
  /**
 
549
   * Returns the tip text for this property
 
550
   * @return tip text for this property suitable for
 
551
   * displaying in the explorer/experimenter gui
 
552
   */
 
553
  public String clusterSubTypeTipText() {
 
554
    return "The sub-type of cluster to use.";
 
555
  }
 
556
 
 
557
  /** 
 
558
   * checks, whether cluster type is random
 
559
   * 
 
560
   * @return true if cluster type is random
 
561
   */
 
562
  public boolean isRandom() {
 
563
    return (m_clustertype == SubspaceCluster.UNIFORM_RANDOM);
 
564
  }
 
565
 
 
566
  /** 
 
567
   * checks, whether cluster type is uniform
 
568
   * 
 
569
   * @return true if cluster type is uniform
 
570
   */
 
571
  public boolean isUniform() {
 
572
    return (m_clustertype == SubspaceCluster.TOTAL_UNIFORM);
 
573
  }
 
574
 
 
575
  /** 
 
576
   * checks, whether cluster type is gaussian
 
577
   * 
 
578
   * @return true if cluster type is gaussian
 
579
   */
 
580
  public boolean isGaussian() {
 
581
    return (m_clustertype == SubspaceCluster.GAUSSIAN);
 
582
  }
 
583
 
 
584
  /** 
 
585
   * checks, whether cluster sub type is continuous
 
586
   * 
 
587
   * @return true if cluster sub type is continuous
 
588
   */
 
589
  public boolean isContinuous() {
 
590
    return (m_clustertype == SubspaceCluster.CONTINUOUS);
 
591
  }
 
592
 
 
593
  /** 
 
594
   * checks, whether cluster sub type is integer
 
595
   * 
 
596
   * @return true if cluster sub type is integer
 
597
   */
 
598
  public boolean isInteger() {
 
599
    return (m_clustertype == SubspaceCluster.INTEGER);
 
600
  }
 
601
 
 
602
  /**
 
603
   * Sets the upper and lower boundary for instances for this cluster.
 
604
   *
 
605
   * @param fromTo  the string containing the upper and lower boundary for
 
606
   *                instances per cluster separated by ..
 
607
   */
 
608
  protected void setInstNums(String fromTo) {
 
609
    int i = fromTo.indexOf("..");
 
610
    if (i == -1) 
 
611
      i = fromTo.length();
 
612
    String from = fromTo.substring(0, i);
 
613
    m_MinInstNum = Integer.parseInt(from);
 
614
    if (i < fromTo.length()) {
 
615
      String to = fromTo.substring(i + 2, fromTo.length());
 
616
      m_MaxInstNum = Integer.parseInt(to);
 
617
    } 
 
618
    else {
 
619
      m_MaxInstNum = m_MinInstNum;
 
620
    }
 
621
  }
 
622
 
 
623
  /**
 
624
   * Get a string with the  upper and lower boundary for the 
 
625
   * number of instances for this cluster.
 
626
   *
 
627
   * @return the string containing the upper and lower boundary for
 
628
   * instances per cluster separated by ..
 
629
   */
 
630
  protected String getInstNums() {
 
631
    String text = new String(""+m_MinInstNum+".."+m_MaxInstNum);
 
632
    return text;
 
633
  }
 
634
  
 
635
  /**
 
636
   * Returns the tip text for this property
 
637
   * @return tip text for this property suitable for
 
638
   * displaying in the explorer/experimenter gui
 
639
   */
 
640
  protected String instNumsTipText() {
 
641
    return "The lower and upper boundary for the number of instances in this cluster.";
 
642
  }
 
643
 
 
644
  /**
 
645
   * returns the default min number of instances
 
646
   * 
 
647
   * @return the default min number of instances
 
648
   */
 
649
  protected int defaultMinInstNum() {
 
650
    return 1;
 
651
  }
 
652
 
 
653
  /**
 
654
   * Gets the lower boundary for instances per cluster.
 
655
   *
 
656
   * @return the the lower boundary for instances per cluster
 
657
   */
 
658
  public int getMinInstNum() { 
 
659
    return m_MinInstNum; 
 
660
  }
 
661
  
 
662
  /**
 
663
   * Sets the lower boundary for instances per cluster.
 
664
   *
 
665
   * @param newMinInstNum new lower boundary for instances per cluster
 
666
   */
 
667
  public void setMinInstNum(int newMinInstNum) {
 
668
    m_MinInstNum = newMinInstNum;
 
669
  }
 
670
  
 
671
  /**
 
672
   * Returns the tip text for this property
 
673
   * 
 
674
   * @return tip text for this property suitable for
 
675
   *         displaying in the explorer/experimenter gui
 
676
   */
 
677
  public String minInstNumTipText() {
 
678
    return "The lower boundary for instances per cluster.";
 
679
  }
 
680
 
 
681
  /**
 
682
   * returns the default max number of instances
 
683
   * 
 
684
   * @return the default max number of instances
 
685
   */
 
686
  protected int defaultMaxInstNum() {
 
687
    return 50;
 
688
  }
 
689
 
 
690
  /**
 
691
   * Gets the upper boundary for instances per cluster.
 
692
   *
 
693
   * @return the upper boundary for instances per cluster
 
694
   */
 
695
  public int getMaxInstNum() { 
 
696
    return m_MaxInstNum; 
 
697
  }
 
698
  
 
699
  /**
 
700
   * Sets the upper boundary for instances per cluster.
 
701
   *
 
702
   * @param newMaxInstNum new upper boundary for instances per cluster
 
703
   */
 
704
  public void setMaxInstNum(int newMaxInstNum) {
 
705
    m_MaxInstNum = newMaxInstNum;
 
706
  }
 
707
  
 
708
  /**
 
709
   * Returns the tip text for this property
 
710
   * 
 
711
   * @return tip text for this property suitable for
 
712
   *         displaying in the explorer/experimenter gui
 
713
   */
 
714
  public String maxInstNumTipText() {
 
715
    return "The upper boundary for instances per cluster.";
 
716
  }
 
717
 
 
718
  /**
 
719
   * Sets the real number of instances for this cluster.
 
720
   *
 
721
   * @param r random number generator 
 
722
   */
 
723
  public void setNumInstances(Random r) {
 
724
    if (m_MaxInstNum > m_MinInstNum)
 
725
      m_numInstances = (int)(r.nextDouble() 
 
726
                       * (m_MaxInstNum - m_MinInstNum) + m_MinInstNum);
 
727
    else
 
728
      m_numInstances =  m_MinInstNum;
 
729
  }
 
730
 
 
731
  /**
 
732
   * returns the default values list
 
733
   * 
 
734
   * @return the default values list
 
735
   */
 
736
  protected String defaultValuesList() {
 
737
    return "1,10";
 
738
  }
 
739
 
 
740
  /**
 
741
   * Sets the ranges for each attribute.
 
742
   *
 
743
   * @param fromToList the string containing the upper and lower boundary for
 
744
   * instances per cluster separated by ..
 
745
   * @throws Exception if values are not correct in number or value
 
746
   */
 
747
  public void setValuesList(String fromToList) throws Exception {
 
748
    m_minValue = new double [m_numClusterAttributes];
 
749
    m_maxValue = new double [m_numClusterAttributes];
 
750
    setValuesList(fromToList, m_minValue, m_maxValue, "D");
 
751
    SubspaceCluster parent = (SubspaceCluster) getParent();
 
752
 
 
753
    for (int i = 0; i < m_numClusterAttributes; i++) {
 
754
      if (m_minValue[i] > m_maxValue[i])
 
755
        throw new Exception("Min must be smaller than max.");
 
756
 
 
757
      if (getParent() != null) {
 
758
        // boolean values are only 0.0 and 1.0
 
759
        if (parent.isBoolean(m_attrIndices[i])) {
 
760
          parent.getNumValues()[m_attrIndices[i]] = 2;
 
761
          if (((m_minValue[i] != 0.0) && (m_minValue[i] != 1.0)) ||
 
762
              ((m_maxValue[i] != 0.0) && (m_maxValue[i] != 1.0)))
 
763
            throw new Exception("Ranges for boolean must be 0 or 1 only.");
 
764
        }
 
765
 
 
766
        if (parent.isNominal(m_attrIndices[i])) {
 
767
          // nominal values: attributes range might have to be enlarged
 
768
          double rest = m_minValue[i] - Math.rint(m_minValue[i]);
 
769
          if (rest != 0.0) 
 
770
            throw new Exception(" Ranges for nominal must be integer"); 
 
771
          rest = m_maxValue[i] - Math.rint(m_maxValue[i]);
 
772
          if (rest != 0.0) 
 
773
            throw new Exception("Ranges for nominal must be integer"); 
 
774
          if (m_minValue[i] < 0.0) 
 
775
            throw new Exception("Range for nominal must start with number 0.0 or higher");
 
776
          if (m_maxValue[i] + 1 > parent.getNumValues()[m_attrIndices[i]]) {
 
777
            // add new values to attribute
 
778
            // (actual format is not yet defined)
 
779
            parent.getNumValues()[m_attrIndices[i]] = (int)m_maxValue[i] + 1;
 
780
          }
 
781
        }
 
782
      }
 
783
    }
 
784
  }
 
785
 
 
786
  /**
 
787
   * returns the range for each attribute as string
 
788
   */
 
789
  public String getValuesList() {
 
790
    String        result;
 
791
    int           i;
 
792
 
 
793
    result = "";
 
794
 
 
795
    if (m_minValue != null) {
 
796
      for (i = 0; i < m_minValue.length; i++) {
 
797
        if (i > 0)
 
798
          result += ",";
 
799
        result += "" + m_minValue[i] + "," + m_maxValue[i];
 
800
      }
 
801
    }
 
802
 
 
803
    return result;
 
804
  }
 
805
  
 
806
  /**
 
807
   * Returns the tip text for this property
 
808
   * @return tip text for this property suitable for
 
809
   * displaying in the explorer/experimenter gui
 
810
   */
 
811
  public String valuesListTipText() {
 
812
    return "The range for each each attribute as string.";
 
813
  }
 
814
 
 
815
  /**
 
816
   * returns the default mean/stddev list
 
817
   */
 
818
  protected String defaultMeanStddev() {
 
819
    return "0,1.0";
 
820
  }
 
821
 
 
822
  /**
 
823
   * Sets mean and standarddeviation.
 
824
   *
 
825
   * @param meanstddev the string containing the upper and lower boundary for
 
826
   * instances per cluster separated by ..
 
827
   * @throws Exception if values are not correct in number or value
 
828
   */
 
829
  public void setMeanStddev(String meanstddev) throws Exception {
 
830
    m_meanValue   = new double [m_numClusterAttributes];
 
831
    m_stddevValue = new double [m_numClusterAttributes];
 
832
    setValuesList(meanstddev, m_meanValue, m_stddevValue, "D");
 
833
  }
 
834
 
 
835
  /**
 
836
   * returns the current mean/stddev setup
 
837
   */
 
838
  public String getMeanStddev() {
 
839
    String        result;
 
840
    int           i;
 
841
 
 
842
    result = "";
 
843
 
 
844
    if (m_meanValue != null) {
 
845
      for (i = 0; i < m_meanValue.length; i++) {
 
846
        if (i > 0)
 
847
          result += ",";
 
848
        result += "" + m_meanValue[i] + "," + m_stddevValue[i];
 
849
      }
 
850
    }
 
851
 
 
852
    return result;
 
853
  }
 
854
  
 
855
  /**
 
856
   * Returns the tip text for this property
 
857
   * @return tip text for this property suitable for
 
858
   * displaying in the explorer/experimenter gui
 
859
   */
 
860
  public String meanStddevTipText() {
 
861
    return "The mean and stddev, in case of gaussian.";
 
862
  }
 
863
 
 
864
  /**
 
865
   * Sets the ranges for each attribute.
 
866
   *
 
867
   * @param fromToList the string containing the upper and lower boundary for
 
868
   * instances per cluster separated by ..
 
869
   * @param first the "from's"
 
870
   * @param second the "to's"
 
871
   * @param optionLetter the option, from which the list came
 
872
   * @throws Exception if values are not correct in number or value
 
873
   */
 
874
  public void setValuesList(String fromToList, double[] first, double[] second, 
 
875
      String optionLetter) throws Exception {
 
876
 
 
877
    StringTokenizer     tok;
 
878
    int                 index;
 
879
    
 
880
    tok = new StringTokenizer(fromToList, ",");
 
881
    if (tok.countTokens() != first.length + second.length)
 
882
      throw new Exception(
 
883
          "Wrong number of values for option '-" + optionLetter + "'.");
 
884
 
 
885
    index = 0;
 
886
    while (tok.hasMoreTokens()) {
 
887
      first[index]  = Double.parseDouble(tok.nextToken());
 
888
      second[index] = Double.parseDouble(tok.nextToken());
 
889
      index++;
 
890
    }
 
891
  }
 
892
}