// FILE. . . . . d:/hak/hlt/src/hlt/fot/fuz/ArgumentMappingMatrix.java
// EDIT BY . . . Hassan Ait-Kaci
// ON MACHINE. . Hak-Laptop
// STARTED ON. . Sat Dec  1 14:40:48 2018

// This is a "homomorphic" version of the class defined for fuzzy values in:
// FILE. . . . . d:/hak/hlt/src/hlt/math/fuzzy/FuzzyMatrix.java

package hlt.fot.fuz;

import hlt.math.fuzzy.FuzzyMatrix;

import hlt.language.util.IntArrayList; // for ... ???
// for the set of fuzzy degrees used by this fuzzy matrix (see end of file):
import hlt.language.util.DoubleArrayList;

/**
 * This is a class for a square matrix each element of which consists of
 * argument-position mappings from each functor to each functor at a
 * given approximation degree, a fuzzy value (<i>i.e.</i>, a
 * <tt>double</tt> in the closed continuous interval
 * <tt>[0.0,1.0]</tt>). It is a subclass of <a
 * href="SignatureSimilarity.html"><tt>SignatureSimilarity</tt></a>,
 * itself a subclass of <a
 * href="../../math/fuzzy/FuzzyMatrix.html"><tt>hlt.math.fuzzy.FuzzyMatrix</tt></a>,
 * itself a subclass of <a
 * href="../../math/matrix/Matrix.html"><tt>hlt.math.matrix.Matrix</tt></a>.
 * It provides information on the functor-argument position mappings for
 * each similar pair of functors in the signature at each approximation
 * degree in <a
 * href="../../math/fuzzy/FuzzyMatrix.html#degrees"><tt>degrees()</tt></a>,
 * which is a <tt>DoubleArrayList</tt> inherited from <a
 * href="../../math/fuzzy/FuzzyMatrix.html"><tt>
 * FuzzyMatrix</tt></a>. It extends its parent class with validity
 * verification and closures operations on declared functor-argument
 * position mappings in addition to those it inherits on fuzzy values.
 *
 * @see         SignatureSimilarity
 * @see         ../../math/fuzzy/FuzzyMatrix
 *
 * @version     Last modified on Sat Dec 07 19:07:01 2019 by hak
 * @author      <a href="mailto:hak@acm.org">Hassan A&iuml;t-Kaci</a>
 * @copyright   &copy; <a href="http://www.hassan-ait-kaci.net/">by the author</a>
 */

public class ArgumentMappingMatrix extends SignatureSimilarity
{

  /* ******************************************************************** */
  /*                                FIELDS                                */
  /* ******************************************************************** */

  /**
   * The field <tt>mappings</tt> is an array of <a
   * href="ArgumentPositionMapping.html"><tt>ArgumentPositionMapping</tt></a>
   * objects.  It has a size equal to the size of <a
   * href="../../math/fuzzy/FuzzyMatrix.html#degrees"><tt>degrees</tt></a>,
   * the <tt>DoubleArrayList</tt> inherited from <tt>FuzzyMatrix</tt>
   * and which is the set of degrees in the matrix of fuzzy similarity
   * values <tt>data</tt> after it has been closed into a similarity
   * from a set of declared similar pairs.  Each mapping in
   * <tt>mappings</tt> can be seen as a 4-tuple of the form
   * <tt>[f,g,&alpha;,pairs<sub>f,g,&alpha;</sub>]</tt>, where: <ol>
   *
   * <li><tt>f</tt> and <tt>g</tt> are distinct similar <tt>Functor</tt>s;</li>
   *
   * <li><tt>&alpha;</tt> is the fuzzy value of this similar pair, a <tt>double</tt> in <tt>(0,1]</tt>;</li>
   *
   * <li><tt>pairs<sub>f,g,&alpha;</sub></tt> is a finite sequence of
   * pairs of argument positions such that <tt>0</tt> &leq;
   * <tt>pairs<sub>f,g,&alpha;</sub>.size()</tt> &leq;
   * <tt>Math.min(f.arity(),g.arity())</tt>;</li>
   *
   * <li>for each pair of indices <tt>i</tt> and <tt>j</tt> such that if
   * <tt>0</tt> &leq; <tt>i</tt> &leq; <tt>j</tt> &lt;
   * <tt>degrees.size()</tt>:
   *     <ul>
   *     <li><tt>mappings[i]</tt> &subseteq; <tt>mappings[j]</tt> (<i>i.e.</i>,
   *         the mappings are approximation-consistent); and,</li> 
   *
   *     <li>for any pair of functors <tt>f</tt> and <tt>g</tt>, then:
   *     <tt>pairs<sub>f,g,degrees[i]</sub></tt> &subseteq;
   *     <tt>pairs<sub>f,g,degrees[j]</sub></tt>.</li>
   *     </ul>
   *
   * </li>
   * </ol>
   */
  protected ArgumentPositionMapping[] mappings = new ArgumentPositionMapping[degrees.size()];
  

