import java.io.*;
import java.util.*;
import java.text.*;
import Jama.*;
/**
* CAfuzzy - Correspondence Analysis on Fuzzy Input
* Jama Matrix class package, "JAMA: A Java Matrix Package" is used.
* See: http://math.nist.gov/javanumerics/jama
* Example of use:
* javac CAfuzzy.java
* java CAfuzzy iris.dat >
* caoutput.txt
* Format of input data set:
*
* - integer row and column dimensions,
*
- followed by floating values
*
- which are read row-wise.
*
* Outputs produced:
*
* - Echo of input file name, input dimensions, sample of data
*
- Matrix to be diagonalized
*
- Eigenvectors
*
- Eigenvalues and as cumulative percentages
*
- Row projections in new factor space
*
- Column projections in new factor space
*
- Row contributions to factors
*
- Column contributions to factors
*
* Version: 2002 Aug. 16
* Author: F. Murtagh, f.murtagh@qub.ac.uk
* @version 2002 Aug 16
* @author F. Murtagh, f.murtagh@qub.ac.uk
*/
public class CAfuzzy{
public static final double EPS = 1.0e-8;
public static void main (String argv[])
{
PrintStream out = System.out;
try{
//-------------------------------------------------------------------
if (argv.length == 0) {
System.out.println(" Syntax: java CAfuzzy infile.dat ");
System.out.println(" Input file format: ");
System.out.println(" Line 1: integer no. rows, no. cols.");
System.out.println(" Successive lines: matrix values, floating");
System.out.println(" Read in row-wise");
System.exit (1);
}
String filname = argv[0];
System.out.println (" Input file name: " + filname);
// Open the matrix file
FileInputStream is = new FileInputStream(filname);
BufferedReader bis = new BufferedReader(new InputStreamReader(is));
StreamTokenizer st = new StreamTokenizer(bis);
// Row and column sizes, read in first
st.nextToken(); int n = (int)st.nval;
st.nextToken(); int m = (int)st.nval;
System.out.println(" No. of rows, n = " + n);
System.out.println(" No. of cols, m = " + m);
// Input array, values to be read in successively, float
double[][] indat = new double[n][m];
double inval;
// New read in input array values, successively
System.out.println
(" Input data sample follows as a check, first 4 values.");
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
st.nextToken();
inval = (double)st.nval;
indat[i][j] = inval;
if (i < 2 && j < 2) {
System.out.println(" value = " + inval);
}
}
}
System.out.println();
// Some output formating parameters
int collo = 2; // start col for output printing
int colhi = 5; // last col for output printing
int nplac = 10; // no. of places in output float values
int ndec = 4; // no. of dec. places in output
//-------------------------------------------------------------------
int mnew;
// Data preprocessing - fuzzify
double[][] indatstd = Fuzzify(n, m, indat);
mnew = 2*m; // fuzzification has expanded col dim by 2
// Data to be analyzed is now indatstd, with dims n x 2m, or n x mnew
double rowsums[] = new double[n];
double colsums[] = new double[mnew];
double total = 0.0;
// Row sums and overall total
for (int i = 0; i < n; i++) {
rowsums[i] = 0.0;
for (int j = 0; j < mnew; j++) {
rowsums[i] += indatstd[i][j];
total += indatstd[i][j];
}
}
// Col sums
for (int j = 0; j < mnew; j++) {
colsums[j] = 0.0;
for (int i = 0; i largest eval, first always = 1):");
// evecs contains the cols. ordered right to left
// Evecs is the more natural order with cols. ordered left to right
// So to repeat: leftmost col. of Evecs is assoc with largest Evals
// Evals and Evecs ordered from left to right
double tot = 0.0;
for (int j = 0; j < evals.length; j++) {
tot += evals[j];
}
// reverse order of evals into Evals
double[] Evals = new double[mnew];
for (int j = 0; j < mnew; j++) {
Evals[j] = evals[mnew - j - 1];
}
// reverse order of Matrix evecs into Matrix Evecs
double[][] tempold = evecs.getArray();
double[][] Evex = new double[mnew][mnew];
for (int j1 = 0; j1 < mnew; j1++) {
for (int j2 = 0; j2 < mnew; j2++) {
Evex[j1][j2] = tempold[j1][mnew - j2 - 1] /
Math.sqrt(colsums[j1]);
}
}
Matrix Evecs = new Matrix(Evex);
Evecs.print(10,4);
// So as a JAMA Matrix, we have Evecs, and
// as a multidim. array of dims mnew x mnew, we have Evex
System.out.println();
System.out.println
(" E-vals. (first always = 1) and as cumul. perc. (first excl.):");
double runningtotal = 0.0;
double[] percentevals = new double[mnew];
// low index in following = 1 to exclude first trivial eval.
percentevals[0] = 0.0;
for (int j = 1; j < Evals.length; j++) {
percentevals[j] = runningtotal + 100.0*Evals[j]/(tot-1.0);
runningtotal = percentevals[j];
}
printVect(Evals, 4, 10);
printVect(percentevals, 4, 10);
//-------------------------------------------------------------------
// Projections - row, and col
// Row projections in new space, X U Dims: (n x m) x (m x m)
System.out.println();
System.out.println
(" Row projections in new factor space. Start, end columns: " +
collo + " " + colhi);
double rowproj[][] = new double[n][mnew];
for (int i = 0; i < n; i++) {
for (int j1 = 0; j1 < mnew; j1++) {
rowproj[i][j1] = 0.0;
for (int j2 = 0; j2 < mnew; j2++) {
rowproj[i][j1] += indatstd[i][j2]*Evex[j2][j1];
}
if (rowsums[i] >= EPS) rowproj[i][j1] /= rowsums[i];
if (rowsums[i] < EPS) rowproj[i][j1] = 0.0;
}
}
// Print from cols collo to colhi;
// precision: nplac chars in total, ndec dec places
printMatrix(n, mnew, rowproj, collo, colhi, ndec, nplac);
System.out.println ();
System.out.println
(" Column projections in new factor space. Start, end columns: " +
collo + " " + colhi);
double colproj[][] = new double[mnew][mnew];
for (int j1 = 0; j1 < mnew; j1++) {
for (int j2 = 0; j2 < mnew; j2++) {
colproj[j1][j2] = 0.0;
for (int j3 = 0; j3 < mnew; j3++) {
colproj[j1][j2] += CP[j1][j3] * Evex[j3][j2] *
Math.sqrt(colsums[j3]);
}
if (colsums[j1] >= EPS && Evals[j2] >= EPS)
colproj[j1][j2] /= Math.sqrt(Evals[j2]*colsums[j1]);
if (colsums[j1] < EPS && Evals[j2] < EPS)
colproj[j1][j2] = 0.0;
}
}
// Print from cols collo to colhi;
// precision: nplac chars in total, ndec dec places
printMatrix(mnew, mnew, colproj, collo, colhi, ndec, nplac);
System.out.println ();
System.out.println
(" Row contributions to factors. Start, end columns: " +
collo + " " + colhi);
double rowcntr[][] = new double[n][mnew];
double rowconColsum;
for (int j = 0; j < mnew; j++) {
rowconColsum = 0.0;
for (int i = 0; i < n; i++) {
rowcntr[i][j] = rowsums[i]*Math.pow(rowproj[i][j], 2.0);
rowconColsum += rowcntr[i][j];
}
// Normalize so that sum of contributions for a factor equals 1
for (int i = 0; i < n; i++) {
if (rowconColsum > EPS) rowcntr[i][j] /= rowconColsum;
if (rowconColsum <= EPS) rowcntr[i][j] = 0.0;
}
}
// Print from cols collo to colhi;
// precision: nplac chars in total, ndec dec places
printMatrix(n, mnew, rowcntr, collo, colhi, ndec, nplac);
System.out.println ();
System.out.println
(" Column contributions to factors. Start, end columns: " +
collo + " " + colhi);
double colcntr[][] = new double[mnew][mnew];
double colconColsum;
for (int j1 = 0; j1 < mnew; j1++) {
colconColsum = 0.0;
for (int j2 = 0; j2 < mnew; j2++) {
colcntr[j2][j1] = colsums[j2]*Math.pow(colproj[j2][j1], 2.0);
colconColsum += colcntr[j2][j1];
}
// Normalize so that sum of contributions for a factor sum to 1
for (int j2 = 0; j2 < mnew; j2++) {
if (colconColsum > EPS) colcntr[j2][j1] /= colconColsum;
if (colconColsum <= EPS) colcntr[j2][j1] = 0.0;
}
}
// Print from cols collo to colhi;
// precision: nplac chars in total, ndec dec places
printMatrix(mnew, mnew, colcntr, collo, colhi, ndec, nplac);
//-------------------------------------------------------------------
// That's it.
}
catch (IOException e) {
out.println("error: " + e);
System.exit(1);
}
} // end of main
//-------------------------------------------------------------------
// Little method for helping in output formating
public static String getSpaces(int n) {
StringBuffer sb = new StringBuffer(n);
for (int i = 0; i < n; i++) sb.append(' ');
return sb.toString();
} // getSpaces
//-------------------------------------------------------------------
/**
* Method for printing a matrix
* @param n1 row dimension of matrix
* @param n2 column dimension of matrix
* @param m input matrix values
* @param collo start column for printing
* @param colhi end column for printing
* @param d display precision, number of decimal places
* @param w display precision, total width of floating value
*/
public static void printMatrix(int n1, int n2, double[][] m,
int collo, int colhi, int d, int w)
{
// Some definitions for handling output formating
NumberFormat myFormat = NumberFormat.getNumberInstance();
FieldPosition fp = new FieldPosition(NumberFormat.INTEGER_FIELD);
myFormat.setMaximumIntegerDigits(d);
myFormat.setMaximumFractionDigits(d);
myFormat.setMinimumFractionDigits(d);
for (int i=0; i
* @param m input vector of length m.length
* @param d display precision, number of decimal places
* @param w display precision, total width of floating value
*/
public static void printVect(double[] m, int d, int w)
{
// Some definitions for handling output formating
NumberFormat myFormat = NumberFormat.getNumberInstance();
FieldPosition fp = new FieldPosition(NumberFormat.INTEGER_FIELD);
myFormat.setMaximumIntegerDigits(d);
myFormat.setMaximumFractionDigits(d);
myFormat.setMinimumFractionDigits(d);
int len = m.length;
for (int i=0; i
* @param nrow number of rows in input matrix
* @param ncol number of columns in input matrix
* @param A input matrix values
* @param ncolnew new number of columns in transformed data
*/
public static double[][] Fuzzify(int nrow, int ncol, double[][] A)
{
// Adat will contain the fuzzified data and will be returned
double[][] Adat = new double[nrow][2*ncol];
double[] coltemp = new double[nrow];
double perc25, perc50, perc75; // percentiles
int medloc, p25loc, p75loc; // percentile offsets
medloc = nrow/2;
p25loc = nrow/4;
p75loc = (3*nrow)/4;
for (int j = 0; j < ncol; j++) {
// for each col
for (int i = 0; i < nrow; i++) coltemp[i] = A[i][j];
inSort(coltemp); // sort in place, modifying values
perc50 = coltemp[medloc];
perc25 = coltemp[p25loc];
perc75 = coltemp[p75loc];
// System.out.println(perc50 + " " +
// perc25 + " " +
// perc75);
for (int i = 0; i < nrow; i++) {
if (A[i][j] > perc75) {
Adat[i][2*j] = 0;
Adat[i][2*j+1] = 1;
}
if (A[i][j] < perc25) {
Adat[i][2*j] = 1;
Adat[i][2*j+1] = 0;
}
if (A[i][j] <= perc75 && A[i][j] >= perc25) {
Adat[i][2*j] = (A[i][j] - perc25)/(perc75 - perc25);
Adat[i][2*j+1] = 1.0 - Adat[i][2*j];
}
}
}
return Adat;
} // Fuzzify
//-------------------------------------------------------------------
/**
* Method to sort a double vector, by inefficient straight insertion
* See section 8.1, p. 243, of Numerical Recipes in C.
* @param invect input data to be sorted, sorted in place
*/
private static void inSort (double[] invect) {
double a;
int i;
for (int j = 2; j < invect.length; j++) {
a = invect[j];
i = j - 1;
while (i > 0 && invect[i] > a) {
invect[i+1] = invect[i];
i--;
}
invect[i+1] = a;
}
// Return type void
} // inSort
} // CAfuzzy