|
Graphviz
2.29.20120524.0446
|
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 #include "digcola.h" 00015 #ifdef DIGCOLA 00016 #include "kkutils.h" 00017 #include "matrix_ops.h" 00018 #include "conjgrad.h" 00019 00020 static void 00021 standardize(double* orthog, int nvtxs) 00022 { 00023 double len, avg = 0; 00024 int i; 00025 for (i=0; i<nvtxs; i++) 00026 avg+=orthog[i]; 00027 avg/=nvtxs; 00028 00029 /* centralize: */ 00030 for (i=0; i<nvtxs; i++) 00031 orthog[i]-=avg; 00032 00033 /* normalize: */ 00034 len = norm(orthog, 0, nvtxs-1); 00035 vecscale(orthog, 0, nvtxs-1, 1.0 / len, orthog); 00036 } 00037 00038 static void 00039 mat_mult_vec_orthog(float** mat, int dim1, int dim2, double* vec, 00040 double* result, double* orthog) 00041 { 00042 /* computes mat*vec, where mat is a dim1*dim2 matrix */ 00043 int i,j; 00044 double sum; 00045 00046 for (i=0; i<dim1; i++) { 00047 sum=0; 00048 for (j=0; j<dim2; j++) { 00049 sum += mat[i][j]*vec[j]; 00050 } 00051 result[i]=sum; 00052 } 00053 if (orthog!=NULL) { 00054 double alpha=-dot(result,0,dim1-1,orthog); 00055 scadd(result, 0, dim1-1, alpha, orthog); 00056 } 00057 } 00058 00059 static void 00060 power_iteration_orthog(float** square_mat, int n, int neigs, 00061 double** eigs, double* evals, double* orthog, double p_iteration_threshold) 00062 { 00063 /* 00064 * Power-Iteration with (I-orthog*orthog^T)*square_mat*(I-orthog*orthog^T) 00065 */ 00066 00067 int i,j; 00068 double *tmp_vec = N_GNEW(n, double); 00069 double *last_vec = N_GNEW(n, double); 00070 double *curr_vector; 00071 double len; 00072 double angle; 00073 double alpha; 00074 int iteration; 00075 int largest_index; 00076 double largest_eval; 00077 00078 double tol=1-p_iteration_threshold; 00079 00080 if (neigs>=n) { 00081 neigs=n; 00082 } 00083 00084 for (i=0; i<neigs; i++) { 00085 curr_vector = eigs[i]; 00086 /* guess the i-th eigen vector */ 00087 choose: 00088 for (j=0; j<n; j++) { 00089 curr_vector[j] = rand()%100; 00090 } 00091 00092 if (orthog!=NULL) { 00093 alpha=-dot(orthog,0,n-1,curr_vector); 00094 scadd(curr_vector, 0, n-1, alpha, orthog); 00095 } 00096 // orthogonalize against higher eigenvectors 00097 for (j=0; j<i; j++) { 00098 alpha = -dot(eigs[j], 0, n-1, curr_vector); 00099 scadd(curr_vector, 0, n-1, alpha, eigs[j]); 00100 } 00101 len = norm(curr_vector, 0, n-1); 00102 if (len<1e-10) { 00103 /* We have chosen a vector colinear with prvious ones */ 00104 goto choose; 00105 } 00106 vecscale(curr_vector, 0, n-1, 1.0 / len, curr_vector); 00107 iteration=0; 00108 do { 00109 iteration++; 00110 cpvec(last_vec,0,n-1,curr_vector); 00111 00112 mat_mult_vec_orthog(square_mat,n,n,curr_vector,tmp_vec,orthog); 00113 cpvec(curr_vector,0,n-1,tmp_vec); 00114 00115 /* orthogonalize against higher eigenvectors */ 00116 for (j=0; j<i; j++) { 00117 alpha = -dot(eigs[j], 0, n-1, curr_vector); 00118 scadd(curr_vector, 0, n-1, alpha, eigs[j]); 00119 } 00120 len = norm(curr_vector, 0, n-1); 00121 if (len<1e-10) { 00122 /* We have reached the null space (e.vec. associated 00123 * with e.val. 0) 00124 */ 00125 goto exit; 00126 } 00127 00128 vecscale(curr_vector, 0, n-1, 1.0 / len, curr_vector); 00129 angle = dot(curr_vector, 0, n-1, last_vec); 00130 } while (fabs(angle)<tol); 00131 /* the Rayleigh quotient (up to errors due to orthogonalization): 00132 * u*(A*u)/||A*u||)*||A*u||, where u=last_vec, and ||u||=1 00133 */ 00134 evals[i]=angle*len; 00135 } 00136 exit: 00137 for (; i<neigs; i++) { 00138 /* compute the smallest eigenvector, which are 00139 * probably associated with eigenvalue 0 and for 00140 * which power-iteration is dangerous 00141 */ 00142 curr_vector = eigs[i]; 00143 /* guess the i-th eigen vector */ 00144 for (j=0; j<n; j++) 00145 curr_vector[j] = rand()%100; 00146 /* orthogonalize against higher eigenvectors */ 00147 for (j=0; j<i; j++) { 00148 alpha = -dot(eigs[j], 0, n-1, curr_vector); 00149 scadd(curr_vector, 0, n-1, alpha, eigs[j]); 00150 } 00151 len = norm(curr_vector, 0, n-1); 00152 vecscale(curr_vector, 0, n-1, 1.0 / len, curr_vector); 00153 evals[i]=0; 00154 00155 } 00156 00157 /* sort vectors by their evals, for overcoming possible mis-convergence: */ 00158 for (i=0; i<neigs-1; i++) { 00159 largest_index=i; 00160 largest_eval=evals[largest_index]; 00161 for (j=i+1; j<neigs; j++) { 00162 if (largest_eval<evals[j]) { 00163 largest_index=j; 00164 largest_eval=evals[largest_index]; 00165 } 00166 } 00167 if (largest_index!=i) { // exchange eigenvectors: 00168 cpvec(tmp_vec,0,n-1,eigs[i]); 00169 cpvec(eigs[i],0,n-1,eigs[largest_index]); 00170 cpvec(eigs[largest_index],0,n-1,tmp_vec); 00171 00172 evals[largest_index]=evals[i]; 00173 evals[i]=largest_eval; 00174 } 00175 } 00176 00177 free (tmp_vec); free (last_vec); 00178 00179 } 00180 00181 static float* 00182 compute_avgs(DistType** Dij, int n, float* all_avg) 00183 { 00184 float* row_avg = N_GNEW(n, float); 00185 int i,j; 00186 double sum=0, sum_row; 00187 00188 for (i=0; i<n; i++) { 00189 sum_row=0; 00190 for (j=0; j<n; j++) { 00191 sum+=(double)Dij[i][j]*(double)Dij[i][j]; 00192 sum_row+=(double)Dij[i][j]*(double)Dij[i][j]; 00193 } 00194 row_avg[i]=(float)sum_row/n; 00195 } 00196 *all_avg=(float)sum/(n*n); 00197 return row_avg; 00198 } 00199 00200 static float** 00201 compute_Bij(DistType** Dij, int n) 00202 { 00203 int i,j; 00204 float* storage = N_GNEW(n*n,float); 00205 float** Bij = N_GNEW(n, float*); 00206 float* row_avg; 00207 float all_avg; 00208 00209 for (i=0; i<n; i++) 00210 Bij[i] = storage+i*n; 00211 00212 row_avg = compute_avgs(Dij, n, &all_avg); 00213 for (i=0; i<n; i++) { 00214 for (j=0; j<=i; j++) { 00215 Bij[i][j]=-(float)Dij[i][j]*Dij[i][j]+row_avg[i]+row_avg[j]-all_avg; 00216 Bij[j][i]=Bij[i][j]; 00217 } 00218 } 00219 free (row_avg); 00220 return Bij; 00221 } 00222 00223 static void 00224 CMDS_orthog(vtx_data* graph, int n, int dim, double** eigs, double tol, 00225 double* orthog, DistType** Dij) 00226 { 00227 int i,j; 00228 float** Bij = compute_Bij(Dij, n); 00229 double* evals= N_GNEW(dim, double); 00230 00231 double * orthog_aux = NULL; 00232 if (orthog!=NULL) { 00233 orthog_aux = N_GNEW(n, double); 00234 for (i=0; i<n; i++) { 00235 orthog_aux[i]=orthog[i]; 00236 } 00237 standardize(orthog_aux,n); 00238 } 00239 power_iteration_orthog(Bij, n, dim, eigs, evals, orthog_aux, tol); 00240 00241 for (i=0; i<dim; i++) { 00242 for (j=0; j<n; j++) { 00243 eigs[i][j]*=sqrt(fabs(evals[i])); 00244 } 00245 } 00246 free (Bij[0]); free (Bij); 00247 free (evals); free (orthog_aux); 00248 } 00249 00250 #define SCALE_FACTOR 256 00251 00252 int IMDS_given_dim(vtx_data* graph, int n, double* given_coords, 00253 double* new_coords, double conj_tol) 00254 { 00255 int iterations2; 00256 int i,j, rv = 0; 00257 DistType** Dij; 00258 float* f_storage = NULL; 00259 double* x = given_coords; 00260 double uniLength; 00261 double* orthog_aux = NULL; 00262 double* y = new_coords; 00263 float** lap = N_GNEW(n, float*); 00264 float degree; 00265 double pos_i; 00266 double* balance = N_GNEW(n, double); 00267 double b; 00268 boolean converged; 00269 00270 #if 0 00271 iterations1=mat_mult_count1=0; /* We don't compute the x-axis at all. */ 00272 #endif 00273 00274 Dij = compute_apsp(graph, n); 00275 00276 /* scaling up the distances to enable an 'sqrt' operation later 00277 * (in case distances are integers) 00278 */ 00279 for (i=0; i<n; i++) 00280 for (j=0; j<n; j++) 00281 Dij[i][j]*=SCALE_FACTOR; 00282 00283 assert(x!=NULL); 00284 { 00285 double sum1, sum2; 00286 /* scale x (given axis) to minimize the stress */ 00287 orthog_aux = N_GNEW(n, double); 00288 for (i=0; i<n; i++) { 00289 orthog_aux[i]=x[i]; 00290 } 00291 standardize(orthog_aux,n); 00292 00293 for (sum1=sum2=0,i=1; i<n; i++) { 00294 for (j=0; j<i; j++) { 00295 sum1+=1.0/(Dij[i][j])*fabs(x[i]-x[j]); 00296 sum2+=1.0/(Dij[i][j]*Dij[i][j])*fabs(x[i]-x[j])*fabs(x[i]-x[j]); 00297 } 00298 } 00299 uniLength=sum1/sum2; 00300 for (i=0; i<n; i++) 00301 x[i]*=uniLength; 00302 } 00303 00304 /* smart ini: */ 00305 CMDS_orthog(graph, n, 1, &y, conj_tol, x, Dij); 00306 00307 /* Compute Laplacian: */ 00308 f_storage = N_GNEW(n*n, float); 00309 00310 for (i=0; i<n; i++) { 00311 lap[i]=f_storage+i*n; 00312 degree=0; 00313 for (j=0; j<n; j++) { 00314 if (j==i) 00315 continue; 00316 degree-=lap[i][j]=-1.0f/((float)Dij[i][j]*(float)Dij[i][j]); // w_{ij} 00317 00318 } 00319 lap[i][i]=degree; 00320 } 00321 00322 00323 /* compute residual distances */ 00324 /* if (x!=NULL) */ 00325 { 00326 double diff; 00327 for (i=1; i<n; i++) { 00328 pos_i=x[i]; 00329 for (j=0; j<i; j++) { 00330 diff=(double)Dij[i][j]*(double)Dij[i][j]-(pos_i-x[j])*(pos_i-x[j]); 00331 Dij[i][j]=Dij[j][i]=diff>0 ? (DistType)sqrt(diff) : 0; 00332 } 00333 } 00334 } 00335 00336 /* Compute the balance vector: */ 00337 for (i=0; i<n; i++) { 00338 pos_i=y[i]; 00339 balance[i]=0; 00340 for (j=0; j<n; j++) { 00341 if (j==i) 00342 continue; 00343 if (pos_i>=y[j]) { 00344 balance[i]+=Dij[i][j]*(-lap[i][j]); // w_{ij}*delta_{ij} 00345 } 00346 else { 00347 balance[i]-=Dij[i][j]*(-lap[i][j]); // w_{ij}*delta_{ij} 00348 } 00349 } 00350 } 00351 00352 for (converged=FALSE,iterations2=0; iterations2<200 && !converged; iterations2++) { 00353 if (conjugate_gradient_f(lap, y, balance, n, conj_tol, n, TRUE) < 0) { 00354 rv = 1; 00355 goto cleanup; 00356 } 00357 converged=TRUE; 00358 for (i=0; i<n; i++) { 00359 pos_i=y[i]; 00360 b=0; 00361 for (j=0; j<n; j++) { 00362 if (j==i) 00363 continue; 00364 if (pos_i>=y[j]) { 00365 b+=Dij[i][j]*(-lap[i][j]); 00366 00367 } 00368 else { 00369 b-=Dij[i][j]*(-lap[i][j]); 00370 00371 } 00372 } 00373 if ((b != balance[i]) && (fabs(1-b/balance[i])>1e-5)) { 00374 converged=FALSE; 00375 balance[i]=b; 00376 } 00377 } 00378 } 00379 00380 for (i=0; i<n; i++) { 00381 x[i] /= uniLength; 00382 y[i] /= uniLength; 00383 } 00384 00385 cleanup: 00386 00387 free (Dij[0]); free (Dij); 00388 free (lap[0]); free (lap); 00389 free (orthog_aux); free (balance); 00390 return rv; 00391 } 00392 00393 #endif /* DIGCOLA */ 00394
1.7.5