  /* ******************************************************************** */
  /*                             CONSTRUCTORS                             */
  /* ******************************************************************** */

  /** AS LONG AS THIS COMMENT IS HERE, THIS CLASS HAS NOT BEEN COMPLETELY DEFINED */

  /**
   * Creates a new <tt>ArgumentMappingMatrix</tt> object.
   */
  public ArgumentMappingMatrix (SimilarFunctorSignature signature,double[][] data)
  {
    super(signature,data);
  }

  /* ******************************************************************** */
  /*                               METHODS                                */
  /* ******************************************************************** */

  /* ******************************************************************** */

  // // /**
  // //  * Sets the <tt>i,j</tt> entry in <tt>data</tt> to <tt>degree</tt> (NB:
  // //  * <tt>i</tt> and <tt>j</tt> indices start at <tt>1</tt> and end at
  // //  * <tt>rownum</tt> and <tt>colnum</tt>). Throws a
  // //  * <tt>NonFuzzyValueException</tt> exception if <tt>degree</tt> is not
  // //  * within <tt>[0.0,1.0]</tt>.
  // //  */
  // // public ArgumentMappingMatrix set (int i, int j, double degree)
  // // {
  // //   if (i < 1 || i > rownum || j < 1 || j > colnum)
  // //     throw new RuntimeException("Row/Column index out of bounds: ("+i+","+j+")");    

  // //   // NB: adjusting indices to start at 0 for internal data array:
  // //   data[i-1][j-1] = FuzzyTools.checkFuzzyValue(degree);

  // //   return this;
  // // }

  // // /**
  // //  * Returns <tt>true</tt> if this fuzzy matrix is pointwise-equal to
  // //  * the given one.
  // //  */
  // // public boolean equals (ArgumentMappingMatrix B)
  // // {
  // //   ArgumentMappingMatrix A = this;

  // //   if (A == B)
  // //     return true;

  // //   if (A.data == B.data)
  // //     return true;

  // //   if (B.rownum != A.rownum || B.colnum != A.colnum)
  // //     throw new RuntimeException("Incompatible matrix dimensions: <"
  // // 				 +A.rownum+","+A.colnum+"> =/= <"+B.rownum+","+B.colnum+">");


  // //   for (int i = 0; i < rownum; i++)
  // //     for (int j = 0; j < colnum; j++)
  // // 	if (A.data[i][j] != B.data[i][j])
  // // 	  return false;

  // //   return true;
  // // }

  // // /**
  // //  * This is an in-place pointwise update that modifies each entry of
  // //  * this fuzzy matrix to the value of the corresponding entry in the
  // //  * given matrix.
  // //  */
  // // public ArgumentMappingMatrix update (ArgumentMappingMatrix M)
  // // {
  // //   if (rownum != M.rownum || colnum != M.colnum)
  // //     throw new RuntimeException("Incompatible matrix dimensions: <"
  // // 				 +rownum+","+colnum+"> =/= <"+M.rownum+","+M.colnum+">");

