/misc/src/release/graphviz-2.18-1/src/graphviz-2.18/lib/neatogen/pca.c

Go to the documentation of this file.
00001 /* $Id: pca.c,v 1.2 2006/12/07 22:49:37 erg Exp $ $Revision: 1.2 $ */
00002 /* vim:set shiftwidth=4 ts=8: */
00003 
00004 /**********************************************************
00005 *      This software is part of the graphviz package      *
00006 *                http://www.graphviz.org/                 *
00007 *                                                         *
00008 *            Copyright (c) 1994-2004 AT&T Corp.           *
00009 *                and is licensed under the                *
00010 *            Common Public License, Version 1.0           *
00011 *                      by AT&T Corp.                      *
00012 *                                                         *
00013 *        Information and Software Systems Research        *
00014 *              AT&T Research, Florham Park NJ             *
00015 **********************************************************/
00016 
00017 
00018 #include "matrix_ops.h"
00019 #include "pca.h"
00020 #include "closest.h"
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <math.h>
00024 
00025 static int num_pairs = 4;
00026 
00027 void
00028 PCA_alloc(DistType ** coords, int dim, int n, double **new_coords,
00029           int new_dim)
00030 {
00031     double **DD = NULL;         /* dim*dim matrix: coords*coords^T */
00032     double sum;
00033     int i, j, k;
00034     double **eigs = NULL;
00035     double *evals = NULL;
00036     double *storage_ptr;
00037 
00038     eigs = N_GNEW(new_dim, double *);
00039     for (i = 0; i < new_dim; i++)
00040         eigs[i] = N_GNEW(dim, double);
00041     evals = N_GNEW(new_dim, double);
00042 
00043     DD = N_GNEW(dim, double *);
00044     storage_ptr = N_GNEW(dim * dim, double);
00045     for (i = 0; i < dim; i++) {
00046         DD[i] = storage_ptr;
00047         storage_ptr += dim;
00048     }
00049 
00050     for (i = 0; i < dim; i++) {
00051         for (j = 0; j <= i; j++) {
00052             /* compute coords[i]*coords[j] */
00053             sum = 0;
00054             for (k = 0; k < n; k++) {
00055                 sum += coords[i][k] * coords[j][k];
00056             }
00057             DD[i][j] = DD[j][i] = sum;
00058         }
00059     }
00060 
00061     power_iteration(DD, dim, new_dim, eigs, evals, TRUE);
00062 
00063     for (j = 0; j < new_dim; j++) {
00064         for (i = 0; i < n; i++) {
00065             sum = 0;
00066             for (k = 0; k < dim; k++) {
00067                 sum += coords[k][i] * eigs[j][k];
00068             }
00069             new_coords[j][i] = sum;
00070         }
00071     }
00072 
00073     for (i = 0; i < new_dim; i++)
00074         free(eigs[i]);
00075     free(eigs);
00076     free(evals);
00077     free(DD[0]);
00078     free(DD);
00079 }
00080 
00081 boolean
00082 iterativePCA_1D(double **coords, int dim, int n, double *new_direction)
00083 {
00084     vtx_data *laplacian;
00085     float **mat1 = NULL;
00086     double **mat = NULL;
00087     double eval;
00088 
00089     /* Given that first projection of 'coords' is 'coords[0]'
00090        compute another projection direction 'new_direction'
00091        that scatters points that are close in 'coords[0]'
00092      */
00093 
00094     /* find the nodes that were close in 'coords[0]' */
00095     /* and construct appropriate Laplacian */
00096     closest_pairs2graph(coords[0], n, num_pairs * n, &laplacian);
00097 
00098     /* Compute coords*Lap*coords^T */
00099     mult_sparse_dense_mat_transpose(laplacian, coords, n, dim, &mat1);
00100     mult_dense_mat_d(coords, mat1, dim, n, dim, &mat);
00101     free(mat1[0]);
00102     free(mat1);
00103 
00104     /* Compute direction */
00105     return power_iteration(mat, dim, 1, &new_direction, &eval, TRUE);
00106 /* ?? When is mat freed? */
00107 }
00108 
00109 #ifdef UNUSED
00110 
00111 double dist(double **coords, int dim, int p1, int p2)
00112 {
00113     int i;
00114     double sum = 0;
00115 
00116     for (i = 0; i < dim; i++) {
00117         sum +=
00118             (coords[i][p1] - coords[i][p2]) * (coords[i][p1] -
00119                                                coords[i][p2]);
00120     }
00121     return sqrt(sum);
00122 }
00123 
00124 
00125 void weight_laplacian(double **X, int n, int dim, vtx_data * laplacian)
00126 {
00127     int i, j, neighbor;
00128 
00129     int *edges;
00130     float *ewgts;
00131     for (i = 0; i < n; i++) {
00132         edges = laplacian[i].edges;
00133         ewgts = laplacian[i].ewgts;
00134         *ewgts = 0;
00135         for (j = 1; j < laplacian[i].nedges; j++) {
00136             neighbor = edges[j];
00137             *ewgts -= ewgts[j] =
00138                 float (-1.0 / (dist(X, dim, i, neighbor) + 1e-10));
00139         }
00140     }
00141 }
00142 
00143 #endif

Generated on Mon Mar 31 19:03:27 2008 for Graphviz by  doxygen 1.5.1