SparseInstance.java
Upload User: rhdiban
Upload Date: 2013-08-09
Package Size: 15085k
Code Size: 25k
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.  *    SparseInstance.java
  18.  *    Copyright (C) 2000 Eibe Frank
  19.  *
  20.  */
  21. package weka.core;
  22. import java.util.*;
  23. import java.io.*;
  24. /**
  25.  * Class for storing an instance as a sparse vector. A sparse instance
  26.  * only requires storage for those attribute values that are non-zero.
  27.  * Since the objective is to reduce storage requirements for datasets
  28.  * with large numbers of default values, this also includes nominal
  29.  * attributes -- the first nominal value (i.e. that which has index 0)
  30.  * will not require explicit storage, so rearrange your nominal attribute
  31.  * value orderings if necessary. Missing values will be stored
  32.  * explicitly.
  33.  */
  34. public class SparseInstance extends Instance {
  35.   /** The index of the attribute associated with each stored value. */
  36.   protected int[] m_Indices;
  37.   /** The maximum number of values that can be stored. */
  38.   protected int m_NumAttributes;
  39.   protected SparseInstance() {
  40.   }
  41.   /**
  42.    * Constructor that generates a sparse instance from the given
  43.    * instance. Reference to the dataset is set to null.
  44.    * (ie. the instance doesn't have access to information about the
  45.    * attribute types)
  46.    *
  47.    * @param instance the instance from which the attribute values
  48.    * and the weight are to be copied
  49.    */
  50.   public SparseInstance(Instance instance) {
  51.     
  52.     m_Weight = instance.m_Weight;
  53.     m_Dataset = null;
  54.     m_NumAttributes = instance.numAttributes();
  55.     if (instance instanceof SparseInstance) {
  56.       m_AttValues = ((SparseInstance)instance).m_AttValues;
  57.       m_Indices = ((SparseInstance)instance).m_Indices;
  58.     } else {
  59.       double[] tempValues = new double[instance.numAttributes()];
  60.       int[] tempIndices = new int[instance.numAttributes()];
  61.       int vals = 0;
  62.       for (int i = 0; i < instance.numAttributes(); i++) {
  63. if (instance.value(i) != 0) {
  64.   tempValues[vals] = instance.value(i);
  65.   tempIndices[vals] = i;
  66.   vals++;
  67. }
  68.       }
  69.       m_AttValues = new double[vals];
  70.       m_Indices = new int[vals];
  71.       System.arraycopy(tempValues, 0, m_AttValues, 0, vals);
  72.       System.arraycopy(tempIndices, 0, m_Indices, 0, vals);
  73.     }
  74.   }
  75.   /**
  76.    * Constructor that copies the info from the given instance. 
  77.    * Reference to the dataset is set to null.
  78.    * (ie. the instance doesn't have access to information about the
  79.    * attribute types)
  80.    *
  81.    * @param instance the instance from which the attribute
  82.    * info is to be copied 
  83.    */
  84.   public SparseInstance(SparseInstance instance) {
  85.     
  86.     m_AttValues = instance.m_AttValues;
  87.     m_Indices = instance.m_Indices;
  88.     m_Weight = instance.m_Weight;
  89.     m_NumAttributes = instance.m_NumAttributes;
  90.     m_Dataset = null;
  91.   }
  92.   /**
  93.    * Constructor that generates a sparse instance from the given
  94.    * parameters. Reference to the dataset is set to null.
  95.    * (ie. the instance doesn't have access to information about the
  96.    * attribute types)
  97.    *
  98.    * @param weight the instance's weight
  99.    * @param attValues a vector of attribute values 
  100.    */
  101.   public SparseInstance(double weight, double[] attValues) {
  102.     
  103.     m_Weight = weight;
  104.     m_Dataset = null;
  105.     m_NumAttributes = attValues.length;
  106.     double[] tempValues = new double[m_NumAttributes];
  107.     int[] tempIndices = new int[m_NumAttributes];
  108.     int vals = 0;
  109.     for (int i = 0; i < m_NumAttributes; i++) {
  110.       if (attValues[i] != 0) {
  111. tempValues[vals] = attValues[i];
  112. tempIndices[vals] = i;
  113. vals++;
  114.       }
  115.     }
  116.     m_AttValues = new double[vals];
  117.     m_Indices = new int[vals];
  118.     System.arraycopy(tempValues, 0, m_AttValues, 0, vals);
  119.     System.arraycopy(tempIndices, 0, m_Indices, 0, vals);
  120.   }
  121.   
  122.   /**
  123.    * Constructor that inititalizes instance variable with given
  124.    * values. Reference to the dataset is set to null. (ie. the instance
  125.    * doesn't have access to information about the attribute types)
  126.    *
  127.    * @param weight the instance's weight
  128.    * @param attValues a vector of attribute values (just the ones to be stored)
  129.    * @param indices the indices of the given values in the full vector
  130.    * @param maxNumValues the maximium number of values that can be stored
  131.    */
  132.   public SparseInstance(double weight, double[] attValues,
  133. int[] indices, int maxNumValues){
  134.     
  135.     int vals = 0; 
  136.     m_AttValues = new double [attValues.length];
  137.     m_Indices = new int [indices.length];
  138.     for (int i = 0; i < attValues.length; i++) {
  139.       if (attValues[i] != 0) {
  140.         m_AttValues[vals] = attValues[i];
  141.         m_Indices[vals] = indices[i];
  142.         vals++;
  143.       }
  144.     }
  145.     if (vals != attValues.length) {
  146.       // Need to truncate.
  147.       double [] newVals = new double[vals];
  148.       System.arraycopy(m_AttValues, 0, newVals, 0, vals);
  149.       m_AttValues = newVals;
  150.       int [] newIndices = new int[vals];
  151.       System.arraycopy(m_Indices, 0, newIndices, 0, vals);
  152.       m_Indices = newIndices;
  153.     }
  154.     m_Weight = weight;
  155.     m_NumAttributes = maxNumValues;
  156.     m_Dataset = null;
  157.   }
  158.   /**
  159.    * Constructor of an instance that sets weight to one, all values to
  160.    * be missing, and the reference to the dataset to null. (ie. the instance
  161.    * doesn't have access to information about the attribute types)
  162.    *
  163.    * @param numAttributes the size of the instance 
  164.    */
  165.   public SparseInstance(int numAttributes) {
  166.     
  167.     m_AttValues = new double[numAttributes];
  168.     m_NumAttributes = numAttributes;
  169.     m_Indices = new int[numAttributes];
  170.     for (int i = 0; i < m_AttValues.length; i++) {
  171.       m_AttValues[i] = MISSING_VALUE;
  172.       m_Indices[i] = i;
  173.     }
  174.     m_Weight = 1;
  175.     m_Dataset = null;
  176.   }
  177.   /**
  178.    * Returns the attribute associated with the internal index. 
  179.    *
  180.    * @param indexOfIndex the index of the attribute's index 
  181.    * @return the attribute at the given position
  182.    * @exception UnassignedDatasetException if instance doesn't have access to a
  183.    * dataset
  184.    */ 
  185.   public Attribute attributeSparse(int indexOfIndex) {
  186.    
  187.     if (m_Dataset == null) {
  188.       throw new UnassignedDatasetException("Instance doesn't have access to a dataset!");
  189.     }
  190.     return m_Dataset.attribute(m_Indices[indexOfIndex]);
  191.   }
  192.   /**
  193.    * Produces a shallow copy of this instance. The copy has
  194.    * access to the same dataset. (if you want to make a copy
  195.    * that doesn't have access to the dataset, use 
  196.    * <code>new SparseInstance(instance)</code>
  197.    *
  198.    * @return the shallow copy
  199.    */
  200.   public Object copy() {
  201.     Instance result = new SparseInstance(this);
  202.     result.m_Dataset = m_Dataset;
  203.     return result;
  204.   }
  205.   /**
  206.    * Returns the index of the attribute stored at the given position.
  207.    *
  208.    * @param position the position 
  209.    * @return the index of the attribute stored at the given position
  210.    */
  211.   public int index(int position) {
  212.     return m_Indices[position];
  213.   }
  214.   /**
  215.    * Tests if a specific value is "missing".
  216.    *
  217.    * @param attIndex the attribute's index
  218.    */
  219.   public boolean isMissing(int attIndex) {
  220.     if (Double.isNaN(value(attIndex))) {
  221.       return true;
  222.     }
  223.     return false;
  224.   }
  225.   /**
  226.    * Locates the greatest index that is not greater than the
  227.    * given index.
  228.    *
  229.    * @return the internal index of the attribute index. Returns
  230.    * -1 if no index with this property couldn't be found
  231.    */
  232.   public int locateIndex(int index) {
  233.     int min = 0, max = m_Indices.length - 1;
  234.     // Binary search
  235.     while (max >= min) {
  236.       int current = (max + min) / 2;
  237.       if (m_Indices[current] > index) {
  238. max = current - 1;
  239.       } else if (m_Indices[current] < index) {
  240. min = current + 1;
  241.       } else {
  242. return current;
  243.       }
  244.     }
  245.     return max;
  246.   }
  247.   /**
  248.    * Merges this instance with the given instance and returns
  249.    * the result. Dataset is set to null.
  250.    *
  251.    * @param inst the instance to be merged with this one
  252.    * @return the merged instances
  253.    */
  254.   public Instance mergeInstance(Instance inst) {
  255.     double[] values = new double[numValues() + inst.numValues()];
  256.     int[] indices = new int[numValues() + inst.numValues()];
  257.     int m = 0;
  258.     for (int j = 0; j < numValues(); j++, m++) {
  259.       values[m] = valueSparse(j);
  260.       indices[m] = index(j);
  261.     }
  262.     for (int j = 0; j < inst.numValues(); j++, m++) {
  263.       values[m] = inst.valueSparse(j);
  264.       indices[m] = inst.index(j) + inst.numAttributes();
  265.     }
  266.     
  267.     return new SparseInstance(1.0, values, indices, numAttributes() +
  268.       inst.numAttributes());
  269.   }
  270.   /**
  271.    * Returns the number of attributes.
  272.    *
  273.    * @return the number of attributes as an integer
  274.    */
  275.   public int numAttributes() {
  276.     return m_NumAttributes;
  277.   }
  278.   /**
  279.    * Returns the number of values in the sparse vector.
  280.    *
  281.    * @return the number of values
  282.    */
  283.   public int numValues() {
  284.     return m_Indices.length;
  285.   }
  286.   /** 
  287.    * Replaces all missing values in the instance with the 
  288.    * values contained in the given array. A deep copy of
  289.    * the vector of attribute values is performed before the
  290.    * values are replaced.
  291.    *
  292.    * @param array containing the means and modes
  293.    * @exception IllegalArgumentException if numbers of attributes are unequal
  294.    */
  295.   public void replaceMissingValues(double[] array) {
  296.  
  297.     if ((array == null) || (array.length != m_NumAttributes)) {
  298.       throw new IllegalArgumentException("Unequal number of attributes!");
  299.     }
  300.     double[] tempValues = new double[m_AttValues.length];
  301.     int[] tempIndices = new int[m_AttValues.length];
  302.     int vals = 0;
  303.     for (int i = 0; i < m_AttValues.length; i++) {
  304.       if (isMissingValue(m_AttValues[i])) {
  305. if (array[m_Indices[i]] != 0) {
  306.   tempValues[vals] = array[m_Indices[i]];
  307.   tempIndices[vals] = m_Indices[i];
  308.   vals++;
  309.       } else {
  310. tempValues[vals] = m_AttValues[i];
  311. tempIndices[vals] = m_Indices[i];
  312. vals++;
  313.       }
  314.     }
  315.     m_AttValues = new double[vals];
  316.     m_Indices = new int[vals];
  317.     System.arraycopy(tempValues, 0, m_AttValues, 0, vals);
  318.     System.arraycopy(tempIndices, 0, m_Indices, 0, vals);
  319.   }
  320.   /**
  321.    * Sets a specific value in the instance to the given value 
  322.    * (internal floating-point format). Performs a deep copy
  323.    * of the vector of attribute values before the value is set.
  324.    *
  325.    * @param attIndex the attribute's index 
  326.    * @param value the new attribute value (If the corresponding
  327.    * attribute is nominal (or a string) then this is the new value's
  328.    * index as a double).  
  329.    */
  330.   public void setValue(int attIndex, double value) {
  331.     int index = locateIndex(attIndex);
  332.     
  333.     if ((index >= 0) && (m_Indices[index] == attIndex)) {
  334.       if (value != 0) {
  335. double[] tempValues = new double[m_AttValues.length];
  336. System.arraycopy(m_AttValues, 0, tempValues, 0, m_AttValues.length);
  337. tempValues[index] = value;
  338. m_AttValues = tempValues;
  339.       } else {
  340. double[] tempValues = new double[m_AttValues.length - 1];
  341. int[] tempIndices = new int[m_Indices.length - 1];
  342. System.arraycopy(m_AttValues, 0, tempValues, 0, index);
  343. System.arraycopy(m_Indices, 0, tempIndices, 0, index);
  344. System.arraycopy(m_AttValues, index + 1, tempValues, index, 
  345.  m_AttValues.length - index - 1);
  346. System.arraycopy(m_Indices, index + 1, tempIndices, index, 
  347.  m_Indices.length - index - 1);
  348. m_AttValues = tempValues;
  349. m_Indices = tempIndices;
  350.       }
  351.     } else {
  352.       if (value != 0) {
  353. double[] tempValues = new double[m_AttValues.length + 1];
  354. int[] tempIndices = new int[m_Indices.length + 1];
  355. System.arraycopy(m_AttValues, 0, tempValues, 0, index + 1);
  356. System.arraycopy(m_Indices, 0, tempIndices, 0, index + 1);
  357. tempIndices[index + 1] = attIndex;
  358. tempValues[index + 1] = value;
  359. System.arraycopy(m_AttValues, index + 1, tempValues, index + 2, 
  360.  m_AttValues.length - index - 1);
  361. System.arraycopy(m_Indices, index + 1, tempIndices, index + 2, 
  362.  m_Indices.length - index - 1);
  363. m_AttValues = tempValues;
  364. m_Indices = tempIndices;
  365.       }
  366.     }
  367.   }
  368.   /**
  369.    * Sets a specific value in the instance to the given value 
  370.    * (internal floating-point format). Performs a deep copy
  371.    * of the vector of attribute values before the value is set.
  372.    *
  373.    * @param indexOfIndex the index of the attribute's index 
  374.    * @param value the new attribute value (If the corresponding
  375.    * attribute is nominal (or a string) then this is the new value's
  376.    * index as a double).  
  377.    */
  378.   public void setValueSparse(int indexOfIndex, double value) {
  379.     if (value != 0) {
  380.       double[] tempValues = new double[m_AttValues.length];
  381.       System.arraycopy(m_AttValues, 0, tempValues, 0, m_AttValues.length);
  382.       m_AttValues = tempValues;
  383.       m_AttValues[indexOfIndex] = value;
  384.     } else {
  385.       double[] tempValues = new double[m_AttValues.length - 1];
  386.       int[] tempIndices = new int[m_Indices.length - 1];
  387.       System.arraycopy(m_AttValues, 0, tempValues, 0, indexOfIndex);
  388.       System.arraycopy(m_Indices, 0, tempIndices, 0, indexOfIndex);
  389.       System.arraycopy(m_AttValues, indexOfIndex + 1, tempValues, indexOfIndex, 
  390.        m_AttValues.length - indexOfIndex - 1);
  391.       System.arraycopy(m_Indices, indexOfIndex + 1, tempIndices, indexOfIndex, 
  392.        m_Indices.length - indexOfIndex - 1);
  393.       m_AttValues = tempValues;
  394.       m_Indices = tempIndices;
  395.     }
  396.   }
  397.   /**
  398.    * Returns the values of each attribute as an array of doubles.
  399.    *
  400.    * @return an array containing all the instance attribute values
  401.    */
  402.   public double[] toDoubleArray() {
  403.     double[] newValues = new double[m_NumAttributes];
  404.     for (int i = 0; i < m_AttValues.length; i++) {
  405.       newValues[m_Indices[i]] = m_AttValues[i];
  406.     }
  407.     return newValues;
  408.   }
  409.   /**
  410.    * Returns the description of one instance in sparse format. 
  411.    * If the instance doesn't have access to a dataset, it returns the 
  412.    * internal floating-point values. Quotes string values that contain 
  413.    * whitespace characters.
  414.    *
  415.    * @return the instance's description as a string
  416.    */
  417.   public String toString() {
  418.     StringBuffer text = new StringBuffer();
  419.     
  420.     text.append('{');
  421.     for (int i = 0; i < m_Indices.length; i++) {
  422.       if (i > 0) text.append(",");
  423.       if (isMissingValue(m_AttValues[i])) {
  424. text.append(m_Indices[i] + " ?");
  425.       } else {
  426. if (m_Dataset == null) {
  427.   text.append(m_Indices[i] + " " + 
  428.       Utils.doubleToString(m_AttValues[i],6));
  429. } else {
  430.   if (m_Dataset.attribute(m_Indices[i]).isNominal() || 
  431.       m_Dataset.attribute(m_Indices[i]).isString()) {
  432.     try {
  433.       text.append(m_Indices[i] + " " +
  434.   Utils.quote(m_Dataset.attribute(m_Indices[i]).
  435.       value((int)valueSparse(i))));
  436.     } catch (Exception e) {
  437.               e.printStackTrace();
  438.               System.err.println(new Instances(m_Dataset, 0));
  439.               System.err.println("Att:" + m_Indices[i] + " Val:" + valueSparse(i));
  440.       throw new Error("This should never happen!");
  441.     }
  442.   } else {
  443.     text.append(m_Indices[i] + " " +
  444. Utils.doubleToString(m_AttValues[i],6));
  445.   }
  446. }
  447.       }
  448.     }
  449.     text.append('}');
  450.     return text.toString();
  451.   }
  452.   /**
  453.    * Returns an instance's attribute value in internal format.
  454.    *
  455.    * @param attIndex the attribute's index
  456.    * @return the specified value as a double (If the corresponding
  457.    * attribute is nominal (or a string) then it returns the value's index as a 
  458.    * double).
  459.    */
  460.   public double value(int attIndex) {
  461.     int index = locateIndex(attIndex);
  462.     if ((index >= 0) && (m_Indices[index] == attIndex)) {
  463.       return m_AttValues[index];
  464.     } else {
  465.       return 0.0;
  466.     }
  467.   }  
  468.   /**
  469.    * Deletes an attribute at the given position (0 to 
  470.    * numAttributes() - 1).
  471.    *
  472.    * @param pos the attribute's position
  473.    */
  474.   void forceDeleteAttributeAt(int position) {
  475.     int index = locateIndex(position);
  476.     m_NumAttributes--;
  477.     if ((index >= 0) && (m_Indices[index] == position)) {
  478.       int[] tempIndices = new int[m_Indices.length - 1];
  479.       double[] tempValues = new double[m_AttValues.length - 1];
  480.       System.arraycopy(m_Indices, 0, tempIndices, 0, index);
  481.       System.arraycopy(m_AttValues, 0, tempValues, 0, index);
  482.       for (int i = index; i < m_Indices.length - 1; i++) {
  483. tempIndices[i] = m_Indices[i + 1] - 1;
  484. tempValues[i] = m_AttValues[i + 1];
  485.       }
  486.       m_Indices = tempIndices;
  487.       m_AttValues = tempValues;
  488.     } else {
  489.       int[] tempIndices = new int[m_Indices.length];
  490.       double[] tempValues = new double[m_AttValues.length];
  491.       System.arraycopy(m_Indices, 0, tempIndices, 0, index + 1);
  492.       System.arraycopy(m_AttValues, 0, tempValues, 0, index + 1);
  493.       for (int i = index + 1; i < m_Indices.length; i++) {
  494. tempIndices[i] = m_Indices[i] - 1;
  495. tempValues[i] = m_AttValues[i];
  496.       }
  497.       m_Indices = tempIndices;
  498.       m_AttValues = tempValues;
  499.     }
  500.   }
  501.   /**
  502.    * Inserts an attribute at the given position
  503.    * (0 to numAttributes()) and sets its value to be missing. 
  504.    *
  505.    * @param pos the attribute's position
  506.    */
  507.   void forceInsertAttributeAt(int position)  {
  508.     int index = locateIndex(position);
  509.     m_NumAttributes++;
  510.     if ((index >= 0) && (m_Indices[index] == position)) {
  511.       int[] tempIndices = new int[m_Indices.length + 1];
  512.       double[] tempValues = new double[m_AttValues.length + 1];
  513.       System.arraycopy(m_Indices, 0, tempIndices, 0, index);
  514.       System.arraycopy(m_AttValues, 0, tempValues, 0, index);
  515.       tempIndices[index] = position;
  516.       tempValues[index] = MISSING_VALUE;
  517.       for (int i = index; i < m_Indices.length; i++) {
  518. tempIndices[i + 1] = m_Indices[i] + 1;
  519. tempValues[i + 1] = m_AttValues[i];
  520.       }
  521.       m_Indices = tempIndices;
  522.       m_AttValues = tempValues;
  523.     } else {
  524.       int[] tempIndices = new int[m_Indices.length + 1];
  525.       double[] tempValues = new double[m_AttValues.length + 1];
  526.       System.arraycopy(m_Indices, 0, tempIndices, 0, index + 1);
  527.       System.arraycopy(m_AttValues, 0, tempValues, 0, index + 1);
  528.       tempIndices[index + 1] = position;
  529.       tempValues[index + 1] = MISSING_VALUE;
  530.       for (int i = index + 1; i < m_Indices.length; i++) {
  531. tempIndices[i + 1] = m_Indices[i] + 1;
  532. tempValues[i + 1] = m_AttValues[i];
  533.       }
  534.       m_Indices = tempIndices;
  535.       m_AttValues = tempValues;
  536.     }
  537.   }
  538.   /**
  539.    * Main method for testing this class.
  540.    */
  541.   public static void main(String[] options) {
  542.     try {
  543.       // Create numeric attributes "length" and "weight"
  544.       Attribute length = new Attribute("length");
  545.       Attribute weight = new Attribute("weight");
  546.       
  547.       // Create vector to hold nominal values "first", "second", "third" 
  548.       FastVector my_nominal_values = new FastVector(3); 
  549.       my_nominal_values.addElement("first"); 
  550.       my_nominal_values.addElement("second"); 
  551.       my_nominal_values.addElement("third"); 
  552.       
  553.       // Create nominal attribute "position" 
  554.       Attribute position = new Attribute("position", my_nominal_values);
  555.       
  556.       // Create vector of the above attributes 
  557.       FastVector attributes = new FastVector(3);
  558.       attributes.addElement(length);
  559.       attributes.addElement(weight);
  560.       attributes.addElement(position);
  561.       
  562.       // Create the empty dataset "race" with above attributes
  563.       Instances race = new Instances("race", attributes, 0);
  564.       
  565.       // Make position the class attribute
  566.       race.setClassIndex(position.index());
  567.       
  568.       // Create empty instance with three attribute values
  569.       SparseInstance inst = new SparseInstance(3);
  570.       
  571.       // Set instance's values for the attributes "length", "weight", and "position"
  572.       inst.setValue(length, 5.3);
  573.       inst.setValue(weight, 300);
  574.       inst.setValue(position, "first");
  575.       
  576.       // Set instance's dataset to be the dataset "race"
  577.       inst.setDataset(race);
  578.       
  579.       // Print the instance
  580.       System.out.println("The instance: " + inst);
  581.       
  582.       // Print the first attribute
  583.       System.out.println("First attribute: " + inst.attribute(0));
  584.       
  585.       // Print the class attribute
  586.       System.out.println("Class attribute: " + inst.classAttribute());
  587.       
  588.       // Print the class index
  589.       System.out.println("Class index: " + inst.classIndex());
  590.       
  591.       // Say if class is missing
  592.       System.out.println("Class is missing: " + inst.classIsMissing());
  593.       
  594.       // Print the instance's class value in internal format
  595.       System.out.println("Class value (internal format): " + inst.classValue());
  596.       
  597.       // Print a shallow copy of this instance
  598.       SparseInstance copy = (SparseInstance) inst.copy();
  599.       System.out.println("Shallow copy: " + copy);
  600.       
  601.       // Set dataset for shallow copy
  602.       copy.setDataset(inst.dataset());
  603.       System.out.println("Shallow copy with dataset set: " + copy);
  604.       // Print out all values in internal format
  605.       System.out.print("All stored values in internal format: ");
  606.       for (int i = 0; i < inst.numValues(); i++) {
  607. if (i > 0) {
  608.   System.out.print(",");
  609. }
  610. System.out.print(inst.valueSparse(i));
  611.       }
  612.       System.out.println();
  613.       // Set all values to zero
  614.       System.out.print("All values set to zero: ");
  615.       while (inst.numValues() > 0) {
  616. inst.setValueSparse(0, 0);
  617.       }
  618.       for (int i = 0; i < inst.numValues(); i++) {
  619. if (i > 0) {
  620.   System.out.print(",");
  621. }
  622. System.out.print(inst.valueSparse(i));
  623.       }
  624.       System.out.println();
  625.       // Set all values to one
  626.       System.out.print("All values set to one: ");
  627.       for (int i = 0; i < inst.numAttributes(); i++) {
  628. inst.setValue(i, 1);
  629.       }
  630.       for (int i = 0; i < inst.numValues(); i++) {
  631. if (i > 0) {
  632.   System.out.print(",");
  633. }
  634. System.out.print(inst.valueSparse(i));
  635.       }
  636.       System.out.println();
  637.       // Unset dataset for copy, delete first attribute, and insert it again
  638.       copy.setDataset(null);
  639.       copy.deleteAttributeAt(0);
  640.       copy.insertAttributeAt(0);
  641.       copy.setDataset(inst.dataset());
  642.       System.out.println("Copy with first attribute deleted and inserted: " + copy); 
  643.       // Same for second attribute
  644.       copy.setDataset(null);
  645.       copy.deleteAttributeAt(1);
  646.       copy.insertAttributeAt(1);
  647.       copy.setDataset(inst.dataset());
  648.       System.out.println("Copy with second attribute deleted and inserted: " + copy); 
  649.       // Same for last attribute
  650.       copy.setDataset(null);
  651.       copy.deleteAttributeAt(2);
  652.       copy.insertAttributeAt(2);
  653.       copy.setDataset(inst.dataset());
  654.       System.out.println("Copy with third attribute deleted and inserted: " + copy); 
  655.       
  656.       // Enumerate attributes (leaving out the class attribute)
  657.       System.out.println("Enumerating attributes (leaving out class):");
  658.       Enumeration enum = inst.enumerateAttributes();
  659.       while (enum.hasMoreElements()) {
  660. Attribute att = (Attribute) enum.nextElement();
  661. System.out.println(att);
  662.       }
  663.       
  664.       // Headers are equivalent?
  665.       System.out.println("Header of original and copy equivalent: " +
  666.  inst.equalHeaders(copy));
  667.       // Test for missing values
  668.       System.out.println("Length of copy missing: " + copy.isMissing(length));
  669.       System.out.println("Weight of copy missing: " + copy.isMissing(weight.index()));
  670.       System.out.println("Length of copy missing: " + 
  671.  Instance.isMissingValue(copy.value(length)));
  672.       System.out.println("Missing value coded as: " + Instance.missingValue());
  673.       // Prints number of attributes and classes
  674.       System.out.println("Number of attributes: " + copy.numAttributes());
  675.       System.out.println("Number of classes: " + copy.numClasses());
  676.       // Replace missing values
  677.       double[] meansAndModes = {2, 3, 0};
  678.       copy.replaceMissingValues(meansAndModes);
  679.       System.out.println("Copy with missing value replaced: " + copy);
  680.       // Setting and getting values and weights
  681.       copy.setClassMissing();
  682.       System.out.println("Copy with missing class: " + copy);
  683.       copy.setClassValue(0);
  684.       System.out.println("Copy with class value set to first value: " + copy);
  685.       copy.setClassValue("third");
  686.       System.out.println("Copy with class value set to "third": " + copy);
  687.       copy.setMissing(1);
  688.       System.out.println("Copy with second attribute set to be missing: " + copy);
  689.       copy.setMissing(length);
  690.       System.out.println("Copy with length set to be missing: " + copy);
  691.       copy.setValue(0, 0);
  692.       System.out.println("Copy with first attribute set to 0: " + copy);
  693.       copy.setValue(weight, 1);
  694.       System.out.println("Copy with weight attribute set to 1: " + copy);
  695.       copy.setValue(position, "second");
  696.       System.out.println("Copy with position set to "second": " + copy);
  697.       copy.setValue(2, "first");
  698.       System.out.println("Copy with last attribute set to "first": " + copy);
  699.       System.out.println("Current weight of instance copy: " + copy.weight());
  700.       copy.setWeight(2);
  701.       System.out.println("Current weight of instance copy (set to 2): " + copy.weight());
  702.       System.out.println("Last value of copy: " + copy.toString(2));
  703.       System.out.println("Value of position for copy: " + copy.toString(position));
  704.       System.out.println("Last value of copy (internal format): " + copy.value(2));
  705.       System.out.println("Value of position for copy (internal format): " + 
  706.  copy.value(position));
  707.     } catch (Exception e) {
  708.       e.printStackTrace();
  709.     }
  710.   }
  711. }