  // //   for (int i = 0; i < rownum; i++)
  // //     for (int j = 0; j < colnum; j++)
  // // 	data[i][j] = M.data[i][j];

  // //   return this;
  // // }

  // // /* ******************************************************************** */

  // // /**
  // //  * Returns a random <tt>double</tt> in <tt>[0.0,1.0]</tt>.
  // //  */
  // // public static double random ()
  // // {
  // //   double r = Math.random(); // this returns a double in [0.,1.0) - does not include 1.0

  // //   // when r is kinda close to 1.0 we toss a coin heavily biased towards not returning 1.0
  // //   if (Math.ceil(10*r) == 10.0)
  // //     if (Math.random() > 0.75)
  // // 	return 1.0;

  // //   // when r is kinda close to 0.0 we toss a coin heavily biased towards not returning 0.0
  // //   if (Math.floor(10*r) == 0.0)
  // //     if (Math.random() > 0.75)
  // // 	return 0.0;

  // //   // otherwise return r as is
  // //   return r;
  // // }

  // // /**
  // //  * Create and return a random <tt>rownum</tt>-by-<tt>colnum</tt> matrix with
  // //  * degrees in <tt>[0.0,1.0]</tt>
  // //  */
  // // public static ArgumentMappingMatrix random (int rownum, int colnum)
  // // {
  // //   ArgumentMappingMatrix M = new ArgumentMappingMatrix(rownum,colnum);

  // //   for (int i = 0; i < rownum; i++)
  // //     for (int j = 0; j < colnum; j++)
  // // 	M.data[i][j] = ArgumentMappingMatrix.random();

  // //   return M;
  // // }

  // // /* ******************************************************************** */

  // // /**
  // //  * Returns a new fuzzy matrix corresponding the transpose of this one.
  // //  */
  // // public ArgumentMappingMatrix transpose ()
  // // {
  // //   ArgumentMappingMatrix M = new ArgumentMappingMatrix(colnum,rownum);

  // //   for (int i = 0; i < rownum; i++)
  // //     for (int j = 0; j < colnum; j++)
  // // 	M.data[j][i] = data[i][j];

  // //   return M;
  // // }

  // // /**
  // //  * Returns a new <tt>ArgumentMappingMatrix</tt> equal to <tt>this</tt> plus
  // //  * <tt>M</tt> (does not modify <tt>this</tt>).
  // //  */
  // // public ArgumentMappingMatrix plus (ArgumentMappingMatrix M)
  // // {
  // //   if (rownum != M.rownum || colnum != M.colnum)
  // //     throw new RuntimeException("Incompatible matrix dimensions: <"
  // // 				 +rownum+","+colnum+"> =/= <"+M.rownum+","+M.colnum+">");

  // //   ArgumentMappingMatrix N = new ArgumentMappingMatrix(rownum,colnum);

  // //   for (int i = 0; i < rownum; i++)
  // //     for (int j = 0; j < colnum; j++)
  // // 	N.data[i][j] = sup(data[i][j],M.data[i][j]);

  // //   return N;
  // // }

  // // /**
  // //  * Modifies in place the entries of <tt>this</tt> to those of
  // //  * <tt>this</tt> plus <tt>M</tt>.
  // //  */
  // // public ArgumentMappingMatrix i_plus (ArgumentMappingMatrix M)
  // // {
  // //   if (rownum != M.rownum || colnum != M.colnum)
  // //     throw new RuntimeException("Incompatible matrix dimensions: <"
  // // 				 +rownum+","+colnum+"> =/= <"+M.rownum+","+M.colnum+">");

  // //   for (int i = 0; i < rownum; i++)
  // //     for (int j = 0; j < colnum; j++)
  // // 	data[i][j] = sup(data[i][j],M.data[i][j]);

  // //   return this;
  // // }

