source: tags/MetisMQIDemo/src/main/java/weka/datagenerators/classifiers/regression/MexicanHat.java

Last change on this file was 29, checked in by gnappo, 15 years ago

Taggata versione per la demo e aggiunto branch.

File size: 16.5 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 * MexicanHat.java
19 * Copyright (C) 2005 University of Waikato, Hamilton, New Zealand
20 *
21 */
22
23package weka.datagenerators.classifiers.regression;
24
25import weka.core.Attribute;
26import weka.core.FastVector;
27import weka.core.Instance;
28import weka.core.DenseInstance;
29import weka.core.Instances;
30import weka.core.Option;
31import weka.core.RevisionUtils;
32import weka.core.Utils;
33import weka.datagenerators.RegressionGenerator;
34
35import java.util.Enumeration;
36import java.util.Random;
37import java.util.Vector;
38
39/**
40 <!-- globalinfo-start -->
41 * A data generator for the simple 'Mexian Hat' function:<br/>
42 *    y = sin|x| / |x|<br/>
43 * In addition to this simple function, the amplitude can be changed and gaussian noise can be added.
44 * <p/>
45 <!-- globalinfo-end -->
46 *
47 <!-- options-start -->
48 * Valid options are: <p/>
49 *
50 * <pre> -h
51 *  Prints this help.</pre>
52 *
53 * <pre> -o &lt;file&gt;
54 *  The name of the output file, otherwise the generated data is
55 *  printed to stdout.</pre>
56 *
57 * <pre> -r &lt;name&gt;
58 *  The name of the relation.</pre>
59 *
60 * <pre> -d
61 *  Whether to print debug informations.</pre>
62 *
63 * <pre> -S
64 *  The seed for random function (default 1)</pre>
65 *
66 * <pre> -n &lt;num&gt;
67 *  The number of examples to generate (default 100)</pre>
68 *
69 * <pre> -A &lt;num&gt;
70 *  The amplitude multiplier (default 1.0).</pre>
71 *
72 * <pre> -R &lt;num&gt;..&lt;num&gt;
73 *  The range x is randomly drawn from (default -10.0..10.0).</pre>
74 *
75 * <pre> -N &lt;num&gt;
76 *  The noise rate (default 0.0).</pre>
77 *
78 * <pre> -V &lt;num&gt;
79 *  The noise variance (default 1.0).</pre>
80 *
81 <!-- options-end -->
82 *
83 * @author  FracPete (fracpete at waikato dot ac dot nz)
84 * @version $Revision: 5987 $
85 */
86
87public class MexicanHat
88  extends RegressionGenerator {
89
90  /** for serialization */
91  static final long serialVersionUID = 4577016375261512975L;
92 
93  /** the amplitude of y */
94  protected double m_Amplitude;
95
96  /** the lower boundary of the range, x is drawn from */
97  protected double m_MinRange;
98
99  /** the upper boundary of the range, x is drawn from */
100  protected double m_MaxRange;
101
102  /** the rate of the gaussian noise */
103  protected double m_NoiseRate;
104
105  /** the variance of the gaussian noise */
106  protected double m_NoiseVariance;
107
108  /** the random number generator for the noise */
109  protected Random m_NoiseRandom = null;
110
111  /**
112   * initializes the generator
113   */
114  public MexicanHat() {
115    super();
116
117    setAmplitude(defaultAmplitude());
118    setMinRange(defaultMinRange());
119    setMaxRange(defaultMaxRange());
120    setNoiseRate(defaultNoiseRate());
121    setNoiseVariance(defaultNoiseVariance());
122  }
123 
124  /**
125   * Returns a string describing this data generator.
126   *
127   * @return a description of the data generator suitable for
128   * displaying in the explorer/experimenter gui
129   */
130  public String globalInfo() {
131    return 
132        "A data generator for the simple 'Mexian Hat' function:\n"
133        + "   y = sin|x| / |x|\n"
134        + "In addition to this simple function, the amplitude can be changed and "
135        + "gaussian noise can be added.";
136  }
137
138  /**
139   * Returns an enumeration describing the available options.
140   *
141   * @return an enumeration of all the available options
142   */
143  public Enumeration listOptions() {
144    Vector result = enumToVector(super.listOptions());
145
146    result.addElement(new Option(
147              "\tThe amplitude multiplier (default " 
148              + defaultAmplitude() + ").",
149              "A", 1, "-A <num>"));
150
151    result.addElement(new Option(
152              "\tThe range x is randomly drawn from (default " 
153              + defaultMinRange() + ".." + defaultMaxRange() + ").",
154              "R", 1, "-R <num>..<num>"));
155
156    result.addElement(new Option(
157              "\tThe noise rate (default " 
158              + defaultNoiseRate() + ").",
159              "N", 1, "-N <num>"));
160
161    result.addElement(new Option(
162              "\tThe noise variance (default "
163              + defaultNoiseVariance() + ").",
164              "V", 1, "-V <num>"));
165
166    return result.elements();
167  }
168 
169  /**
170   * Parses a list of options for this object. <p/>
171   *
172   <!-- options-start -->
173   * Valid options are: <p/>
174   *
175   * <pre> -h
176   *  Prints this help.</pre>
177   *
178   * <pre> -o &lt;file&gt;
179   *  The name of the output file, otherwise the generated data is
180   *  printed to stdout.</pre>
181   *
182   * <pre> -r &lt;name&gt;
183   *  The name of the relation.</pre>
184   *
185   * <pre> -d
186   *  Whether to print debug informations.</pre>
187   *
188   * <pre> -S
189   *  The seed for random function (default 1)</pre>
190   *
191   * <pre> -n &lt;num&gt;
192   *  The number of examples to generate (default 100)</pre>
193   *
194   * <pre> -A &lt;num&gt;
195   *  The amplitude multiplier (default 1.0).</pre>
196   *
197   * <pre> -R &lt;num&gt;..&lt;num&gt;
198   *  The range x is randomly drawn from (default -10.0..10.0).</pre>
199   *
200   * <pre> -N &lt;num&gt;
201   *  The noise rate (default 0.0).</pre>
202   *
203   * <pre> -V &lt;num&gt;
204   *  The noise variance (default 1.0).</pre>
205   *
206   <!-- options-end -->
207   *
208   * @param options the list of options as an array of strings
209   * @exception Exception if an option is not supported
210   */
211  public void setOptions(String[] options) throws Exception {
212    String        tmpStr;
213   
214    super.setOptions(options);
215
216    tmpStr = Utils.getOption('A', options);
217    if (tmpStr.length() != 0)
218      setAmplitude(Double.parseDouble(tmpStr));
219    else
220      setAmplitude(defaultAmplitude());
221
222    tmpStr = Utils.getOption('R', options);
223    if (tmpStr.length() != 0)
224      setRange(tmpStr);
225    else
226      setRange(defaultMinRange() + ".." + defaultMaxRange());
227   
228    tmpStr = Utils.getOption('N', options);
229    if (tmpStr.length() != 0)
230      setNoiseRate(Double.parseDouble(tmpStr));
231    else
232      setNoiseRate(defaultNoiseRate());
233
234    tmpStr = Utils.getOption('V', options);
235    if (tmpStr.length() != 0)
236      setNoiseVariance(Double.parseDouble(tmpStr));
237    else
238      setNoiseVariance(defaultNoiseVariance());
239  }
240
241  /**
242   * Gets the current settings of the datagenerator BIRCHCluster.
243   *
244   * @return an array of strings suitable for passing to setOptions
245   */
246  public String[] getOptions() {
247    Vector        result;
248    String[]      options;
249    int           i;
250   
251    result  = new Vector();
252    options = removeBlacklist(super.getOptions());
253    for (i = 0; i < options.length; i++)
254      result.add(options[i]);
255
256    result.add("-A"); 
257    result.add("" + getAmplitude());
258
259    result.add("-R"); 
260    result.add("" + getRange());
261
262    result.add("-N"); 
263    result.add("" + getNoiseRate());
264
265    result.add("-V"); 
266    result.add("" + getNoiseVariance());
267   
268    return (String[]) result.toArray(new String[result.size()]);
269  }
270
271  /**
272   * returns the default amplitude
273   *
274   * @return the default amplitude
275   */
276  protected double defaultAmplitude() {
277    return 1.0;
278  }
279
280  /**
281   * Gets the amplitude multiplier.
282   *
283   * @return the amplitude multiplier
284   */
285  public double getAmplitude() { 
286    return m_Amplitude; 
287  }
288 
289  /**
290   * Sets the amplitude multiplier.
291   *
292   * @param value the amplitude multiplier
293   */
294  public void setAmplitude(double value) {
295    m_Amplitude = value;
296  }
297 
298  /**
299   * Returns the tip text for this property
300   *
301   * @return tip text for this property suitable for
302   *         displaying in the explorer/experimenter gui
303   */
304  public String amplitudeTipText() {
305    return "The amplitude of the mexican hat.";
306  }
307
308  /**
309   * Sets the upper and lower boundary for the range of x
310   *
311   * @param fromTo the string containing the upper and lower boundary for
312   *               the range of x, separated by ..
313   */
314  protected void setRange(String fromTo) {
315    int i = fromTo.indexOf("..");
316    String from = fromTo.substring(0, i);
317    setMinRange(Double.valueOf(from).doubleValue());
318    String to = fromTo.substring(i + 2, fromTo.length());
319    setMaxRange(Double.valueOf(to).doubleValue());
320  }
321
322  /**
323   * Gets the upper and lower boundary for the range of x
324   *
325   * @return the string containing the upper and lower boundary for
326   *         the range of x, separated by ..
327   */
328  protected String getRange() {
329    String fromTo = "" 
330                    + Utils.doubleToString(getMinRange(), 2) + ".."
331                    + Utils.doubleToString(getMaxRange(), 2);
332    return fromTo;
333  }
334 
335  /**
336   * Returns the tip text for this property
337   *
338   * @return tip text for this property suitable for
339   *         displaying in the explorer/experimenter gui
340   */
341  protected String rangeTipText() {
342    return "The upper and lower boundary for the range x is drawn from randomly.";
343  }
344
345  /**
346   * returns the default min range
347   *
348   * @return the default min range
349   */
350  protected double defaultMinRange() {
351    return -10;
352  }
353
354  /**
355   * Sets the lower boundary for the range of x
356   *
357   * @param value the lower boundary
358   */
359  public void setMinRange(double value) {
360    m_MinRange = value;
361  }
362
363  /**
364   * Gets the lower boundary for the range of x
365   *
366   * @return the lower boundary for the range of x
367   */
368  public double getMinRange() {
369    return m_MinRange;
370  }
371 
372  /**
373   * Returns the tip text for this property
374   *
375   * @return tip text for this property suitable for
376   *         displaying in the explorer/experimenter gui
377   */
378  public String minRangeTipText() {
379    return "The lower boundary for the range x is drawn from randomly.";
380  }
381
382  /**
383   * returns the default max range
384   *
385   * @return the default max range
386   */
387  protected double defaultMaxRange() {
388    return 10;
389  }
390
391  /**
392   * Sets the upper boundary for the range of x
393   *
394   * @param value the upper boundary
395   */
396  public void setMaxRange(double value) {
397    m_MaxRange = value;
398  }
399
400  /**
401   * Gets the upper boundary for the range of x
402   *
403   * @return the upper boundary for the range of x
404   */
405  public double getMaxRange() {
406    return m_MaxRange;
407  }
408 
409  /**
410   * Returns the tip text for this property
411   *
412   * @return tip text for this property suitable for
413   *         displaying in the explorer/experimenter gui
414   */
415  public String maxRangeTipText() {
416    return "The upper boundary for the range x is drawn from randomly.";
417  }
418
419  /**
420   * returns the default gaussian noise rate
421   *
422   * @return the default gaussian noise rate
423   */
424  protected double defaultNoiseRate() {
425    return 0.0;
426  }
427
428  /**
429   * Gets the gaussian noise rate.
430   *
431   * @return the gaussian noise rate
432   */
433  public double getNoiseRate() { 
434    return m_NoiseRate; 
435  }
436 
437  /**
438   * Sets the gaussian noise rate.
439   *
440   * @param value the gaussian noise rate
441   */
442  public void setNoiseRate(double value) {
443    m_NoiseRate = value;
444  }
445 
446  /**
447   * Returns the tip text for this property
448   *
449   * @return tip text for this property suitable for
450   *         displaying in the explorer/experimenter gui
451   */
452  public String noiseRateTipText() {
453    return "The gaussian noise rate to use.";
454  }
455
456  /**
457   * returns the default variance of the noise rate
458   *
459   * @return the default variance of the noise rate
460   */
461  protected double defaultNoiseVariance() {
462    return 1.0;
463  }
464
465  /**
466   * Gets the noise variance
467   *
468   * @return the noise variance
469   */
470  public double getNoiseVariance() { 
471    return m_NoiseVariance; 
472  }
473 
474  /**
475   * Sets the noise variance
476   *
477   * @param value the noise variance
478   */
479  public void setNoiseVariance(double value) {
480    if (value > 0)
481      m_NoiseVariance = value;
482    else
483      throw new IllegalArgumentException(
484          "Noise variance needs to be > 0 (provided: " + value + ")!");
485  }
486 
487  /**
488   * Returns the tip text for this property
489   *
490   * @return tip text for this property suitable for
491   *         displaying in the explorer/experimenter gui
492   */
493  public String noiseVarianceTipText() {
494    return "The noise variance to use.";
495  }
496
497  /**
498   * Return if single mode is set for the given data generator
499   * mode depends on option setting and or generator type.
500   *
501   * @return single mode flag
502   * @throws Exception if mode is not set yet
503   */
504  public boolean getSingleModeFlag() throws Exception {
505    return true;
506  }
507
508  /**
509   * Initializes the format for the dataset produced.
510   * Must be called before the generateExample or generateExamples
511   * methods are used.
512   * Re-initializes the random number generator with the given seed.
513   *
514   * @return the format for the dataset
515   * @throws Exception if the generating of the format failed
516   * @see  #getSeed()
517   */
518  public Instances defineDataFormat() throws Exception {
519    FastVector      atts;
520
521    m_Random      = new Random(getSeed());
522    m_NoiseRandom = new Random(getSeed());
523
524    // number of examples is the same as given per option
525    setNumExamplesAct(getNumExamples());
526
527    // initialize dataset format
528    atts = new FastVector();
529    atts.addElement(new Attribute("x"));
530    atts.addElement(new Attribute("y"));
531   
532    m_DatasetFormat = new Instances(getRelationNameToUse(), atts, 0);
533   
534    return m_DatasetFormat;
535  }
536
537  /**
538   * Generates one example of the dataset.
539   *
540   * @return the generated example
541   * @throws Exception if the format of the dataset is not yet defined
542   * @throws Exception if the generator only works with generateExamples
543   * which means in non single mode
544   */
545  public Instance generateExample() throws Exception {
546    Instance    result;
547    Random      rand;
548    double      x;
549    double      y;
550    double[]    atts;
551
552    result = null;
553    rand   = getRandom();
554
555    if (m_DatasetFormat == null)
556      throw new Exception("Dataset format not defined.");
557
558    // generate attributes
559    atts = new double[m_DatasetFormat.numAttributes()];
560   
561    // random x
562    x = rand.nextDouble();
563    // fit into range
564    x = x * (getMaxRange() - getMinRange()) + getMinRange();
565   
566    // generate y
567    if (Utils.eq(x, 0))
568      y = getAmplitude();
569    else
570      y = getAmplitude() 
571          * StrictMath.sin(StrictMath.abs(x)) / StrictMath.abs(x);
572    // noise
573    y = y + getAmplitude() 
574            * m_NoiseRandom.nextGaussian() 
575            * getNoiseRate() * getNoiseVariance();
576
577    atts[0] = x;
578    atts[1] = y;
579    result = new DenseInstance(1.0, atts);
580
581    // dataset reference
582    result.setDataset(m_DatasetFormat);
583   
584    return result;
585  }
586
587  /**
588   * Generates all examples of the dataset. Re-initializes the random number
589   * generator with the given seed, before generating instances.
590   *
591   * @return the generated dataset
592   * @throws Exception if the format of the dataset is not yet defined
593   * @throws Exception if the generator only works with generateExample,
594   * which means in single mode
595   * @see   #getSeed()
596   */
597  public Instances generateExamples() throws Exception {
598    Instances       result;
599    int             i;
600
601    result   = new Instances(m_DatasetFormat, 0);
602    m_Random = new Random(getSeed());
603
604    for (i = 0; i < getNumExamplesAct(); i++)
605      result.add(generateExample());
606
607    return result;
608  }
609
610  /**
611   * Generates a comment string that documentates the data generator.
612   * By default this string is added at the beginning of the produced output
613   * as ARFF file type, next after the options.
614   *
615   * @return string contains info about the generated rules
616   */
617  public String generateStart () {
618    return "";
619  }
620
621  /**
622   * Generates a comment string that documentats the data generator.
623   * By default this string is added at the end of theproduces output
624   * as ARFF file type.
625   *
626   * @return string contains info about the generated rules
627   * @throws Exception if the generating of the documentaion fails
628   */
629  public String generateFinished() throws Exception {
630    return "";
631  }
632 
633  /**
634   * Returns the revision string.
635   *
636   * @return            the revision
637   */
638  public String getRevision() {
639    return RevisionUtils.extract("$Revision: 5987 $");
640  }
641
642  /**
643   * Main method for testing this class.
644   *
645   * @param args should contain arguments for the data producer:
646   */
647  public static void main(String[] args) {
648    runDataGenerator(new MexicanHat(), args);
649  }
650}
Note: See TracBrowser for help on using the repository browser.