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

Windows Develop

Development Platform:

Java

  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.  *    BinarySparseInstance.java
  18.  *    Copyright (C) 2000 Webmind Corp.
  19.  *
  20.  */
  21. package weka.core;
  22. import java.util.*;
  23. import java.io.*;
  24. /**
  25.  * Class for storing a binary-data-only instance as a sparse vector. A
  26.  * sparse instance only requires storage for those attribute values
  27.  * that are non-zero.  Since the objective is to reduce storage
  28.  * requirements for datasets with large numbers of default values,
  29.  * this also includes nominal attributes -- the first nominal value
  30.  * (i.e. that which has index 0) will not require explicit storage, so
  31.  * rearrange your nominal attribute value orderings if
  32.  * necessary. Missing values are not supported, and will be treated as 
  33.  * 1 (true).
  34.  */
  35. public class BinarySparseInstance extends SparseInstance {
  36.   /**
  37.    * Constructor that generates a sparse instance from the given
  38.    * instance. Reference to the dataset is set to null.
  39.    * (ie. the instance doesn't have access to information about the
  40.    * attribute types)
  41.    *
  42.    * @param instance the instance from which the attribute values
  43.    * and the weight are to be copied
  44.    */
  45.   public BinarySparseInstance(Instance instance) {
  46.     
  47.     m_Weight = instance.m_Weight;
  48.     m_Dataset = null;
  49.     m_NumAttributes = instance.numAttributes();
  50.     if (instance instanceof SparseInstance) {
  51.       m_AttValues = null;
  52.       m_Indices = ((SparseInstance)instance).m_Indices;
  53.     } else {
  54.       int[] tempIndices = new int[instance.numAttributes()];
  55.       int vals = 0;
  56.       for (int i = 0; i < instance.numAttributes(); i++) {
  57. if (instance.value(i) != 0) {
  58.   tempIndices[vals] = i;
  59.   vals++;
  60. }
  61.       }
  62.       m_AttValues = null;
  63.       m_Indices = new int[vals];
  64.       System.arraycopy(tempIndices, 0, m_Indices, 0, vals);
  65.     }
  66.   }
  67.   
  68.   /**
  69.    * Constructor that copies the info from the given instance. 
  70.    * Reference to the dataset is set to null.
  71.    * (ie. the instance doesn't have access to information about the
  72.    * attribute types)
  73.    *
  74.    * @param instance the instance from which the attribute
  75.    * info is to be copied 
  76.    */
  77.   public BinarySparseInstance(SparseInstance instance) {
  78.     
  79.     m_AttValues = null;
  80.     m_Indices = instance.m_Indices;
  81.     m_Weight = instance.m_Weight;
  82.     m_NumAttributes = instance.m_NumAttributes;
  83.     m_Dataset = null;
  84.   }
  85.   /**
  86.    * Constructor that generates a sparse instance from the given
  87.    * parameters. Reference to the dataset is set to null.
  88.    * (ie. the instance doesn't have access to information about the
  89.    * attribute types)
  90.    *
  91.    * @param weight the instance's weight
  92.    * @param attValues a vector of attribute values 
  93.    */
  94.   public BinarySparseInstance(double weight, double[] attValues) {
  95.     
  96.     m_Weight = weight;
  97.     m_Dataset = null;
  98.     m_NumAttributes = attValues.length;
  99.     int[] tempIndices = new int[m_NumAttributes];
  100.     int vals = 0;
  101.     for (int i = 0; i < m_NumAttributes; i++) {
  102.       if (attValues[i] != 0) {
  103. tempIndices[vals] = i;
  104. vals++;
  105.       }
  106.     }
  107.     m_AttValues = null;
  108.     m_Indices = new int[vals];
  109.     System.arraycopy(tempIndices, 0, m_Indices, 0, vals);
  110.   }
  111.   
  112.   /**
  113.    * Constructor that inititalizes instance variable with given
  114.    * values. Reference to the dataset is set to null. (ie. the instance
  115.    * doesn't have access to information about the attribute types)
  116.    *
  117.    * @param weight the instance's weight
  118.    * @param indices the indices of the given values in the full vector
  119.    * @param maxNumValues the maximium number of values that can be stored
  120.    */
  121.   public BinarySparseInstance(double weight,
  122.                               int[] indices, int maxNumValues) {
  123.     
  124.     m_AttValues = null;
  125.     m_Indices = indices;
  126.     m_Weight = weight;
  127.     m_NumAttributes = maxNumValues;
  128.     m_Dataset = null;
  129.   }
  130.   /**
  131.    * Constructor of an instance that sets weight to one, all values to
  132.    * 1, and the reference to the dataset to null. (ie. the instance
  133.    * doesn't have access to information about the attribute types)
  134.    *
  135.    * @param numAttributes the size of the instance 
  136.    */
  137.   public BinarySparseInstance(int numAttributes) {
  138.     
  139.     m_AttValues = null;
  140.     m_NumAttributes = numAttributes;
  141.     m_Indices = new int[numAttributes];
  142.     for (int i = 0; i < m_Indices.length; i++) {
  143.       m_Indices[i] = i;
  144.     }
  145.     m_Weight = 1;
  146.     m_Dataset = null;
  147.   }
  148.   /**
  149.    * Produces a shallow copy of this instance. The copy doesn't have
  150.    * access to a dataset.
  151.    *
  152.    * @return the shallow copy
  153.    */
  154.   public Object copy() {
  155.     return new BinarySparseInstance(this);
  156.   }
  157.   /**
  158.    * Merges this instance with the given instance and returns
  159.    * the result. Dataset is set to null.
  160.    *
  161.    * @param inst the instance to be merged with this one
  162.    * @return the merged instances
  163.    */
  164.   public Instance mergeInstance(Instance inst) {
  165.     int [] indices = new int [numValues() + inst.numValues()];
  166.     int m = 0;
  167.     for (int j = 0; j < numValues(); j++) {
  168.       indices[m++] = index(j);
  169.     }
  170.     for (int j = 0; j < inst.numValues(); j++) {
  171.       if (inst.valueSparse(j) != 0) {
  172.         indices[m++] = inst.index(j) + inst.numAttributes();
  173.       }
  174.     }
  175.     if (m != indices.length) {
  176.       // Need to truncate
  177.       int [] newInd = new int [m];
  178.       System.arraycopy(indices, 0, newInd, 0, m);
  179.       indices = newInd;
  180.     }
  181.     return new BinarySparseInstance(1.0, indices, numAttributes() +
  182.                                     inst.numAttributes());
  183.   }
  184.   /** 
  185.    * Does nothing, since we don't support missing values.
  186.    *
  187.    * @param array containing the means and modes
  188.    * @exception IllegalArgumentException if numbers of attributes are unequal
  189.    */
  190.   public void replaceMissingValues(double[] array) {
  191.  
  192.     // Does nothing, since we don't store missing values.
  193.   }
  194.   /**
  195.    * Sets a specific value in the instance to the given value 
  196.    * (internal floating-point format). Performs a deep copy
  197.    * of the vector of attribute values before the value is set.
  198.    *
  199.    * @param attIndex the attribute's index 
  200.    * @param value the new attribute value (If the corresponding
  201.    * attribute is nominal (or a string) then this is the new value's
  202.    * index as a double).  
  203.    */
  204.   public void setValue(int attIndex, double value) {
  205.     int index = locateIndex(attIndex);
  206.     
  207.     if ((index >= 0) && (m_Indices[index] == attIndex)) {
  208.       if (value == 0) {
  209. int[] tempIndices = new int[m_Indices.length - 1];
  210. System.arraycopy(m_Indices, 0, tempIndices, 0, index);
  211. System.arraycopy(m_Indices, index + 1, tempIndices, index, 
  212.  m_Indices.length - index - 1);
  213. m_Indices = tempIndices;
  214.       }
  215.     } else {
  216.       if (value != 0) {
  217. int[] tempIndices = new int[m_Indices.length + 1];
  218. System.arraycopy(m_Indices, 0, tempIndices, 0, index + 1);
  219. tempIndices[index + 1] = attIndex;
  220. System.arraycopy(m_Indices, index + 1, tempIndices, index + 2, 
  221.  m_Indices.length - index - 1);
  222. m_Indices = tempIndices;
  223.       }
  224.     }
  225.   }
  226.   /**
  227.    * Sets a specific value in the instance to the given value 
  228.    * (internal floating-point format). Performs a deep copy
  229.    * of the vector of attribute values before the value is set.
  230.    *
  231.    * @param indexOfIndex the index of the attribute's index 
  232.    * @param value the new attribute value (If the corresponding
  233.    * attribute is nominal (or a string) then this is the new value's
  234.    * index as a double).  
  235.    */
  236.   public void setValueSparse(int indexOfIndex, double value) {
  237.     if (value == 0) {
  238.       int[] tempIndices = new int[m_Indices.length - 1];
  239.       System.arraycopy(m_Indices, 0, tempIndices, 0, indexOfIndex);
  240.       System.arraycopy(m_Indices, indexOfIndex + 1, tempIndices, indexOfIndex, 
  241.        m_Indices.length - indexOfIndex - 1);
  242.       m_Indices = tempIndices;
  243.     }
  244.   }
  245.   /**
  246.    * Returns the values of each attribute as an array of doubles.
  247.    *
  248.    * @return an array containing all the instance attribute values
  249.    */
  250.   public double[] toDoubleArray() {
  251.     double[] newValues = new double[m_NumAttributes];
  252.     for (int i = 0; i < m_AttValues.length; i++) {
  253.       newValues[m_Indices[i]] = 1.0;
  254.     }
  255.     return newValues;
  256.   }
  257.   /**
  258.    * Returns the description of one instance in sparse format. 
  259.    * If the instance doesn't have access to a dataset, it returns the 
  260.    * internal floating-point values. Quotes string values that contain 
  261.    * whitespace characters.
  262.    *
  263.    * @return the instance's description as a string
  264.    */
  265.   public String toString() {
  266.     StringBuffer text = new StringBuffer();
  267.     
  268.     text.append('{');
  269.     for (int i = 0; i < m_Indices.length; i++) {
  270.       if (i > 0) {
  271.         text.append(",");
  272.       }
  273.       if (m_Dataset == null) {
  274.         text.append(m_Indices[i] + " 1");
  275.       } else {
  276.         if (m_Dataset.attribute(m_Indices[i]).isNominal() || 
  277.             m_Dataset.attribute(m_Indices[i]).isString()) {
  278.           text.append(m_Indices[i] + " " +
  279.                       Utils.quote(m_Dataset.attribute(m_Indices[i]).
  280.                                   value(1)));
  281.         } else {
  282.           text.append(m_Indices[i] + " 1");
  283.         }
  284.       }
  285.     }
  286.     text.append('}');
  287.     return text.toString();
  288.   }
  289.   /**
  290.    * Returns an instance's attribute value in internal format.
  291.    *
  292.    * @param attIndex the attribute's index
  293.    * @return the specified value as a double (If the corresponding
  294.    * attribute is nominal (or a string) then it returns the value's index as a 
  295.    * double).
  296.    */
  297.   public double value(int attIndex) {
  298.     int index = locateIndex(attIndex);
  299.     if ((index >= 0) && (m_Indices[index] == attIndex)) {
  300.       return 1.0;
  301.     } else {
  302.       return 0.0;
  303.     }
  304.   }  
  305.   /**
  306.    * Returns an instance's attribute value in internal format.
  307.    * Does exactly the same thing as value() if applied to an Instance.
  308.    *
  309.    * @param indexOfIndex the index of the attribute's index
  310.    * @return the specified value as a double (If the corresponding
  311.    * attribute is nominal (or a string) then it returns the value's index as a 
  312.    * double).
  313.    */
  314.   public final double valueSparse(int indexOfIndex) {
  315.     int index = m_Indices[indexOfIndex]; // Throws if out of bounds
  316.     return 1;
  317.   }  
  318.   /**
  319.    * Deletes an attribute at the given position (0 to 
  320.    * numAttributes() - 1).
  321.    *
  322.    * @param pos the attribute's position
  323.    */
  324.   void forceDeleteAttributeAt(int position) {
  325.     int index = locateIndex(position);
  326.     m_NumAttributes--;
  327.     if ((index >= 0) && (m_Indices[index] == position)) {
  328.       int[] tempIndices = new int[m_Indices.length - 1];
  329.       System.arraycopy(m_Indices, 0, tempIndices, 0, index);
  330.       for (int i = index; i < m_Indices.length - 1; i++) {
  331. tempIndices[i] = m_Indices[i + 1] - 1;
  332.       }
  333.       m_Indices = tempIndices;
  334.     } else {
  335.       int[] tempIndices = new int[m_Indices.length];
  336.       System.arraycopy(m_Indices, 0, tempIndices, 0, index + 1);
  337.       for (int i = index + 1; i < m_Indices.length - 1; i++) {
  338. tempIndices[i] = m_Indices[i] - 1;
  339.       }
  340.       m_Indices = tempIndices;
  341.     }
  342.   }
  343.   /**
  344.    * Inserts an attribute at the given position
  345.    * (0 to numAttributes()) and sets its value to 1. 
  346.    *
  347.    * @param pos the attribute's position
  348.    */
  349.   void forceInsertAttributeAt(int position)  {
  350.     int index = locateIndex(position);
  351.     m_NumAttributes++;
  352.     if ((index >= 0) && (m_Indices[index] == position)) {
  353.       int[] tempIndices = new int[m_Indices.length + 1];
  354.       System.arraycopy(m_Indices, 0, tempIndices, 0, index);
  355.       tempIndices[index] = position;
  356.       for (int i = index; i < m_Indices.length; i++) {
  357. tempIndices[i + 1] = m_Indices[i] + 1;
  358.       }
  359.       m_Indices = tempIndices;
  360.     } else {
  361.       int[] tempIndices = new int[m_Indices.length + 1];
  362.       System.arraycopy(m_Indices, 0, tempIndices, 0, index + 1);
  363.       tempIndices[index + 1] = position;
  364.       for (int i = index + 1; i < m_Indices.length; i++) {
  365. tempIndices[i + 1] = m_Indices[i] + 1;
  366.       }
  367.       m_Indices = tempIndices;
  368.     }
  369.   }
  370.   /**
  371.    * Main method for testing this class.
  372.    */
  373.   public static void main(String[] options) {
  374.     try {
  375.       // Create numeric attributes "length" and "weight"
  376.       Attribute length = new Attribute("length");
  377.       Attribute weight = new Attribute("weight");
  378.       
  379.       // Create vector to hold nominal values "first", "second", "third" 
  380.       FastVector my_nominal_values = new FastVector(3); 
  381.       my_nominal_values.addElement("first"); 
  382.       my_nominal_values.addElement("second"); 
  383.       
  384.       // Create nominal attribute "position" 
  385.       Attribute position = new Attribute("position", my_nominal_values);
  386.       
  387.       // Create vector of the above attributes 
  388.       FastVector attributes = new FastVector(3);
  389.       attributes.addElement(length);
  390.       attributes.addElement(weight);
  391.       attributes.addElement(position);
  392.       
  393.       // Create the empty dataset "race" with above attributes
  394.       Instances race = new Instances("race", attributes, 0);
  395.       
  396.       // Make position the class attribute
  397.       race.setClassIndex(position.index());
  398.       
  399.       // Create empty instance with three attribute values
  400.       BinarySparseInstance inst = new BinarySparseInstance(3);
  401.       
  402.       // Set instance's values for the attributes "length", "weight", and "position"
  403.       inst.setValue(length, 5.3);
  404.       inst.setValue(weight, 300);
  405.       inst.setValue(position, "first");
  406.       
  407.       // Set instance's dataset to be the dataset "race"
  408.       inst.setDataset(race);
  409.       
  410.       // Print the instance
  411.       System.out.println("The instance: " + inst);
  412.       
  413.       // Print the first attribute
  414.       System.out.println("First attribute: " + inst.attribute(0));
  415.       
  416.       // Print the class attribute
  417.       System.out.println("Class attribute: " + inst.classAttribute());
  418.       
  419.       // Print the class index
  420.       System.out.println("Class index: " + inst.classIndex());
  421.       
  422.       // Say if class is missing
  423.       System.out.println("Class is missing: " + inst.classIsMissing());
  424.       
  425.       // Print the instance's class value in internal format
  426.       System.out.println("Class value (internal format): " + inst.classValue());
  427.       
  428.       // Print a shallow copy of this instance
  429.       SparseInstance copy = (SparseInstance) inst.copy();
  430.       System.out.println("Shallow copy: " + copy);
  431.       
  432.       // Set dataset for shallow copy
  433.       copy.setDataset(inst.dataset());
  434.       System.out.println("Shallow copy with dataset set: " + copy);
  435.       // Print out all values in internal format
  436.       System.out.print("All stored values in internal format: ");
  437.       for (int i = 0; i < inst.numValues(); i++) {
  438. if (i > 0) {
  439.   System.out.print(",");
  440. }
  441. System.out.print(inst.valueSparse(i));
  442.       }
  443.       System.out.println();
  444.       // Set all values to zero
  445.       System.out.print("All values set to zero: ");
  446.       while (inst.numValues() > 0) {
  447. inst.setValueSparse(0, 0);
  448.       }
  449.       for (int i = 0; i < inst.numValues(); i++) {
  450. if (i > 0) {
  451.   System.out.print(",");
  452. }
  453. System.out.print(inst.valueSparse(i));
  454.       }
  455.       System.out.println();
  456.       // Set all values to one
  457.       System.out.print("All values set to one: ");
  458.       for (int i = 0; i < inst.numAttributes(); i++) {
  459. inst.setValue(i, 1);
  460.       }
  461.       for (int i = 0; i < inst.numValues(); i++) {
  462. if (i > 0) {
  463.   System.out.print(",");
  464. }
  465. System.out.print(inst.valueSparse(i));
  466.       }
  467.       System.out.println();
  468.       // Unset dataset for copy, delete first attribute, and insert it again
  469.       copy.setDataset(null);
  470.       copy.deleteAttributeAt(0);
  471.       copy.insertAttributeAt(0);
  472.       copy.setDataset(inst.dataset());
  473.       System.out.println("Copy with first attribute deleted and inserted: " + copy); 
  474.       // Same for second attribute
  475.       copy.setDataset(null);
  476.       copy.deleteAttributeAt(1);
  477.       copy.insertAttributeAt(1);
  478.       copy.setDataset(inst.dataset());
  479.       System.out.println("Copy with second attribute deleted and inserted: " + copy); 
  480.       // Same for last attribute
  481.       copy.setDataset(null);
  482.       copy.deleteAttributeAt(2);
  483.       copy.insertAttributeAt(2);
  484.       copy.setDataset(inst.dataset());
  485.       System.out.println("Copy with third attribute deleted and inserted: " + copy); 
  486.       
  487.       // Enumerate attributes (leaving out the class attribute)
  488.       System.out.println("Enumerating attributes (leaving out class):");
  489.       Enumeration enum = inst.enumerateAttributes();
  490.       while (enum.hasMoreElements()) {
  491. Attribute att = (Attribute) enum.nextElement();
  492. System.out.println(att);
  493.       }
  494.       
  495.       // Headers are equivalent?
  496.       System.out.println("Header of original and copy equivalent: " +
  497.  inst.equalHeaders(copy));
  498.       // Test for missing values
  499.       System.out.println("Length of copy missing: " + copy.isMissing(length));
  500.       System.out.println("Weight of copy missing: " + copy.isMissing(weight.index()));
  501.       System.out.println("Length of copy missing: " + 
  502.  Instance.isMissingValue(copy.value(length)));
  503.       System.out.println("Missing value coded as: " + Instance.missingValue());
  504.       // Prints number of attributes and classes
  505.       System.out.println("Number of attributes: " + copy.numAttributes());
  506.       System.out.println("Number of classes: " + copy.numClasses());
  507.       // Replace missing values
  508.       double[] meansAndModes = {2, 3, 0};
  509.       copy.replaceMissingValues(meansAndModes);
  510.       System.out.println("Copy with missing value replaced: " + copy);
  511.       // Setting and getting values and weights
  512.       copy.setClassMissing();
  513.       System.out.println("Copy with missing class: " + copy);
  514.       copy.setClassValue(0);
  515.       System.out.println("Copy with class value set to first value: " + copy);
  516.       copy.setClassValue("second");
  517.       System.out.println("Copy with class value set to "second": " + copy);
  518.       copy.setMissing(1);
  519.       System.out.println("Copy with second attribute set to be missing: " + copy);
  520.       copy.setMissing(length);
  521.       System.out.println("Copy with length set to be missing: " + copy);
  522.       copy.setValue(0, 0);
  523.       System.out.println("Copy with first attribute set to 0: " + copy);
  524.       copy.setValue(weight, 1);
  525.       System.out.println("Copy with weight attribute set to 1: " + copy);
  526.       copy.setValue(position, "second");
  527.       System.out.println("Copy with position set to "second": " + copy);
  528.       copy.setValue(2, "first");
  529.       System.out.println("Copy with last attribute set to "first": " + copy);
  530.       System.out.println("Current weight of instance copy: " + copy.weight());
  531.       copy.setWeight(2);
  532.       System.out.println("Current weight of instance copy (set to 2): " + copy.weight());
  533.       System.out.println("Last value of copy: " + copy.toString(2));
  534.       System.out.println("Value of position for copy: " + copy.toString(position));
  535.       System.out.println("Last value of copy (internal format): " + copy.value(2));
  536.       System.out.println("Value of position for copy (internal format): " + 
  537.  copy.value(position));
  538.     } catch (Exception e) {
  539.       e.printStackTrace();
  540.     }
  541.   }
  542. }