  // // /**
  // //  * Returns a new <tt>ArgumentMappingMatrix</tt> equal to <tt>this</tt> times
  // //  * <tt>M</tt> (does not modify <tt>this</tt>).
  // //  */
  // // public ArgumentMappingMatrix times (ArgumentMappingMatrix M)
  // // {
  // //   if (colnum != M.rownum)
  // //     throw new RuntimeException("Incompatible col/rom matrix dimensions: "+colnum+" =/= "+M.rownum);

  // //   ArgumentMappingMatrix N = new ArgumentMappingMatrix(rownum,M.colnum);

  // //   for (int i = 0; i < rownum; i++)
  // //     for (int j = 0; j < M.colnum; j++)
  // // 	{
  // // 	  double accumulator = 0.0;
  // // 	  for (int k = 0; k < colnum; k++)
  // // 	    accumulator = sup(accumulator,inf(data[i][k],M.data[k][j]));
  // // 	  N.data[i][j] = accumulator;
  // // 	}

  // //   return N;
  // // }

  // // /**
  // //  * Modifies in place the entries of <tt>this</tt> to those of
  // //  * <tt>this</tt> times <tt>M</tt>.
  // //  */
  // // public ArgumentMappingMatrix i_times (ArgumentMappingMatrix M)
  // // {
  // //   if (colnum != M.rownum)
  // //     throw new RuntimeException("Incompatible col/rom matrix dimensions: "+colnum+" =/= "+M.rownum);

  // //   for (int i = 0; i < rownum; i++)
  // //     for (int j = 0; j < M.colnum; j++)
  // // 	{
  // // 	  double accumulator = 0.0;
  // // 	  for (int k = 0; k < colnum; k++)
  // // 	    accumulator = sup(accumulator,inf(data[i][k],M.data[k][j]));
  // // 	  data[i][j] = accumulator;
  // // 	}

  // //   return this;
  // // }

  // // /* ************************************************************************ */
  
  // // /**
  // //  * <a id="degrees"/>
  // //  * Contains the set of degrees of this fuzzy matrix in ascending order.
  // //  */
  // // final protected DoubleArrayList degrees = new DoubleArrayList(); // the degrees of this fuzzy matrix

  // // /**
  // //  * Returns the set of degrees of this fuzzy matrix.
  // //  */
  // // public final DoubleArrayList degrees ()
  // // {
  // //   if (degrees.isEmpty())
  // //     computeDegrees();

  // //   return degrees;
  // // }

  // // /**
  // //  * Recomputes and returns the set of degrees of this fuzzy matrix.
  // //  */
  // // public final void computeDegrees ()
  // // {
  // //   degrees.setSize(0); // erase all entries if any

  // //   for (int i = 0; i < rownum; i++)
  // //     for (int j = 0; j < colnum; j++)
  // // 	addDegree(data[i][j]);
  // // }

  // // /**
  // //  * Inserts a double <tt>degree</tt> into this matrix' set of degree
  // //  * keeping this set sorted in increasing order, and returns the set.
  // //  */
  // // protected final DoubleArrayList addDegree (double degree)
  // // {
  // //   int i = 0;

  // //   while (i < degrees.size() && degree > degrees.get(i))
  // //     i++;

  // //   if (degree != degrees.get(i))
  // //     degrees.add(i,degree); // will shift degrees at indices to the right and insert degree at i

  // //   return degrees;
  // // }

  // // /* ************************************************************************ */

  // // /**
  // //  * Default <tt>double</tt> precision for <tt>printf</tt>.
  // //  */
  // // public static String precision = "%9.4f ";

  // // /**
  // //  * Prints this fuzzy matrix to standard output
  // //  */
  // // public void show ()
  // // {
  // //   for (int i = 0; i < rownum; i++)
  // //     {
  // // 	for (int j = 0; j < colnum; j++)
  // // 	  System.out.printf(precision, data[i][j]);
  // // 	System.out.println();
  // //     }
  // // }





