00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "digcola.h"
00018 #ifdef DIGCOLA
00019 #include <math.h>
00020 #include <stdlib.h>
00021 #include <time.h>
00022 #include <stdio.h>
00023 #include <float.h>
00024 #include "stress.h"
00025 #include "dijkstra.h"
00026 #include "bfs.h"
00027 #include "matrix_ops.h"
00028 #include "kkutils.h"
00029 #include "conjgrad.h"
00030 #include "quad_prog_solver.h"
00031 #include "matrix_ops.h"
00032
00033 #define localConstrMajorIterations 15
00034 #define levels_sep_tol 1e-1
00035
00036 int
00037 stress_majorization_with_hierarchy(
00038 vtx_data* graph,
00039 int n,
00040 int nedges_graph,
00041 double** d_coords,
00042 int dim,
00043 int smart_ini,
00044 int model,
00045 int maxi,
00046 double levels_gap
00047 )
00048 {
00049 int iterations = 0;
00050
00051
00052
00053
00054
00055
00056
00057 int i,j,k;
00058 boolean directionalityExist = FALSE;
00059 float * lap1 = NULL;
00060 float * dist_accumulator = NULL;
00061 float * tmp_coords = NULL;
00062 float ** b = NULL;
00063 #ifdef NONCORE
00064 FILE * fp=NULL;
00065 #endif
00066 double * degrees = NULL;
00067 float * lap2=NULL;
00068 int lap_length;
00069 float * f_storage=NULL;
00070 float ** coords=NULL;
00071
00072 double conj_tol=tolerance_cg;
00073 float ** unpackedLap = NULL;
00074 CMajEnv *cMajEnv = NULL;
00075 double y_0;
00076 int length;
00077 DistType diameter;
00078 float * Dij=NULL;
00079
00080 double abs_tol=1e-2;
00081
00082 double relative_tol=levels_sep_tol;
00083 int *ordering=NULL, *levels=NULL;
00084 float constant_term;
00085 int count;
00086 double degree;
00087 int step;
00088 float val;
00089 double old_stress, new_stress;
00090 boolean converged;
00091 int len;
00092 int num_levels;
00093 float *hierarchy_boundaries;
00094
00095 if (graph[0].edists!=NULL) {
00096 for (i=0; i<n; i++) {
00097 for (j=1; j<graph[i].nedges; j++) {
00098 directionalityExist = directionalityExist || (graph[i].edists[j]!=0);
00099 }
00100 }
00101 }
00102 if (!directionalityExist) {
00103 return stress_majorization_kD_mkernel(graph, n, nedges_graph, d_coords, dim, smart_ini, model, maxi);
00104 }
00105
00106
00107
00108
00109
00110 if (smart_ini) {
00111 double* x;
00112 double* y;
00113 if (dim>2) {
00114
00115 stress_majorization_kD_mkernel(graph, n, nedges_graph, d_coords+1, dim-1, smart_ini, model, 15);
00116
00117 for (i=0; i<n; i++) {
00118 d_coords[dim-1][i] = d_coords[1][i];
00119 }
00120 }
00121
00122 x = d_coords[0]; y = d_coords[1];
00123 compute_y_coords(graph, n, y, n);
00124 compute_hierarchy(graph, n, abs_tol, relative_tol, y, &ordering, &levels, &num_levels);
00125 if (num_levels<=1) {
00126
00127 return stress_majorization_kD_mkernel(graph, n, nedges_graph, d_coords, dim, smart_ini, model, maxi);
00128 }
00129
00130 if (levels_gap>0) {
00131
00132 double displacement = 0;
00133 int stop;
00134 for (i=0; i<num_levels; i++) {
00135 displacement+=MAX((double)0,levels_gap-(y[ordering[levels[i]]]+displacement-y[ordering[levels[i]-1]]));
00136 stop = i<num_levels-1 ? levels[i+1] : n;
00137 for (j=levels[i]; j<stop; j++) {
00138 y[ordering[j]] += displacement;
00139 }
00140 }
00141 }
00142 if (dim==2) {
00143 IMDS_given_dim(graph, n, y, x, Epsilon);
00144 }
00145 }
00146 else {
00147 initLayout(graph, n, dim, d_coords);
00148 compute_hierarchy(graph, n, abs_tol, relative_tol, NULL, &ordering, &levels, &num_levels);
00149 }
00150 if (n == 1) return 0;
00151
00152 hierarchy_boundaries = N_GNEW(num_levels, float);
00153
00154
00155
00156
00157
00158 if (maxi==0)
00159 return iterations;
00160
00161 if (model == MODEL_SUBSET) {
00162
00163
00164 if (Verbose)
00165 fprintf(stderr, "Calculating subset model");
00166 Dij = compute_apsp_artifical_weights_packed(graph, n);
00167 } else if (model == MODEL_CIRCUIT) {
00168 Dij = circuitModel(graph, n);
00169 if (!Dij) {
00170 agerr(AGWARN,
00171 "graph is disconnected. Hence, the circuit model\n");
00172 agerr(AGPREV,
00173 "is undefined. Reverting to the shortest path model.\n");
00174 }
00175 }
00176 if (!Dij) {
00177 if (Verbose)
00178 fprintf(stderr, "Calculating shortest paths");
00179 Dij = compute_apsp_packed(graph, n);
00180 }
00181
00182 diameter=-1;
00183 length = n+n*(n-1)/2;
00184 for (i=0; i<length; i++) {
00185 if (Dij[i]>diameter) {
00186 diameter = (int)Dij[i];
00187 }
00188 }
00189
00190 if (!smart_ini) {
00191
00192
00193 double max=1;
00194 for (i=0; i<dim; i++) {
00195 for (j=0; j<n; j++) {
00196 if (fabs(d_coords[i][j])>max) {
00197 max=fabs(d_coords[i][j]);
00198 }
00199 }
00200 }
00201 for (i=0; i<dim; i++) {
00202 for (j=0; j<n; j++) {
00203 d_coords[i][j]*=10/max;
00204 }
00205 }
00206 }
00207
00208 if (levels_gap>0) {
00209 int length = n+n*(n-1)/2;
00210 double sum1, sum2, scale_ratio;
00211 int count;
00212 sum1=(float)(n*(n-1)/2);
00213 sum2=0;
00214 for (count=0, i=0; i<n-1; i++) {
00215 count++;
00216 for (j=i+1; j<n; j++,count++) {
00217 sum2+=distance_kD(d_coords, dim, i, j)/Dij[count];
00218 }
00219 }
00220 scale_ratio=sum2/sum1;
00221
00222 for (i=0; i<length; i++) {
00223 Dij[i]*=(float)scale_ratio;
00224 }
00225 }
00226
00227
00228
00229
00230
00231 for (i=0; i<dim; i++) {
00232 orthog1(n, d_coords[i]);
00233 }
00234
00235
00236 y_0 = d_coords[1][0];
00237 for (i=0; i<n; i++) {
00238 d_coords[1][i] -= y_0;
00239 }
00240
00241 coords = N_GNEW(dim, float*);
00242 f_storage = N_GNEW(dim*n, float);
00243 for (i=0; i<dim; i++) {
00244 coords[i] = f_storage+i*n;
00245 for (j=0; j<n; j++) {
00246 coords[i][j] = (float)(d_coords[i][j]);
00247 }
00248 }
00249
00250
00251
00252
00253 constant_term=(float)(n*(n-1)/2);
00254
00255
00256
00257
00258
00259 lap2 = Dij;
00260 lap_length = n+n*(n-1)/2;
00261 square_vec(lap_length, lap2);
00262
00263 invert_vec(lap_length, lap2);
00264
00265
00266 count=0;
00267 degrees = N_GNEW(n, double);
00268 set_vector_val(n, 0, degrees);
00269 for (i=0; i<n-1; i++) {
00270 degree=0;
00271 count++;
00272 for (j=1; j<n-i; j++,count++) {
00273 val = lap2[count];
00274 degree+=val; degrees[i+j]-=val;
00275 }
00276 degrees[i]-=degree;
00277 }
00278 for (step=n,count=0,i=0; i<n; i++,count+=step,step--) {
00279 lap2[count]=(float)degrees[i];
00280 }
00281
00282 #ifdef NONCORE
00283 fpos_t pos;
00284 if (n>max_nodes_in_mem) {
00285 #define FILENAME "tmp_Dij$$$.bin"
00286 fp = fopen(FILENAME, "wb");
00287 fwrite(lap2, sizeof(float), lap_length, fp);
00288 fclose(fp);
00289 }
00290 #endif
00291
00292
00293
00294
00295
00296 b = N_GNEW (dim, float*);
00297 b[0] = N_GNEW (dim*n, float);
00298 for (k=1; k<dim; k++) {
00299 b[k] = b[0]+k*n;
00300 }
00301
00302 tmp_coords = N_GNEW(n, float);
00303 dist_accumulator = N_GNEW(n, float);
00304 #ifdef NONCORE
00305 if (n<=max_nodes_in_mem) {
00306 #endif
00307 lap1 = N_GNEW(lap_length, float);
00308 #ifdef NONCORE
00309 }
00310 else {
00311 lap1=lap2;
00312 fp = fopen(FILENAME, "rb");
00313 fgetpos(fp, &pos);
00314 }
00315 #endif
00316
00317 old_stress=DBL_MAX;
00318
00319 unpackedLap = unpackMatrix(lap2, n);
00320 cMajEnv=initConstrainedMajorization(lap2, n, ordering, levels, num_levels);
00321
00322 for (converged=FALSE,iterations=0; iterations<maxi && !converged; iterations++) {
00323
00324
00325 set_vector_val(n, 0, degrees);
00326 #ifdef NONCORE
00327 if (n<=max_nodes_in_mem) {
00328 #endif
00329 sqrt_vecf(lap_length, lap2, lap1);
00330 #ifdef NONCORE
00331 }
00332 else {
00333 sqrt_vec(lap_length, lap1);
00334 }
00335 #endif
00336 for (count=0,i=0; i<n-1; i++) {
00337 len = n-i-1;
00338
00339 set_vector_valf(n, 0, dist_accumulator);
00340
00341
00342
00343
00344 for (k=0; k<dim; k++) {
00345 set_vector_valf(len, coords[k][i], tmp_coords);
00346 vectors_mult_additionf(len, tmp_coords, -1, coords[k]+i+1);
00347 square_vec(len, tmp_coords);
00348 vectors_additionf(len, tmp_coords, dist_accumulator, dist_accumulator);
00349 }
00350
00351
00352 invert_sqrt_vec(len, dist_accumulator);
00353
00354 for (j=0; j<len; j++) {
00355 if (dist_accumulator[j]>=FLT_MAX || dist_accumulator[j]<0) {
00356 dist_accumulator[j]=0;
00357 }
00358 }
00359
00360 count++;
00361 degree=0;
00362 for (j=0; j<len; j++,count++) {
00363 val=lap1[count]*=dist_accumulator[j];
00364 degree+=val; degrees[i+j+1]-=val;
00365 }
00366 degrees[i]-=degree;
00367 }
00368 for (step=n,count=0,i=0; i<n; i++,count+=step,step--) {
00369 lap1[count]=(float)degrees[i];
00370 }
00371
00372
00373 for (k=0; k<dim; k++) {
00374
00375 right_mult_with_vector_ff(lap1, n, coords[k], b[k]);
00376 }
00377
00378
00379
00380
00381
00382 new_stress=0;
00383 for (k=0; k<dim; k++) {
00384 new_stress+=vectors_inner_productf(n, coords[k], b[k]);
00385 }
00386 new_stress*=2;
00387 new_stress+=constant_term;
00388 #ifdef NONCORE
00389 if (n>max_nodes_in_mem) {
00390
00391 fsetpos(fp, &pos);
00392 fread(lap2, sizeof(float), lap_length, fp);
00393 }
00394 #endif
00395 for (k=0; k<dim; k++) {
00396 right_mult_with_vector_ff(lap2, n, coords[k], tmp_coords);
00397 new_stress-=vectors_inner_productf(n, coords[k], tmp_coords);
00398 }
00399
00400 #ifdef ALTERNATIVE_STRESS_CALC
00401 {
00402 double mat_stress=new_stress;
00403 double compute_stress(float ** coords, float * lap, int dim, int n);
00404 new_stress = compute_stress(coords, lap2, dim, n);
00405 if (fabs(mat_stress-new_stress)/min(mat_stress,new_stress)>0.001) {
00406 fprintf(stderr,"Diff stress vals: %lf %lf (iteration #%d)\n", mat_stress, new_stress,iterations);
00407 }
00408 }
00409 #endif
00410
00411 converged = fabs(new_stress-old_stress)/fabs(old_stress+1e-10) < Epsilon;
00412 converged = converged || (iterations>1 && new_stress>old_stress);
00413
00414
00415
00416 old_stress = new_stress;
00417
00418 for (k=0; k<dim; k++) {
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431 if (k==1) {
00432
00433 constrained_majorization_new_with_gaps(cMajEnv, b[k], coords, dim, k, localConstrMajorIterations, hierarchy_boundaries, levels_gap);
00434
00435 }
00436 else {
00437
00438 conjugate_gradient_mkernel(lap2, coords[k], b[k], n, conj_tol, n);
00439 }
00440 }
00441 }
00442 free (hierarchy_boundaries);
00443 deleteCMajEnv(cMajEnv);
00444
00445 if (coords!=NULL) {
00446 for (i=0; i<dim; i++) {
00447 for (j=0; j<n; j++) {
00448 d_coords[i][j] = coords[i][j];
00449 }
00450 }
00451 free (coords[0]); free (coords);
00452 }
00453
00454 if (b) {
00455 free (b[0]); free (b);
00456 }
00457 free (tmp_coords);
00458 free (dist_accumulator);
00459 free (degrees);
00460 free (lap2);
00461
00462
00463 #ifdef NONCORE
00464 if (n<=max_nodes_in_mem) {
00465 #endif
00466 free (lap1);
00467 #ifdef NONCORE
00468 }
00469 #endif
00470
00471 free (ordering);
00472
00473 free (levels);
00474
00475 if (unpackedLap) {
00476 free (unpackedLap[0]); free (unpackedLap);
00477 }
00478 return iterations;
00479 }
00480 #endif
00481