/*********************************************************************** This file is part of KEEL-software, the Data Mining tool for regression, classification, clustering, pattern mining and so on. Copyright (C) 2004-2010 F. Herrera (herrera@decsai.ugr.es) L. S�nchez (luciano@uniovi.es) J. Alcal�-Fdez (jalcala@decsai.ugr.es) S. Garc�a (sglopez@ujaen.es) A. Fern�ndez (alberto.fernandez@ujaen.es) J. Luengo (julianlm@decsai.ugr.es) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/ **********************************************************************/ /** * File: WilcoxonDistribution.java. * * Class modelling Wilcoxon distribution * * @author Written by Joaquin Derrac (University of Granada) 1/12/2010 * @version 1.0 * @since JDK1.5 */ package keel.GraphInterKeel.statistical.tests; import java.io.IOException; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; public class WilcoxonDistribution{ private static Distribution2KeyTable table; private static boolean initialized = false; private static boolean notInteger; private static NormalDistribution normal; private static double leftTail; private static double rightTail; private static double doubleTail; /** * Computes exact p-values for the Wilcoxon distribution, given that N<50 * * @param N N parameter * @param R R parameter * * @return Exact p-value (1.0 if greater than 0.2, -1.0 if not computable) */ public static double computeExactProbability(int N,double R){ double pValue,value1,value2; if(!initialized){ loadTable(); initialized=true; } if(N>50){ return -1.0; } if(isInt(R)){ notInteger=false; } else{ notInteger=true; } try{ if(!notInteger){ pValue=table.get((int)R, N); if(pValue==-1.0){ pValue=1.0; } }else{ value1=table.get((int)Math.ceil(R), N); if(value1==-1.0){ value1=1.0; } value2=table.get((int)Math.floor(R), N); if(value2==-1.0){ value2=1.0; } pValue=(value1+value2)/2.0; } } catch(ArrayIndexOutOfBoundsException e){ return 1.0; } return pValue; }//end-method /** * Computes asymptotic distribution of the Wilcoxon statistic * * @param N N parameter * @param R R parameter * @param ties Integer vector representing the number and lenght of the ties found in the computation of ranks * * @return Asymptotic p-value */ public static double computeAsymptoticProbability(int N,double R,int [] ties){ double numerator1,numerator2,denominator; double z; double sumTies; normal=new NormalDistribution(); numerator1=R-0.5-(N*(N+1.0)/4.0); numerator2=R+0.5-(N*(N+1.0)/4.0); denominator=Math.sqrt(N*(N+1.0)*((2*N)+1.0)/24.0); if(ties.length>0){ sumTies=0.0; for(int i=0;i<ties.length;i++){ sumTies+=ties[i]*((ties[i]*ties[i])-1.0); } denominator-=sumTies/48.0; } z=numerator1/denominator; leftTail=1.0-normal.getTipifiedProbability(z, true); z=numerator2/denominator; rightTail=normal.getTipifiedProbability(z, false); doubleTail=Math.min(leftTail, rightTail)*2.0; doubleTail=Math.min(doubleTail,1.0); return doubleTail; }//end-method /** * Returns double-tailed p-value of the last comparison * * @return Double-tailed p-value */ public static double getDoubleTail(){ return doubleTail; }//end-method /** * Returns left-tailed p-value of the last comparison * * @return Left-tailed p-value */ public static double getLeftTail(){ return leftTail; }//end-method /** * Returns right-tailed p-value of the last comparison * * @return Right-tailed p-value */ public static double getRightTail(){ return rightTail; }//end-method /** * Tests if a given double represents an integer value * * @param x Double to test * @param delta Acceptance threshold * * @return If a given double represents an integer value */ private static boolean isInt(double x, double delta) { double ceil = Math.ceil(x); return x-delta<ceil && x+delta>ceil; }//end-method /** * Tests if a given double represents an integer value * * @param x Double to test * * @return If a given double represents an integer value */ private static boolean isInt(double x) { return isInt(x, 0.000000001); }//end-method /** * Load table for Wilcoxon distribution */ private static void loadTable(){ table=new Distribution2KeyTable(505,51); loadXML(); }//end-method /** * Get the inner table * * @return Pointer to the table */ public static Distribution2KeyTable getTable(){ return table; }//end-method /** * Load Wilcoxon distribution table from a XML file */ private static void loadXML(){ try{ SAXParserFactory spf=SAXParserFactory.newInstance(); SAXParser sp = spf.newSAXParser(); sp.parse("./help/WilcoxonTable.xml", new WilcoxonReaderFormat()); }catch(ParserConfigurationException e){ System.err.println("Parser error"); }catch(SAXException e2){ System.err.println("SAX error: " + e2.getStackTrace()); } catch (IOException e3) { System.err.println("Input/Output error: " + e3.getMessage() ); } }//end-method }//end-class /** * Inner class representing the format of XML Wilcoxon distribution * * @author Joaquin */ class WilcoxonReaderFormat extends DefaultHandler { int n; int r; String st; /** * Builder */ public WilcoxonReaderFormat(){ super(); r=0; n=4; clearTable(); }//end-method /** * Start document actions */ public void startDocument() throws SAXException{ }//end-method /** * End document actions */ public void endDocument()throws SAXException{ }//end-method /** * Start Element actions */ public void startElement(String uri, String localName, String qName, Attributes attributes) { }//end-method /** * Reading characters * @param buf Buffer of characters * @param offset Offset * @param len Number of characters readed * @throws org.xml.sax.SAXException */ public void characters(char buf[], int offset, int len) throws SAXException{ st = new String(buf, offset, len); }//end-method /** * En of an element * * @param uri Uri * @param localName Local name * @param qName Tag name */ public void endElement(String uri, String localName, String qName) { if(qName.equals("element")){ addElement(); n++; } if(qName.equals("row")){ n=4; r++; } }//end-method /** * Clear asociated table */ private void clearTable(){ WilcoxonDistribution.getTable().clear(); }//end-method /** * Add an element to the asociated table */ private void addElement(){ WilcoxonDistribution.getTable().addValue(r, n, Double.parseDouble(st)); }//end-method }//end-class