  // // /* ************************************************************************ */


  // // /**
  // //  * Returns the number of rows and columns.
  // //  */
  // // public final int rank ()
  // // {
  // //   return rownum; // or colnum
  // // }

  // // /**
  // //  * Create an <tt>N</tt>-by-<tt>N</tt> matrix of <tt>0.0</tt>'s.
  // //  */
  // // public PositionMappingMatrix (int N)
  // // {
  // //   super(N,N);
  // // }

  // // /**
  // //  * Create a square fuzzy matrix matrix with the values in data array
  // //  * of <tt>double</tt>s.
  // //  */
  // // public PositionMappingMatrix (double[][] data)
  // // {
  // //   super(data);
    
  // //   if (data.length != data[0].length)
  // //     throw new RuntimeException("Attempt to create a square fuzzy matrix with a non-square "
  // // 				 +data.length+"x"+data[0].length+" data array ");
  // // }

  // // /**
  // //  * Create a square fuzzy matrix matrix with the values in data array
  // //  * of the given <tt>PositionMappingMatrix</tt>.
  // //  */
  // // public PositionMappingMatrix (PositionMappingMatrix M)
  // // {
  // //   super(M.data);
  // // }

  // // /**
  // //  * Create a square fuzzy matrix with the given data array if
  // //  * <tt>copy</tt> is <tt>false</tt>, or with a new array containing the
  // //  * values in <tt>data</tt> array if <tt>copy</tt> is <tt>true</tt>, in
  // //  * which case it also verifies that all the values in <tt>data</tt>
  // //  * are all within <tt>[0.0,0.1]</tt>.
  // //  * 
  // //  */
  // // public PositionMappingMatrix (double[][] data, boolean copy)
  // // {
  // //   super(data,copy);

  // //   if (data.length != data[0].length)
  // //     throw new RuntimeException("Attempt to create a square fuzzy matrix with a non-square "
  // // 				 +data.length+"x"+data[0].length+" data array ");
  // // }

  // // /* ******************************************************************** */

  // // /**
  // //  * Create and return a new <tt>rank</tt>-by-<tt>rank</tt> identity matrix.
  // //  */
  // // public static PositionMappingMatrix identity (int rank)
  // // {
  // //   PositionMappingMatrix I = new PositionMappingMatrix(rank);

  // //   for (int i = 0; i < rank; i++)
  // //     I.data[i][i] = 1.0;

  // //   return I;
  // // }

  // // /**
  // //  * Create and return a random <tt>rank</tt>-by-<tt>rank</tt> square matrix
  // //  * with values in <tt>[0.0,1.0]</tt>.
  // //  */
  // // public static PositionMappingMatrix random (int rank)
  // // {
  // //   PositionMappingMatrix M = new PositionMappingMatrix(rank);

  // //   for (int i = 0; i < rank; i++)
  // //     for (int j = 0; j < rank; j++)
  // // 	M.data[i][j] = ArgumentMappingMatrix.random();

  // //   return M;
  // // }

  // // /**
  // //  * Returns this matrix' in-place transpose [modifies this
  // //  * <tt>PositionMappingMatrix</tt>'s <tt>data</tt> array in
  // //  * place]. This method is not defined for the superclass
  // //  * <tt>ArgumentMappingMatrix</tt> since it makes sense only when it
  // //  * is square. (However, non-destructive transpose is defined in
  // //  * <tt>ArgumentMappingMatrix</tt> since it makes sense for any
  // //  * rectangular matrice.)
  // //  */
  // // public PositionMappingMatrix i_transpose ()
  // // {
  // //   int rank = rank();
    
  // //   for (int i = 0; i < rank; i++)
  // //     for (int j = i+1; j < rank; j++)
  // // 	{
  // // 	  double tmp = data[i][j];
  // // 	  data[i][j] = data[j][i];
  // // 	  data[j][i] = tmp;
  // // 	}

