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