package fr.unistra.pelican.util.vectorial.orders;
import java.util.Arrays;
import java.util.Comparator;
import fr.unistra.pelican.util.vectorial.VectorPixel;
/**
* This class represents a flexible lexicographical ordering scheme
* for double valued arrays and derivatives.
*
* @author E.A.
*
*/
public class AlphaTrimmedLexicographicalOrdering implements VectorialOrdering,Comparator
{
private double[] alphaV = null;
private double alpha = 0.01;
public int[] syc = new int[3];
/**
*
* @param alpha
*/
public AlphaTrimmedLexicographicalOrdering(double alpha)
{
if(alpha > 0.0) this.alpha = alpha;
else this.alpha = 0.01;
}
/**
*
* @param alpha
*/
public AlphaTrimmedLexicographicalOrdering(double[] alpha)
{
for(int i = 0; i < alpha.length; i++){
if(alpha[i] <= 0.0) alpha[i] = 0.01;
}
this.alphaV = alpha;
}
private class IndexedDouble implements Comparable
{
double d;
int i;
IndexedDouble(double d,int i)
{
this.d = d; this.i = i;
}
public int compareTo(Object o){
IndexedDouble d = (IndexedDouble)o;
if(this.d < d.d) return -1;
else if(this.d > d.d) return 1;
else return 0;
}
}
private class ReverseIndexedDouble implements Comparable
{
double d;
int i;
ReverseIndexedDouble(double d,int i)
{
this.d = d; this.i = i;
}
public int compareTo(Object o){
ReverseIndexedDouble d = (ReverseIndexedDouble)o;
if(this.d < d.d) return 1;
else if(this.d > d.d) return -1;
else return 0;
}
}
/*
* (non-Javadoc)
* @see fr.unistra.pelican.util.vectorial.orders.VectorialOrdering#max(double[][])
*/
public double[] min(double[][] p)
{
if(alphaV == null){
alphaV = new double[p[0].length];
for(int i = 0; i < alphaV.length; i++)
alphaV[i] = alpha;
}
int dim = p[0].length;
for(int d = 0; d < dim - 1; d++){
// auxiliarry
IndexedDouble[] ind = new IndexedDouble[p.length];
// fill it
for(int i = 0; i < ind.length; i++)
ind[i] = new IndexedDouble(p[i][d],i);
// sort it
Arrays.sort(ind);
// keep first alpha %..IN the original array
int trimSize = (int)Math.ceil(p.length * alphaV[d]);
// get all vectors equal to the last one..
// so that we can become equivament to lexico..
// if for the dimension in progress there are more that are equal..
int tmp = trimSize;
for(int i = tmp; i < p.length; i++){
if(p[i][d] == p[tmp - 1][d]) trimSize++;
else break;
}
// if the first alpha % is too small..we're done.
if(trimSize == 1){
syc[d]++;
return p[ind[0].i];
}
// else..once more
double[][] tmp2 = new double[trimSize][dim];
for(int i = 0; i < trimSize; i++)
tmp2[i] = p[ind[i].i];
p = tmp2;
}
// we've reached the last dimension and there are still more than one
// vectors left...in that case..a simple ordering.
IndexedDouble[] ind = new IndexedDouble[p.length];
// fill it
for(int i = 0; i < ind.length; i++)
ind[i] = new IndexedDouble(p[i][dim - 1],i);
// sort it
Arrays.sort(ind);
syc[dim-1]++;
return p[ind[0].i];
}
/*
* (non-Javadoc)
* @see fr.unistra.pelican.util.vectorial.orders.VectorialOrdering#max(double[][])
*/
public double[] max(double[][] p)
{
if(alphaV == null){
alphaV = new double[p[0].length];
for(int i = 0; i < alphaV.length; i++)
alphaV[i] = alpha;
}
int dim = p[0].length;
for(int d = 0; d < dim - 1; d++){
// auxiliarry
ReverseIndexedDouble[] ind = new ReverseIndexedDouble[p.length];
// fill it
for(int i = 0; i < ind.length; i++)
ind[i] = new ReverseIndexedDouble(p[i][d],i);
// sort it
Arrays.sort(ind);
// reverse order
// keep first alpha %..IN the original array
int trimSize = (int)Math.ceil(p.length * alphaV[d]);
// get all vectors equal to the last one..
// so that we can become equivament to lexico..
// if for the dimension in progress there are more that are equal..
int tmp = trimSize;
for(int i = tmp; i < p.length; i++){
if(p[i][d] == p[tmp - 1][d]) trimSize++;
else break;
}
// if the first alpha % is too small..we're done.
if(trimSize == 1){
syc[d]++;
return p[ind[0].i];
}
// else..once more
double[][] tmp2 = new double[trimSize][dim];
for(int i = 0; i < trimSize; i++)
tmp2[i] = p[ind[i].i];
p = tmp2;
}
// we've reached the last dimension and there are still more than one
// vectors left...in that case..a simple ordering.
ReverseIndexedDouble[] ind = new ReverseIndexedDouble[p.length];
// fill it
for(int i = 0; i < ind.length; i++)
ind[i] = new ReverseIndexedDouble(p[i][dim - 1],i);
// sort it
Arrays.sort(ind);
syc[dim-1]++;
return p[ind[0].i];
}
/*
* (non-Javadoc)
* @see fr.unistra.pelican.util.vectorial.orders.VectorialOrdering#rank(double[][], int)
*/
public double[] rank(double[][] p,int r)
{
int dim = p[0].length;
for(int d = 0; d < dim - 1; d++){
// auxiliarry
IndexedDouble[] ind = new IndexedDouble[p.length];
// fill it
for(int i = 0; i < ind.length; i++)
ind[i] = new IndexedDouble(p[i][d],i);
// sort it
Arrays.sort(ind);
// eliminate the upper and lower alpha %
// not ceil...floor...we favor having less trimmed
int trimSize = (int)Math.floor(p.length * alpha);
if(trimSize > 0){
int lowerIndex = trimSize;
int upperIndex = p.length - trimSize - 1;
// total number to take
if(upperIndex < lowerIndex){
int tmp2 = upperIndex;
upperIndex = lowerIndex;
lowerIndex = tmp2;
}
int total = upperIndex - lowerIndex + 1;
// if the first alpha % is too small..we're done.
if(upperIndex == lowerIndex) return p[ind[upperIndex].i];
// else..once more
double[][] tmp2 = new double[total][dim];
//System.err.println(lowerIndex + " " + upperIndex + " " + p.length + " " + trimSize);
for(int i = lowerIndex; i <= upperIndex; i++)
tmp2[i - lowerIndex] = p[ind[i].i];
p = tmp2;
}
}
// we've reached the last dimension and there are still more than one
// vectors left...in that case..a simple ordering.
IndexedDouble[] ind = new IndexedDouble[p.length];
// fill it
for(int i = 0; i < ind.length; i++)
ind[i] = new IndexedDouble(p[i][dim - 1],i);
// sort it
Arrays.sort(ind);
//System.err.println(p.length);
return p[ind[p.length/2].i];
}
/*
* (non-Javadoc)
* @see fr.unistra.pelican.util.vectorial.orders.VectorialOrdering#order(fr.unistra.pelican.util.vectorial.VectorPixel[])
*/
public VectorPixel[] order(VectorPixel[] v)
{
Arrays.sort(v,this);
return v;
}
/**
* Compares the given arguments according to this ordering
*
* @param o1 first double valued array or vector pixel
* @param o2 second double valued array or vector pixel
* @return 1,-1 or 0 if o1 is respectively superior, inferior or equal to o2
*/
public int compare(Object o1,Object o2)
{
double[] p1 = null,p2 = null;
try{
if(o1.getClass().getName().equals("[D")){
p1 = (double[])o1;
p2 = (double[])o2;
}else if(o1.getClass().getName().equals("fr.unistra.pelican.util.vectorial.VectorPixel")){
p1 = ((VectorPixel)o1).getVector();
p2 = ((VectorPixel)o2).getVector();
}else throw new ClassCastException();
}catch(ClassCastException ex){
ex.printStackTrace();
}
for(int i = 0; i < p1.length; i++){
if(p1[i] < p2[i]) return -1;
else if(p1[i] > p2[i]) return 1;
}
return 0;
}
/*
* (non-Javadoc)
* @see fr.unistra.pelican.util.vectorial.orders.VectorialOrdering#max(double[], double[])
*/
public double[] max(double[] p,double[] r)
{
if(compare(p,r) == 1) return p;
else return r;
}
/*
* (non-Javadoc)
* @see fr.unistra.pelican.util.vectorial.orders.VectorialOrdering#min(double[], double[])
*/
public double[] min(double[] p,double[] r)
{
if(compare(p,r) == 1) return r;
else return p;
}
}