  // //   return this;
  // // }

  // // /* ******************************************************************** */

  // // /**
  // //  * Returns a new <tt>PositionMappingMatrix</tt> that is the reflexive
  // //  * closure of this <tt>PositionMappingMatrix</tt>.
  // //  */
  // // public PositionMappingMatrix reflexive_closure ()
  // // {
  // //   return (new PositionMappingMatrix(data)).i_reflexive_closure();
  // // }

  // /**
  //  * Sets this square fuzzy matrix to its reflexive closure and returns it(self).
  //  */
  // public PositionMappingMatrix i_reflexive_closure ()
  // {
  //   for (int i=0; i < rank(); i++)
  //     data[i][i] = 1.0;

  //   return this;
  // }

  // /**
  //  * Returns a new <tt>PositionMappingMatrix</tt> that is the symmetric
  //  * closure of this <tt>PositionMappingMatrix</tt>.
  //  */
  // public PositionMappingMatrix symmetric_closure ()
  // {
  //   return (new PositionMappingMatrix(data)).i_symmetric_closure();
  // }

  // /**
  //  * Sets this <tt>PositionMappingMatrix</tt> to its symmetric closure and returns it(self).
  //  */
  // public PositionMappingMatrix i_symmetric_closure ()
  // {
  //   int rank = rank();
    
  //   for (int i = 0; i < rank; i++)
  //     for (int j = i+1; j < rank; j++)
  // 	{
  // 	  data[i][j] = sup(data[i][j],data[j][i]);
  // 	  data[j][i] = data[i][j];
  // 	}

  //   return this;
  // }

  // /**
  //  * Returns and <tt>PositionMappingMatrix</tt> that is the transitive
  //  * closure of this <tt>PositionMappingMatrix</tt>.
  //  */
  // public PositionMappingMatrix transitive_closure ()
  // {
  //   return (new PositionMappingMatrix(data)).i_transitive_closure();
  // }

  // /**
  //  * Sets this <tt>PositionMappingMatrix</tt> to its transitive closure and
  //  * returns it(self). It computes it using the so-called <i>cubic</i>
  //  * method.
  //  */
  // public PositionMappingMatrix i_transitive_closure ()
  // {
  //   int rank = rank();

  //   for (int k = 0; k < rank; k++)
  //     for (int i = 0; i < rank; i++)
  // 	for (int j = 0; j < rank; j++)
  // 	  data[i][j] = sup(data[i][j],inf(data[i][k],data[k][j]));

  //   return this;
  // }

  // /**
  //  * Returns a <tt>PositionMappingMatrix</tt> that is the similarity closure
  //  * of this <tt>PositionMappingMatrix</tt>.
  //  */
  // public PositionMappingMatrix similarity_closure ()
  // {
  //   return reflexive_closure().i_symmetric_closure().i_transitive_closure();
  // }

  // /**
  //  * Sets this  <tt>PositionMappingMatrix</tt> to its similarity closure and returns it(self).
  //  */
  // public PositionMappingMatrix i_similarity_closure ()
  // {
  //   return i_reflexive_closure().i_symmetric_closure().i_transitive_closure();
  // }

  // /* ******************************************************************** */

