Generator.java
Upload User: rhdiban
Upload Date: 2013-08-09
Package Size: 15085k
Code Size: 15k
Category:

Windows Develop

Development Platform:

Java

  1. /*
  2.  *    Generator.java
  3.  *    Copyright (C) 2000 Gabi Schmidberger
  4.  *
  5.  *    This program is free software; you can redistribute it and/or modify
  6.  *    it under the terms of the GNU General Public License as published by
  7.  *    the Free Software Foundation; either version 2 of the License, or
  8.  *    (at your option) any later version.
  9.  *
  10.  *    This program is distributed in the hope that it will be useful,
  11.  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *    GNU General Public License for more details.
  14.  *
  15.  *    You should have received a copy of the GNU General Public License
  16.  *    along with this program; if not, write to the Free Software
  17.  *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  */
  19. package weka.datagenerators;
  20. import java.lang.Exception;
  21. import java.io.FileOutputStream;
  22. import java.io.PrintWriter;
  23. import java.io.Serializable;
  24. import java.util.Enumeration;
  25. import weka.core.Instance;
  26. import weka.core.Instances;
  27. import weka.core.Option;
  28. import weka.core.OptionHandler;
  29. import weka.core.Utils;
  30. import weka.core.Attribute;
  31. import weka.core.FastVector;
  32. /** 
  33.  * Abstract class for data generators.
  34.  *
  35.  * ------------------------------------------------------------------- <p>
  36.  *
  37.  * General options are: <p>
  38.  *
  39.  * -r string <br>
  40.  * Name of the relation of the generated dataset. <br>
  41.  * (default = name built using name of used generator and options) <p>
  42.  *
  43.  * -a num <br>
  44.  * Number of attributes. (default = 10) <p>
  45.  *
  46.  * -c num <br>
  47.  * Number of classes. (default = 2) <p>
  48.  *
  49.  * -n num <br>
  50.  * Number of examples. (default = 100) <p>
  51.  *
  52.  * -o filename<br>
  53.  * writes the generated dataset to the given file using ARFF-Format.
  54.  * (default = stdout).
  55.  * 
  56.  * ------------------------------------------------------------------- <p>
  57.  *
  58.  * Example usage as the main of a datagenerator called RandomGenerator:
  59.  * <code> <pre>
  60.  * public static void main(String [] args) {
  61.  *   try {
  62.  *     DataGenerator.makeData(new RandomGenerator(), argv);
  63.  *   } catch (Exception e) {
  64.  *     System.err.println(e.getMessage());
  65.  *   }
  66.  * }
  67.  * </pre> </code> 
  68.  * <p>
  69.  *
  70.  * ------------------------------------------------------------------ <p>
  71.  *
  72.  *
  73.  * @author Gabi Schmidberger (gabi@cs.waikato.ac.nz)
  74.  * @version $Revision: 1.1 $
  75.  */
  76. public abstract class Generator implements Serializable {
  77.   /** @serial Debugging mode */
  78.   private boolean m_Debug = false;
  79.   /** @serial The format for the generated dataset */
  80.   private Instances m_Format = null;
  81.   /** @serial Relation name the dataset should have */
  82.   private String m_RelationName = "";
  83.   /** @serial Number of attribute the dataset should have */
  84.   private int m_NumAttributes = 10;
  85.   /** @serial Number of Classes the dataset should have */
  86.   private int m_NumClasses = 2;
  87.   /** @serial Number of instances*/
  88.   private int m_NumExamples = 100;
  89.   /** @serial Number of instances that should be produced into the dataset 
  90.     * this number is by default m_NumExamples,
  91.     * but can be reset by the generator 
  92.     */
  93.    private int m_NumExamplesAct = 0;
  94.   /** @serial PrintWriter */
  95.   private PrintWriter m_Output = null;
  96.   /**
  97.    * Initializes the format for the dataset produced. 
  98.    * Must be called before the generateExample or generateExamples
  99.    * methods are used.
  100.    *
  101.    * @return the format for the dataset 
  102.    * @exception Exception if the generating of the format failed
  103.    */
  104.   abstract Instances defineDataFormat() throws Exception; 
  105.   /**
  106.    * Generates one example of the dataset. 
  107.    *
  108.    * @return the generated example
  109.    * @exception Exception if the format of the dataset is not yet defined
  110.    * @exception Exception if the generator only works with generateExamples
  111.    * which means in non single mode
  112.    */
  113.   abstract Instance generateExample() throws Exception;
  114.   /**
  115.    * Generates all examples of the dataset. 
  116.    *
  117.    * @return the generated dataset
  118.    * @exception Exception if the format of the dataset is not yet defined
  119.    * @exception Exception if the generator only works with generateExample,
  120.    * which means in single mode
  121.    */
  122.   abstract Instances generateExamples() throws Exception;
  123.   /**
  124.    * Generates a comment string that documentats the data generator.
  125.    * By default this string is added at the end of theproduces output
  126.    * as ARFF file type.
  127.    * 
  128.    * @return string contains info about the generated rules
  129.    * @exception Exception if the generating of the documentaion fails
  130.    */
  131.   abstract String generateFinished () throws Exception;
  132.   /**
  133.    * Return if single mode is set for the given data generator
  134.    * mode depends on option setting and or generator type.
  135.    * 
  136.    * @return single mode flag
  137.    * @exception Exception if mode is not set yet
  138.    */
  139.   abstract boolean getSingleModeFlag () throws Exception;
  140.   /**
  141.    * Sets the debug flag.
  142.    * @param debug the new debug flag
  143.    */
  144.   public void setDebug(boolean debug) { 
  145.     m_Debug = debug;
  146.   }
  147.   /**
  148.    * Gets the debug flag.
  149.    * @return the debug flag 
  150.    */
  151.   public boolean getDebug() { return m_Debug; }
  152.   /**
  153.    * Sets the relation name the dataset should have.
  154.    * @param relationName the new relation name
  155.    */
  156.   public void setRelationName(String relationName) {
  157.     if (relationName.length() == 0) {
  158.       // build relationname 
  159.       StringBuffer name = new StringBuffer(this.getClass().getName());
  160.       String [] options = getGenericOptions();
  161.       for (int i = 0; i < options.length; i++) {
  162. name = name.append(options[i].trim());
  163.       }
  164.       if (this instanceof OptionHandler) {
  165.         options = ((OptionHandler)this).getOptions();
  166.         for (int i = 0; i < options.length; i++) {
  167.   name = name.append(options[i].trim());
  168.         }
  169.       }
  170.       m_RelationName = name.toString();
  171.     } 
  172.     else
  173.       m_RelationName = relationName;
  174.   }
  175.   /**
  176.    * Gets the relation name the dataset should have.
  177.    * @return the relation name the dataset should have
  178.    */
  179.   public String getRelationName() { return m_RelationName; }
  180.   /**
  181.    * Sets the number of classes the dataset should have.
  182.    * @param numClasses the new number of classes
  183.    */
  184.   public void setNumClasses(int numClasses) { m_NumClasses = numClasses; }
  185.   /**
  186.    * Gets the number of classes the dataset should have.
  187.    * @return the number of classes the dataset should have
  188.    */
  189.   public int getNumClasses() { return m_NumClasses; }
  190.   /**
  191.    * Sets the number of examples, given by option.
  192.    * @param numExamples the new number of examples
  193.    */
  194.   public void setNumExamples(int numExamples) { m_NumExamples = numExamples; }
  195.   /**
  196.    * Gets the number of examples, given by option.
  197.    * @return the number of examples, given by option 
  198.    */
  199.   public int getNumExamples() { return m_NumExamples; }
  200.   /**
  201.    * Sets the number of attributes the dataset should have.
  202.    * @param numAttributes the new number of attributes
  203.    */
  204.   public void setNumAttributes(int numAttributes) {
  205.     m_NumAttributes = numAttributes;
  206.   }
  207.   /**
  208.    * Gets the number of attributes that should be produced.
  209.    * @return the number of attributes that should be produced
  210.    */
  211.   public int getNumAttributes() { return m_NumAttributes; }
  212.   /**
  213.    * Sets the number of examples the dataset should have.
  214.    * @param numExamplesAct the new number of examples
  215.    */
  216.   public void setNumExamplesAct(int numExamplesAct) { 
  217.     m_NumExamplesAct = numExamplesAct;
  218.   }
  219.   /**
  220.    * Gets the number of examples the dataset should have.
  221.    * @return the number of examples the dataset should have
  222.    */
  223.   public int getNumExamplesAct() { return m_NumExamplesAct; }
  224.   /**
  225.    * Sets the print writer.
  226.    * @param newOutput the new print writer
  227.    */
  228.   public void setOutput(PrintWriter newOutput) {
  229.     m_Output = newOutput;
  230.   }
  231.   /**
  232.    * Gets the print writer.
  233.    * @return print writer object
  234.    */
  235.   public PrintWriter getOutput() { return m_Output; }
  236.   /**
  237.    * Sets the format of the dataset that is to be generated. 
  238.    * @param the new dataset format of the dataset 
  239.    */
  240.   protected void setFormat(Instances newFormat) {
  241.     m_Format = new Instances(newFormat, 0);
  242.   }
  243.   /**
  244.    * Gets the format of the dataset that is to be generated. 
  245.    * @return the dataset format of the dataset
  246.    */
  247.   protected Instances getFormat() {
  248.     Instances format = new Instances(m_Format, 0);
  249.     return format;
  250.   }
  251.   /**
  252.    * Returns a string representing the dataset in the instance queue.
  253.    * @return the string representing the output data format
  254.    */
  255.   protected String toStringFormat() {
  256.   
  257.    if (m_Format == null)
  258.      return "";
  259.    return m_Format.toString();
  260.   }
  261.   /**
  262.    * Calls the data generator.
  263.    *
  264.    * @param dataGenerator one of the data generators 
  265.    * @param options options of the data generator
  266.    * @exception Exception if there was an error in the option list
  267.    */
  268.   public static void makeData(Generator generator, String [] options) 
  269.     throws Exception {
  270.     PrintWriter output = null;
  271.     // read options /////////////////////////////////////////////////
  272.     try {
  273.       setOptions(generator, options);
  274.     } catch (Exception ex) {
  275.       String specificOptions = "";
  276.       if (generator instanceof OptionHandler) {
  277.         specificOptions = generator.listSpecificOptions(generator);
  278.         }
  279.       String genericOptions = listGenericOptions(generator);
  280.       throw new Exception('n' + ex.getMessage()
  281.   + specificOptions + genericOptions);
  282.     }
  283.     
  284.     // define dataset format  ///////////////////////////////////////    
  285.     // computes actual number of examples to be produced
  286.     generator.setFormat(generator.defineDataFormat());
  287.     // get print writer /////////////////////////////////////////////
  288.     output = generator.getOutput();
  289.     // output of options ////////////////////////////////////////////
  290.     output.println("% ");
  291.     output.print("% " + generator.getClass().getName() + " ");
  292.     String [] outOptions = generator.getGenericOptions();
  293.     for (int i = 0; i < outOptions.length; i++) {
  294.       output.print(outOptions[i] + " ");
  295.     }
  296.     outOptions = ((OptionHandler) generator).getOptions();
  297.     for (int i = 0; i < outOptions.length; i++) {
  298.       output.print(outOptions[i] + " ");
  299.     }
  300.     output.println("n%");
  301.     // ask data generator which mode ////////////////////////////////
  302.     boolean singleMode = generator.getSingleModeFlag();
  303.     // start data producer   //////////////////////////////////////// 
  304.     if (singleMode) {
  305.       // output of  dataset header //////////////////////////////////
  306.       output.println(generator.toStringFormat());
  307.       for (int i = 0; i < generator.getNumExamplesAct(); i++)  {
  308.         // over all examples to be produced
  309.         Instance inst = generator.generateExample();
  310.         output.println(inst);
  311.         }
  312.     } else { // generator produces all instances at once
  313.       Instances dataset = generator.generateExamples();
  314.       // output of  dataset ////////////////////////////////////////////
  315.       output.println(dataset);      
  316.     }
  317.     // comment at end of ARFF File /////////////////////////////////////    
  318.     String commentAtEnd = generator.generateFinished();
  319.   
  320.     if (commentAtEnd.length() > 0) {
  321.       output.println(commentAtEnd);
  322.     }
  323.     
  324.     if (output != null) {
  325.       output.close();
  326.     }
  327.   }
  328.   /**
  329.    * Makes a string with the options of the specific data generator.
  330.    *
  331.    * @param generator the datagenerator that is used
  332.    * @return string with the options of the data generator used
  333.    */
  334.   private String listSpecificOptions(Generator generator) { 
  335.     String optionString = "";
  336.     if (generator instanceof OptionHandler) {
  337.       optionString += "nData Generator options:nn";
  338.       Enumeration enum = ((OptionHandler)generator).listOptions();
  339.       while (enum.hasMoreElements()) {
  340.         Option option = (Option) enum.nextElement();
  341. optionString += option.synopsis() + 'n'
  342.     + option.description() + "n";
  343. }
  344.     }
  345.     return optionString;
  346.   }
  347.   /**
  348.    * Sets the generic options and specific options.
  349.    *
  350.    * @param generator the data generator used 
  351.    * @param options the generic options and the specific options
  352.    * @exception Exception if help request or any invalid option
  353.    */
  354.   private static void setOptions(Generator generator,
  355.                                  String[] options) throws Exception { 
  356.     boolean helpRequest = false;
  357.     String outfileName = new String(""); 
  358.     PrintWriter output;
  359.     // get help 
  360.     helpRequest = Utils.getFlag('h', options);
  361.     if (Utils.getFlag('d', options)) { generator.setDebug(true); }
  362.     // get relationname
  363.     String relationName = Utils.getOption('r', options); 
  364.     // set relation name at end of method after all options are set
  365.     // get outputfilename
  366.     outfileName = Utils.getOption('o', options); 
  367.     // get num of classes
  368.     String numClasses = Utils.getOption('c', options);
  369.     if (numClasses.length() != 0)
  370.       generator.setNumClasses(Integer.parseInt(numClasses));
  371.     // get num of instances
  372.     String numExamples = Utils.getOption('n', options);
  373.     if (numExamples.length() != 0) {
  374.       generator.setNumExamples(Integer.parseInt(numExamples));
  375.       generator.setNumExamplesAct(Integer.parseInt(numExamples));
  376.       }
  377.     // get num of attributes
  378.     String numAttributes = Utils.getOption('a', options);
  379.     if (numAttributes.length() != 0)
  380.       generator.setNumAttributes(Integer.parseInt(numAttributes));
  381.       
  382.     if (generator instanceof OptionHandler) {
  383.       ((OptionHandler)generator).setOptions(options);
  384.       }
  385.     // all options are set, now set relation name
  386.     generator.setRelationName(relationName);
  387.     // End read options
  388.     Utils.checkForRemainingOptions(options);
  389.     if (helpRequest) {
  390.       throw new Exception("Help requested.n");
  391.     }
  392.     if (outfileName.length() != 0) {
  393.       output = new PrintWriter(new FileOutputStream(outfileName));
  394.     } else { 
  395.       output = new PrintWriter(System.out);
  396.     }
  397.     generator.setOutput(output);
  398.   }
  399.   /**
  400.    * Method for listing generic options.
  401.    *
  402.    * @param generator the data generator
  403.    * @return string with the generic data generator options
  404.    */
  405.   private static String listGenericOptions (Generator generator) {
  406.     String genericOptions = "nGeneral options:nn"
  407. + "-hn"
  408. + "tGet help on available options.n"
  409. + "-a <number of attributes>n"
  410. + "tThe number of attributes the produced dataset should have.n"
  411. + "-c <number of classes>n"
  412. + "tThe number of classes the produced dataset should have.n"
  413. + "-n <number of examples>n"
  414. + "tThe number of examples the produced dataset should have.n"
  415. + "-o <file>n"
  416. + "tThe name of the file output instances will be written to.n"
  417. + "tIf not supplied the instances will be written to stdout.n";
  418.     return genericOptions;
  419.   }
  420.   /**
  421.    * Gets the current generic settings of the datagenerator.
  422.    *
  423.    * @return an array of strings suitable for passing to setOptions
  424.    */
  425.   private String [] getGenericOptions() {
  426.     String [] options = new String [10];
  427.     int current = 0;
  428.     String name = getRelationName();
  429.     if (name.length() > 0) {
  430.       options[current++] = "-r";
  431.       options[current++] = "" + getRelationName();
  432.     }
  433.     options[current++] = "-a"; options[current++] = "" + getNumAttributes();
  434.     options[current++] = "-c"; options[current++] = "" + getNumClasses();
  435.     options[current++] = "-n"; options[current++] = "" + getNumExamples();
  436.     while (current < options.length) {
  437.       options[current++] = "";
  438.     }
  439.     return options;
  440.   }
  441. }