  // /**
  //  * When this <tt>PositionMappingMatrix</tt> is a similarity relation on
  //  * the set <tt>{0,...,N}</tt>, <tt>partition(cut)</tt> (where
  //  * <tt>cut</tt> is a <tt>double</tt> in <tt>[0.0,1.0]</tt>)
  //  * returns an array of <tt>N</tt> <tt>IntArrayList</tt>s each
  //  * containing the indices in the set <tt>{0,...,N}</tt> constituting a
  //  * similarity class at fuzzy approximation degree greater than or
  //  * equal to <tt>cut</tt> (<i>i.e.</i>, it is a partition of the
  //  * set <tt>{0,...,N}</tt> for similarity degrees that are not less
  //  * than <tt>cut</tt>). Each <tt>IntArrayList</tt> at index
  //  * <tt>i</tt> contains the indices of the elements in the class
  //  * <tt>[i]</tt> ordered in ascending order. Each class is uniquely
  //  * represented and shared by all indices in the class (it is the same
  //  * <tt>IntArrayList</tt> object) for all indices it contains. For
  //  * example, if for <tt>N=6</tt>, the matrix is:
  //  *
  //  * <p>
  //  *
  //  * <pre>
  //  *      0   1   2   3   4   5
  //  *     --- --- --- --- --- ---
  //  * 0 | 1.0 0.5 0.0 0.5 0.4 0.2
  //  * 1 | 0.5 1.0 0.0 0.5 0.4 0.0
  //  * 2 | 0.0 0.0 1.0 0.0 0.0 0.0
  //  * 3 | 0.5 0.5 0.0 1.0 0.4 1.2
  //  * 4 | 0.4 0.4 0.0 0.4 1.0 0.2
  //  * 5 | 0.2 0.2 0.0 0.2 0.2 1.0
  //  * </pre>
  //  * then its <tt>partition(0.4)</tt> array is:
  //  * <pre>
  //  * 0: A
  //  * 1: A
  //  * 2: B
  //  * 3: A
  //  * 4: A
  //  * 5: C
  //  * </pre>
  //  * where <tt>A=[0,1,3,4]</tt>, <tt>B=[2]</tt>, and <tt>C=[5]</tt>.
  //  */
  // public IntArrayList[] partition (double cut)
  // {
  //   int rank = rank();
    
  //   // The array of rank classes
  //   IntArrayList[] classes = new IntArrayList[rank];

  //   // initialize all classes to singletons
  //   for (int i=0; i < rank; i++)
  //     {
  // 	classes[i] = new IntArrayList();
  // 	classes[i].add(i);
  //     }

  //   // sweep through the upper right triangle and merge the partitions
  //   // of equivalent pairs over or at the cut
  //   for (int i=0; i < rank-1; i++)
  //     // {
  // 	for (int j=i+1; j < rank; j++)
  // 	  if (data[i][j] >= cut)
  // 	    // merge the classes at indices i and j and sets all related elements classes
  // 	    merge(classes,i,j);

  //   return classes;
  // }

  // /**
  //  * This merges the classes <tt>classes[i]</tt> and <tt>classes[j]</tt>
  //  * into a new class keeping it sorted in increasing order, and sets
  //  * <tt>classes[k]</tt> to be this new merged class for all indices
  //  * <tt>k</tt> in this class.
  //  */
  // private void merge (IntArrayList[] classes, int i, int j)
  // {
  //   IntArrayList c1 = classes[i];
  //   IntArrayList c2 = classes[j];

  //   if (c1 != c2) // otherwise this would keep going
  //     if (c2.size() < c1.size())
  // 	{
  // 	  for (int k=0; k < c2.size(); k++)
  // 	    insertIndex(c2.get(k),c1);
  // 	  // update all appropriate classes to the merged class
  // 	  for (int k=0; k < c1.size(); k++)
  // 	    classes[c1.get(k)] = c1;
  // 	}
  //     else
  // 	{
  // 	  for (int k=0; k < c1.size(); k++)
  // 	    insertIndex(c1.get(k),c2);
  // 	  // update all appropriate classes to the merged class
  // 	  for (int k=0; k < c2.size(); k++)
  // 	    classes[c2.get(k)] = c2;
  // 	}
  // }

  // /**
  //  * Adds <tt>index</tt> to <tt>orderedClass</tt> keeping it in
  //  * increasing order.
  //  */
  // private void insertIndex (int index, IntArrayList orderedClass)
  // {
  //   int size = orderedClass.size();
  //   int i = 0;
  //   while (i < size && orderedClass.get(i) < index)
  //     i++;

  //   if (index != orderedClass.get(i))
  //     orderedClass.add(i,index);
  // }

}

