77 static char* smoothings[] = {
78 "NONE",
"STRESS_MAJORIZATION_GRAPH_DIST",
"STRESS_MAJORIZATION_AVG_DIST",
"STRESS_MAJORIZATION_POWER_DIST",
"SPRING",
"TRIANGLE",
"RNG"
81 static char* tschemes[] = {
82 "NONE",
"NORMAL",
"FAST",
"HYBRID"
85 static char* methods[] = {
86 "SPRING_ELECTRICAL",
"SPRING_MAXENT",
"STRESS_MAXENT",
"STRESS_APPROX",
"STRESS",
"UNIFORM_STRESS",
"FULL_STRESS",
"NONE"
90 fprintf (stderr,
"spring_electrical_control:\n");
91 fprintf (stderr,
" repulsive and attractive exponents: %.03f %.03f\n", ctrl->
p, ctrl->
q);
93 fprintf (stderr,
" K : %.03f C : %.03f\n", ctrl->
K, ctrl->
C);
94 fprintf (stderr,
" max levels %d coarsen_scheme %d coarsen_node %d\n", ctrl->
multilevels,
97 fprintf (stderr,
" Barnes-Hutt constant %.03f tolerance %.03f maxiter %d\n", ctrl->
bh, ctrl->
tol, ctrl->
maxiter);
99 fprintf (stderr,
" beautify_leaves %d node weights %d rotation %.03f\n",
101 fprintf (stderr,
" smoothing %s overlap %d initial_scaling %.03f do_shrinking %d\n",
103 fprintf (stderr,
" octree scheme %s method %s\n", tschemes[ctrl->
tscheme], methods[ctrl->
method]);
146 if (opt->
work[i] < opt->
work[i+1] && opt->
i > 0){
148 opt->
i =
MAX(0, opt->
i-1);
164 int *ia = A->
ia, *ja = A->
ja, i, j, k;
167 if (ia[A->
m] == 0)
return 1;
168 for (i = 0; i < A->
m; i++){
169 for (j = ia[i]; j < ia[i+1]; j++){
171 for (k = 0; k < dim; k++){
172 d += (coord[dim*i+k] - coord[dim*ja[j]])*(coord[dim*i+k] - coord[dim*ja[j]]);
177 return dist/ia[A->
m];
189 int i, j, k, *ia = A->
ia, *ja = A->
ja, n = A->
m;
192 for (i = 0; i < n; i++){
194 for (j = ia[i]; j < ia[i+1]; j++){
195 if (ja[j] == i)
continue;
197 energy += CRK*pow(
dist, 3.)*2./3.;
201 for (j = 0; j < n; j++){
202 if (j == i)
continue;
204 for (k = 0; k < dim; k++){
206 energy += -KP*2*log(
dist);
208 energy += -KP*pow(
dist,p+1)*2/(p+1);
219 int i, j, k, *ia=A->
ia, *ja = A->
ja;
225 for (i = 0; i < A->
m; i++){
226 xmax =
MAX(xmax, x[i*dim]);
227 xmin =
MIN(xmin, x[i*dim]);
228 ymax =
MAX(ymax, x[i*dim+1]);
229 ymin =
MIN(ymin, x[i*dim+1]);
233 xsize =
MAX(xsize, ysize);
236 fprintf(fp,
"Graphics[{GrayLevel[0.5],Line[{");
238 fprintf(fp,
"Graphics3D[{GrayLevel[0.5],Line[{");
240 for (i = 0; i < A->
m; i++){
241 for (j = ia[i]; j < ia[i+1]; j++){
242 if (ja[j] == i)
continue;
244 if (ne > 1) fprintf(fp,
",");
246 for (k = 0; k < dim; k++) {
247 if (k > 0) fprintf(fp,
",");
248 fprintf(fp,
"%f",x[i*dim+k]);
251 for (k = 0; k < dim; k++) {
252 if (k > 0) fprintf(fp,
",");
253 fprintf(fp,
"%f",x[ja[j]*dim+k]);
259 fprintf(fp,
"}],Hue[%f]",1.);
261 if (width && dim == 2){
262 for (i = 0; i < A->
m; i++){
263 if (i >= 0) fprintf(fp,
",");
264 fprintf(fp,
"(*width={%f,%f}, x = {%f,%f}*){GrayLevel[.5,.5],Rectangle[{%f,%f},{%f,%f}]}", width[i*dim], width[i*dim+1], x[i*dim], x[i*dim + 1],
265 x[i*dim] - width[i*dim], x[i*dim+1] - width[i*dim+1],
266 x[i*dim] + width[i*dim], x[i*dim+1] + width[i*dim+1]);
271 for (i = 0; i < A->
m; i++){
272 if (i >= 0) fprintf(fp,
",");
273 fprintf(fp,
"Text[%d,{",i+1);
274 for (k = 0; k < dim; k++) {
275 if (k > 0) fprintf(fp,
",");
276 fprintf(fp,
"%f",x[i*dim+k]);
280 }
else if (A->
m < 500000){
281 fprintf(fp,
", Point[{");
282 for (i = 0; i < A->
m; i++){
283 if (i > 0) fprintf(fp,
",");
285 for (k = 0; k < dim; k++) {
286 if (k > 0) fprintf(fp,
",");
287 fprintf(fp,
"%f",x[i*dim+k]);
297 fprintf(fp,
"},ImageSize->%f]\n", 2*xsize/2);
303 if (!adaptive_cooling) {
306 if (Fnorm >= Fnorm0){
308 }
else if (Fnorm > 0.95*Fnorm0){
311 step = 0.99*step/cool;
317 #define node_degree(i) (ia[(i)+1] - ia[(i)])
321 *lenmax = len +
MAX((
int) 0.2*len, 10);
328 *lenmax = len +
MAX((
int) 0.2*len, 10);
329 *a =
REALLOC(*a,
sizeof(
int)*(*lenmax));
339 for (k = 0; k < 2; k++){
340 y[k] = x[j*dim+k] - x[i*dim+k];
342 if (
ABS(y[0]) <=
ABS(y[1])*eps){
343 if (y[1] > 0)
return 0.5*
PI;
346 res = atan(y[1]/y[0]);
348 if (y[1] < 0) res = 2*
PI+res;
349 }
else if (y[0] < 0){
361 }
else if (*xx < *yy){
366 static void sort_real(
int n,
real *a){
371 static void set_leaves(
real *x,
int dim,
real dist,
real ang,
int i,
int j){
372 x[dim*j] = cos(ang)*dist + x[dim*i];
373 x[dim*j+1] = sin(ang)*dist + x[dim*i+1];
377 int m = A->
m, i, j, *ia = A->
ia, *ja = A->
ja, k;
380 int nleaves, nleaves_max = 10;
381 real *angles, maxang, ang1 = 0, ang2 = 0, pad, step;
382 int *leaves, nangles_max = 10, nangles;
386 checked =
MALLOC(
sizeof(
int)*m);
388 leaves =
MALLOC(
sizeof(
int)*nleaves_max);
391 for (i = 0; i < m; i++) checked[i] =
FALSE;
393 for (i = 0; i < m; i++){
394 if (ia[i+1] - ia[i] != 1)
continue;
395 if (checked[i])
continue;
399 dist = 0; nleaves = 0; nangles = 0;
400 for (j = ia[p]; j < ia[p+1]; j++){
402 checked[ja[j]] =
TRUE;
405 leaves[nleaves] = ja[j];
409 angles[nangles++] =
get_angle(x, dim, p, ja[j]);
415 sort_real(nangles, angles);
417 for (k = 0; k < nangles - 1; k++){
418 if (angles[k+1] - angles[k] > maxang){
419 maxang = angles[k+1] - angles[k];
420 ang1 = angles[k]; ang2 = angles[k+1];
423 if (2*
PI + angles[0] - angles[nangles - 1] > maxang){
424 maxang = 2*
PI + angles[0] - angles[nangles - 1];
425 ang1 = angles[nangles - 1];
426 ang2 = 2*
PI + angles[0];
429 ang1 = 0; ang2 = 2*
PI; maxang = 2*
PI;
431 pad =
MAX(maxang -
PI*0.166667*(nleaves-1), 0)*0.5;
434 ang1 = 0; ang2 = 2*
PI; maxang = 2*
PI;
437 if (nleaves > 1) step = (ang2 - ang1)/(nleaves - 1);
438 for (i = 0; i < nleaves; i++) {
439 set_leaves(x, dim, dist, ang1, p, leaves[i]);
454 fprintf(fp,
"Graphics[{");
455 for (i = 0; i < n; i++){
456 if (i > 0) fprintf(fp,
",");
457 fprintf(fp,
"Arrow[{{");
458 for (k = 0; k < dim; k++){
459 if (k > 0) fprintf(fp,
",");
460 fprintf(fp,
"%f",x[i*dim+k]);
463 for (k = 0; k < dim; k++){
464 if (k > 0) fprintf(fp,
",");
465 fprintf(fp,
"%f",x[i*dim+k]+0.5*force[i*dim+k]);
470 for (i = 0; i < n; i++){
471 if (i > 0) fprintf(fp,
",");
472 fprintf(fp,
"Tooltip[Point[{");
473 for (k = 0; k < dim; k++){
474 if (k > 0) fprintf(fp,
",");
475 fprintf(fp,
"%f",x[i*dim+k]);
477 fprintf(fp,
"}],%d]",i);
493 real p = ctrl->
p, K = ctrl->
K,
C = ctrl->
C, CRK, tol = ctrl->
tol, maxiter = ctrl->
maxiter, cool = ctrl->
cool, step = ctrl->
step, KP;
502 clock_t start, end, start0;
503 real qtree_cpu = 0, qtree_cpu0 = 0, qtree_new_cpu = 0, qtree_new_cpu0 = 0;
510 if (!A || maxiter <= 0)
return;
513 if (n <= 0 || dim <= 0)
return;
529 for (i = 0; i < dim*n; i++) x[i] =
drand();
534 if (
C < 0) ctrl->
C =
C = 0.2;
535 if (p >= 0) ctrl->
p = p = -1;
537 CRK = pow(
C, (2.-p)/3.)/K;
550 lab =
MALLOC(
sizeof(
char)*100);
551 sprintf(lab,
"sfdp, iter=%d", iter);
552 gviewer_set_label(lab);
553 gviewer_reset_graph_coord(A, dim, x);
555 gviewer_dump_current_frame();
578 qtree_new_cpu += ((
real) (clock() - start))/CLOCKS_PER_SEC;
592 qtree_cpu += ((
real) (end - start)) / CLOCKS_PER_SEC;
596 for (i = 0; i < n; i++){
598 for (j = ia[i]; j < ia[i+1]; j++){
599 if (ja[j] == i)
continue;
601 for (k = 0; k < dim; k++){
602 f[k] -= CRK*(x[i*dim+k] - x[ja[j]*dim+k])*dist;
609 for (i = 0; i < n; i++){
612 for (k = 0; k < dim; k++) F += f[k]*f[k];
615 if (F > 0)
for (k = 0; k < dim; k++) f[k] /= F;
616 for (k = 0; k < dim; k++) x[i*dim+k] += step*f[k];
628 qtree_new_cpu += ((
real) (end - start)) / CLOCKS_PER_SEC;
632 qtree_cpu0 = qtree_cpu - qtree_cpu0;
633 qtree_new_cpu0 = qtree_new_cpu - qtree_new_cpu0;
640 qtree_cpu0 = qtree_cpu;
641 qtree_new_cpu0 = qtree_new_cpu;
646 fprintf(stderr,
"\r iter = %d, step = %f Fnorm = %f nz = %d K = %f ",iter, step, Fnorm, A->
nz,K);
648 fprintf(stderr,
"energy = %f\n",spring_electrical_energy(dim, A, x, p, CRK, KP));
653 step = update_step(adaptive_cooling, step, Fnorm, Fnorm0, cool);
654 }
while (step > tol && iter < maxiter);
657 if (
Verbose && 0) fputs(
"\n", stderr);
663 fprintf(stderr,
"\n iter = %d, step = %f Fnorm = %f nz = %d K = %f ",iter, step, Fnorm, A->
nz, K);
670 total_cpu += ((
real) (clock() - start0)) / CLOCKS_PER_SEC;
671 if (
Verbose) fprintf(stderr,
"\n time for qtree = %f, qtree_force = %f, total cpu = %f\n",qtree_new_cpu, qtree_cpu, total_cpu);
679 if (xold)
FREE(xold);
681 if (force)
FREE(force);
692 real p = ctrl->
p, K = ctrl->
K,
C = ctrl->
C, CRK, tol = ctrl->
tol, maxiter = ctrl->
maxiter, cool = ctrl->
cool, step = ctrl->
step, KP;
700 int nsuper = 0, nsupermax = 10;
701 real *center =
NULL, *supernode_wgts =
NULL, *distances =
NULL, nsuper_avg, counts = 0, counts_avg = 0;
704 clock_t start, end, start0, start2;
705 real qtree_cpu = 0, qtree_cpu0 = 0;
712 fprintf(stderr,
"spring_electrical_embedding_slow");
713 if (!A || maxiter <= 0)
return;
716 if (n <= 0 || dim <= 0)
return;
723 supernode_wgts =
MALLOC(
sizeof(
real)*nsupermax);
739 for (i = 0; i < dim*n; i++) x[i] =
drand();
744 if (
C < 0) ctrl->
C =
C = 0.2;
745 if (p >= 0) ctrl->
p = p = -1;
747 CRK = pow(
C, (2.-p)/3.)/K;
753 strcpy(fname,
"/tmp/graph_layout_0_");
754 sprintf(&(fname[strlen(fname)]),
"%d",n);
755 f = fopen(fname,
"w");
764 for (i = 0; i < dim*n; i++) force[i] = 0;
785 for (i = 0; i < n; i++){
786 for (k = 0; k < dim; k++) f[k] = 0.;
793 ¢er, &supernode_wgts, &distances, &counts, flag);
796 qtree_cpu += ((
real) (end - start)) / CLOCKS_PER_SEC;
798 counts_avg += counts;
799 nsuper_avg += nsuper;
800 if (*flag)
goto RETURN;
801 for (j = 0; j < nsuper; j++){
803 for (k = 0; k < dim; k++){
805 f[k] += supernode_wgts[j]*KP*(x[i*dim+k] - center[j*dim+k])/(dist*dist);
807 f[k] += supernode_wgts[j]*KP*(x[i*dim+k] - center[j*dim+k])/pow(dist, 1.- p);
813 for (j = 0; j < n; j++){
814 if (j == i)
continue;
816 for (k = 0; k < dim; k++){
818 f[k] += node_weights[j]*KP*(x[i*dim+k] - x[j*dim+k])/(dist*dist);
820 f[k] += node_weights[j]*KP*(x[i*dim+k] - x[j*dim+k])/pow(dist, 1.- p);
825 for (j = 0; j < n; j++){
826 if (j == i)
continue;
828 for (k = 0; k < dim; k++){
830 f[k] += KP*(x[i*dim+k] - x[j*dim+k])/(dist*dist);
832 f[k] += KP*(x[i*dim+k] - x[j*dim+k])/pow(dist, 1.- p);
838 for (k = 0; k < dim; k++) force[i*dim+k] += f[k];
843 for (i = 0; i < n; i++){
844 for (k = 0; k < dim; k++) f[k] = 0.;
846 for (j = ia[i]; j < ia[i+1]; j++){
847 if (ja[j] == i)
continue;
849 for (k = 0; k < dim; k++){
850 f[k] -= CRK*(x[i*dim+k] - x[ja[j]*dim+k])*dist;
853 for (k = 0; k < dim; k++) force[i*dim+k] += f[k];
858 for (i = 0; i < n; i++){
860 for (k = 0; k < dim; k++) f[k] = force[i*dim+k];
863 for (k = 0; k < dim; k++) F += f[k]*f[k];
867 if (F > 0)
for (k = 0; k < dim; k++) f[k] /= F;
869 for (k = 0; k < dim; k++) x[i*dim+k] += step*f[k];
878 qtree_cpu0 = qtree_cpu - qtree_cpu0;
879 if (
Verbose && 0) fprintf(stderr,
"\n cpu this outer iter = %f, quadtree time = %f other time = %f\n",((
real) (clock() - start2)) / CLOCKS_PER_SEC, qtree_cpu0,((
real) (clock() - start2))/CLOCKS_PER_SEC - qtree_cpu0);
880 qtree_cpu0 = qtree_cpu;
882 if (
Verbose && 0) fprintf(stderr,
"nsuper_avg=%f, counts_avg = %f 2*nsuper+counts=%f\n",nsuper_avg,counts_avg, 2*nsuper_avg+counts_avg);
888 fprintf(stderr,
"\r iter = %d, step = %f Fnorm = %f nsuper = %d nz = %d K = %f ",iter, step, Fnorm, (
int) nsuper_avg,A->
nz,K);
889 fprintf(stderr,
"energy = %f\n",spring_electrical_energy(dim, A, x, p, CRK, KP));
894 step = update_step(adaptive_cooling, step, Fnorm, Fnorm0, cool);
895 }
while (step > tol && iter < maxiter);
898 if (
Verbose && 0) fputs(
"\n", stderr);
905 strcpy(fname,
"/tmp/graph_layout");
906 sprintf(&(fname[strlen(fname)]),
"%d",n);
907 f = fopen(fname,
"w");
917 fprintf(stderr,
"iter = %d, step = %f Fnorm = %f qt_level = %d nsuper = %d nz = %d K = %f ",iter, step, Fnorm, max_qtree_level, (
int) nsuper_avg,A->
nz,K);
919 fprintf(stderr,
"iter = %d, step = %f Fnorm = %f nsuper = %d nz = %d K = %f ",iter, step, Fnorm, (
int) nsuper_avg,A->
nz,K);
927 total_cpu += ((
real) (clock() - start0)) / CLOCKS_PER_SEC;
928 if (
Verbose) fprintf(stderr,
"time for supernode = %f, total cpu = %f\n",qtree_cpu, total_cpu);
936 if (xold)
FREE(xold);
939 if (center)
FREE(center);
940 if (supernode_wgts)
FREE(supernode_wgts);
941 if (distances)
FREE(distances);
953 real p = ctrl->
p, K = ctrl->
K,
C = ctrl->
C, CRK, tol = ctrl->
tol, maxiter = ctrl->
maxiter, cool = ctrl->
cool, step = ctrl->
step, KP;
961 int nsuper = 0, nsupermax = 10;
962 real *center =
NULL, *supernode_wgts =
NULL, *distances =
NULL, nsuper_avg, counts = 0, counts_avg = 0;
964 clock_t start, end, start0, start2;
965 real qtree_cpu = 0, qtree_cpu0 = 0;
972 if (!A || maxiter <= 0)
return;
975 if (n <= 0 || dim <= 0)
return;
981 supernode_wgts =
MALLOC(
sizeof(
real)*nsupermax);
996 for (i = 0; i < dim*n; i++) x[i] =
drand();
1001 if (
C < 0) ctrl->
C =
C = 0.2;
1002 if (p >= 0) ctrl->
p = p = -1;
1004 CRK = pow(
C, (2.-p)/3.)/K;
1010 strcpy(fname,
"/tmp/graph_layout_0_");
1011 sprintf(&(fname[strlen(fname)]),
"%d",n);
1012 f = fopen(fname,
"w");
1023 #ifdef VIS_MULTILEVEL
1027 static int count = 0;
1028 sprintf(fname,
"/tmp/multilevel_%d",count++);
1029 f = fopen(fname,
"w");
1037 lab =
MALLOC(
sizeof(
char)*100);
1038 sprintf(lab,
"sfdp, adaptive_cooling = %d iter=%d", adaptive_cooling, iter);
1039 gviewer_set_label(lab);
1040 gviewer_reset_graph_coord(A, dim, x);
1042 gviewer_dump_current_frame();
1070 for (i = 0; i < n; i++){
1071 for (k = 0; k < dim; k++) f[k] = 0.;
1073 for (j = ia[i]; j < ia[i+1]; j++){
1074 if (ja[j] == i)
continue;
1076 for (k = 0; k < dim; k++){
1077 f[k] -= CRK*(x[i*dim+k] - x[ja[j]*dim+k])*dist;
1087 ¢er, &supernode_wgts, &distances, &counts, flag);
1091 qtree_cpu += ((
real) (end - start)) / CLOCKS_PER_SEC;
1093 counts_avg += counts;
1094 nsuper_avg += nsuper;
1095 if (*flag)
goto RETURN;
1096 for (j = 0; j < nsuper; j++){
1098 for (k = 0; k < dim; k++){
1100 f[k] += supernode_wgts[j]*KP*(x[i*dim+k] - center[j*dim+k])/(dist*dist);
1102 f[k] += supernode_wgts[j]*KP*(x[i*dim+k] - center[j*dim+k])/pow(dist, 1.- p);
1108 for (j = 0; j < n; j++){
1109 if (j == i)
continue;
1111 for (k = 0; k < dim; k++){
1113 f[k] += node_weights[j]*KP*(x[i*dim+k] - x[j*dim+k])/(dist*dist);
1115 f[k] += node_weights[j]*KP*(x[i*dim+k] - x[j*dim+k])/pow(dist, 1.- p);
1120 for (j = 0; j < n; j++){
1121 if (j == i)
continue;
1123 for (k = 0; k < dim; k++){
1125 f[k] += KP*(x[i*dim+k] - x[j*dim+k])/(dist*dist);
1127 f[k] += KP*(x[i*dim+k] - x[j*dim+k])/pow(dist, 1.- p);
1136 for (k = 0; k < dim; k++) F += f[k]*f[k];
1140 if (F > 0)
for (k = 0; k < dim; k++) f[k] /= F;
1142 for (k = 0; k < dim; k++) x[i*dim+k] += step*f[k];
1151 qtree_cpu0 = qtree_cpu - qtree_cpu0;
1152 if (
Verbose && 0) fprintf(stderr,
"\n cpu this outer iter = %f, quadtree time = %f other time = %f\n",((
real) (clock() - start2)) / CLOCKS_PER_SEC, qtree_cpu0,((
real) (clock() - start2))/CLOCKS_PER_SEC - qtree_cpu0);
1153 qtree_cpu0 = qtree_cpu;
1155 if (
Verbose & 0) fprintf(stderr,
"nsuper_avg=%f, counts_avg = %f 2*nsuper+counts=%f\n",nsuper_avg,counts_avg, 2*nsuper_avg+counts_avg);
1161 fprintf(stderr,
"\r iter = %d, step = %f Fnorm = %f nsuper = %d nz = %d K = %f ",iter, step, Fnorm, (
int) nsuper_avg,A->
nz,K);
1162 fprintf(stderr,
"energy = %f\n",spring_electrical_energy(dim, A, x, p, CRK, KP));
1167 step = update_step(adaptive_cooling, step, Fnorm, Fnorm0, cool);
1168 }
while (step > tol && iter < maxiter);
1171 if (
Verbose && 0) fputs(
"\n", stderr);
1174 #ifdef DEBUG_PRINT_0
1178 strcpy(fname,
"/tmp/graph_layout");
1179 sprintf(&(fname[strlen(fname)]),
"%d",n);
1180 f = fopen(fname,
"w");
1190 fprintf(stderr,
"iter = %d, step = %f Fnorm = %f qt_level = %d nsuper = %d nz = %d K = %f ",iter, step, Fnorm, max_qtree_level, (
int) nsuper_avg,A->
nz,K);
1192 fprintf(stderr,
"iter = %d, step = %f Fnorm = %f nsuper = %d nz = %d K = %f ",iter, step, Fnorm, (
int) nsuper_avg,A->
nz,K);
1200 total_cpu += ((
real) (clock() - start0)) / CLOCKS_PER_SEC;
1201 if (
Verbose) fprintf(stderr,
"time for supernode = %f, total cpu = %f\n",qtree_cpu, total_cpu);
1209 if (xold)
FREE(xold);
1212 if (center)
FREE(center);
1213 if (supernode_wgts)
FREE(supernode_wgts);
1214 if (distances)
FREE(distances);
1218 static void scale_coord(
int n,
int dim,
real *x,
int *
id,
int *jd,
real *d,
real dj){
1220 real w_ij,
dist,
s = 0, stop = 0, sbot = 0., nz = 0;
1222 if (dj == 0.)
return;
1223 for (i = 0; i < n; i++){
1224 for (j =
id[i]; j <
id[i+1]; j++){
1225 if (jd[j] == i)
continue;
1233 for (k = 0; k < dim; k++){
1234 stop += w_ij*dj*
dist;
1235 sbot += w_ij*dist*
dist;
1241 for (i = 0; i < n*dim; i++) x[i] *= s;
1242 fprintf(stderr,
"scaling factor = %f\n",s);
1245 static real dmean_get(
int n,
int *
id,
int *jd,
real* d){
1250 for (i = 0; i < n; i++){
1251 for (j =
id[i]; j <
id[i+1]; j++){
1255 return dmean/((
real)
id[n]);
1281 real p = ctrl->
p,
C = ctrl->
C, tol = ctrl->
tol, maxiter = ctrl->
maxiter, cool = ctrl->
cool, step = ctrl->
step, w_ij, dj = 1.;
1291 int nsuper = 0, nsupermax = 10;
1292 real *center =
NULL, *supernode_wgts =
NULL, *distances =
NULL, nsuper_avg, counts = 0;
1293 int max_qtree_level = 10;
1298 if (!A || maxiter <= 0)
return;
1300 if (n <= 0 || dim <= 0)
return;
1305 supernode_wgts =
MALLOC(
sizeof(
real)*nsupermax);
1325 id = ia; jd = ja; d =
NULL;
1328 dmean = dmean_get(n,
id, jd, d);
1329 rho = rho*(
id[n]/((((
real) n)*((
real) n)) -
id[n]))/pow(dmean, p+1);
1330 fprintf(stderr,
"dmean = %f, rho = %f\n",dmean, rho);
1334 fprintf(stderr,
"send random coordinates\n");
1336 for (i = 0; i < dim*n; i++) x[i] =
drand();
1344 scale_coord(n, dim, x,
id, jd, d, dj);
1348 if (
C < 0) ctrl->
C =
C = 0.2;
1349 if (p >= 0) ctrl->
p = p = -1;
1355 strcpy(fname,
"/tmp/graph_layout_0_");
1356 sprintf(&(fname[strlen(fname)]),
"%d",n);
1357 f = fopen(fname,
"w");
1388 for (i = 0; i < n; i++){
1389 for (k = 0; k < dim; k++) f[k] = 0.;
1392 for (j =
id[i]; j <
id[i+1]; j++){
1393 if (jd[j] == i)
continue;
1401 w_ij = 1./(dj*dj*dj);
1402 for (k = 0; k < dim; k++){
1403 f[k] += -w_ij*(x[i*dim+k] - x[jd[j]*dim+k])*(dist - dj)*(dist - dj)/dist;
1405 }
else if (ctrl->
q == 1){
1407 for (k = 0; k < dim; k++){
1408 f[k] += -w_ij*(x[i*dim+k] - x[jd[j]*dim+k])*(dist - dj)/
dist;
1411 w_ij = 1./pow(dj, ctrl->
q + 1);
1412 for (k = 0; k < dim; k++){
1413 f[k] += -w_ij*(x[i*dim+k] - x[jd[j]*dim+k])*pow(dist - dj, ctrl->
q)/
dist;
1419 for (k = 0; k < dim; k++){
1420 stress += (dist - dj)*(dist - dj)*w_ij;
1428 for (k = 0; k < dim; k++){
1430 f[k] -= rho*node_weights[j]*(x[i*dim+k] - x[jd[j]*dim+k])/(dist*dist);
1432 f[k] -= rho*node_weights[j]*(x[i*dim+k] - x[jd[j]*dim+k])/pow(dist, 1.- p);
1436 for (k = 0; k < dim; k++){
1438 f[k] -= rho*(x[i*dim+k] - x[jd[j]*dim+k])/(dist*dist);
1440 f[k] -= rho*(x[i*dim+k] - x[jd[j]*dim+k])/pow(dist, 1.- p);
1451 ¢er, &supernode_wgts, &distances, &counts, flag);
1452 nsuper_avg += nsuper;
1453 if (*flag)
goto RETURN;
1454 for (j = 0; j < nsuper; j++){
1456 for (k = 0; k < dim; k++){
1458 f[k] += rho*supernode_wgts[j]*(x[i*dim+k] - center[j*dim+k])/(dist*dist);
1460 f[k] += rho*supernode_wgts[j]*(x[i*dim+k] - center[j*dim+k])/pow(dist, 1.- p);
1466 for (j = 0; j < n; j++){
1467 if (j == i)
continue;
1469 for (k = 0; k < dim; k++){
1471 f[k] += rho*node_weights[j]*(x[i*dim+k] - x[j*dim+k])/(dist*dist);
1473 f[k] += rho*node_weights[j]*(x[i*dim+k] - x[j*dim+k])/pow(dist, 1.- p);
1478 for (j = 0; j < n; j++){
1479 if (j == i)
continue;
1481 for (k = 0; k < dim; k++){
1483 f[k] += rho*(x[i*dim+k] - x[j*dim+k])/(dist*dist);
1485 f[k] += rho*(x[i*dim+k] - x[j*dim+k])/pow(dist, 1.- p);
1494 for (k = 0; k < dim; k++) F += f[k]*f[k];
1498 if (F > 0)
for (k = 0; k < dim; k++) f[k] /= F;
1500 for (k = 0; k < dim; k++) x[i*dim+k] += step*f[k];
1507 stress /= (double) A->
nz;
1509 fprintf(stderr,
"\r iter = %d, step = %f Fnorm = %f nsuper = %d nz = %d stress = %f ",iter, step, Fnorm, (
int) nsuper_avg,A->
nz, stress);
1513 step = update_step(adaptive_cooling, step, Fnorm, Fnorm0, cool);
1514 }
while (step > tol && iter < maxiter);
1517 if (
Verbose) fputs(
"\n", stderr);
1524 if (xold)
FREE(xold);
1527 if (center)
FREE(center);
1528 if (supernode_wgts)
FREE(supernode_wgts);
1529 if (distances)
FREE(distances);
1542 real p = ctrl->
p, K = ctrl->
K,
C = ctrl->
C, CRK, tol = ctrl->
tol, maxiter = ctrl->
maxiter, cool = ctrl->
cool, step = ctrl->
step, KP;
1552 int nsuper = 0, nsupermax = 10;
1553 real *center =
NULL, *supernode_wgts =
NULL, *distances =
NULL, nsuper_avg, counts = 0;
1554 int max_qtree_level = 10;
1556 if (!A || maxiter <= 0)
return;
1558 if (n <= 0 || dim <= 0)
return;
1563 supernode_wgts =
MALLOC(
sizeof(
real)*nsupermax);
1581 for (i = 0; i < dim*n; i++) x[i] =
drand();
1586 if (
C < 0) ctrl->
C =
C = 0.2;
1587 if (p >= 0) ctrl->
p = p = -1;
1589 CRK = pow(
C, (2.-p)/3.)/K;
1595 strcpy(fname,
"/tmp/graph_layout_0_");
1596 sprintf(&(fname[strlen(fname)]),
"%d",n);
1597 f = fopen(fname,
"w");
1620 for (i = 0; i < n; i++){
1621 for (k = 0; k < dim; k++) f[k] = 0.;
1624 for (j = ia[i]; j < ia[i+1]; j++){
1625 if (ja[j] == i)
continue;
1627 for (k = 0; k < dim; k++){
1628 f[k] -= CRK*(x[i*dim+k] - x[ja[j]*dim+k])*dist;
1632 for (j =
id[i]; j <
id[i+1]; j++){
1633 if (jd[j] == i)
continue;
1635 for (k = 0; k < dim; k++){
1637 f[k] += 0.2*CRK*(x[i*dim+k] - x[jd[j]*dim+k])*(dist - d[j])*(dist - d[j])/dist;
1639 f[k] -= 0.2*CRK*(x[i*dim+k] - x[jd[j]*dim+k])*(dist - d[j])*(dist - d[j])/dist;
1648 ¢er, &supernode_wgts, &distances, &counts, flag);
1649 nsuper_avg += nsuper;
1650 if (*flag)
goto RETURN;
1651 for (j = 0; j < nsuper; j++){
1653 for (k = 0; k < dim; k++){
1655 f[k] += supernode_wgts[j]*KP*(x[i*dim+k] - center[j*dim+k])/(dist*dist);
1657 f[k] += supernode_wgts[j]*KP*(x[i*dim+k] - center[j*dim+k])/pow(dist, 1.- p);
1663 for (j = 0; j < n; j++){
1664 if (j == i)
continue;
1666 for (k = 0; k < dim; k++){
1668 f[k] += node_weights[j]*KP*(x[i*dim+k] - x[j*dim+k])/(dist*dist);
1670 f[k] += node_weights[j]*KP*(x[i*dim+k] - x[j*dim+k])/pow(dist, 1.- p);
1675 for (j = 0; j < n; j++){
1676 if (j == i)
continue;
1678 for (k = 0; k < dim; k++){
1680 f[k] += KP*(x[i*dim+k] - x[j*dim+k])/(dist*dist);
1682 f[k] += KP*(x[i*dim+k] - x[j*dim+k])/pow(dist, 1.- p);
1691 for (k = 0; k < dim; k++) F += f[k]*f[k];
1695 if (F > 0)
for (k = 0; k < dim; k++) f[k] /= F;
1697 for (k = 0; k < dim; k++) x[i*dim+k] += step*f[k];
1705 fprintf(stderr,
"\r iter = %d, step = %f Fnorm = %f nsuper = %d nz = %d K = %f ",iter, step, Fnorm, (
int) nsuper_avg,A->
nz,K);
1707 fprintf(stderr,
"energy = %f\n",spring_electrical_energy(dim, A, x, p, CRK, KP));
1712 step = update_step(adaptive_cooling, step, Fnorm, Fnorm0, cool);
1713 }
while (step > tol && iter < maxiter);
1716 if (
Verbose && 0) fputs(
"\n", stderr);
1719 #ifdef DEBUG_PRINT_0
1723 strcpy(fname,
"/tmp/graph_layout");
1724 sprintf(&(fname[strlen(fname)]),
"%d",n);
1725 f = fopen(fname,
"w");
1734 if (xold)
FREE(xold);
1737 if (center)
FREE(center);
1738 if (supernode_wgts)
FREE(supernode_wgts);
1739 if (distances)
FREE(distances);
1749 for (i = 0; i < n; i++){
1750 if (i != 0) printf(
",");
1752 for (k = 0; k < dim; k++) {
1753 if (k != 0) printf(
",");
1754 printf(
"%f",x[i*dim+k]);
1790 int i, j, k, *ia = A->
ia, *ja = A->
ja, nz;
1794 for (i = 0; i < A->
m; i++){
1795 for (k = 0; k < dim; k++) y[k] = 0;
1797 for (j = ia[i]; j < ia[i+1]; j++){
1798 if (ja[j] == i)
continue;
1800 for (k = 0; k < dim; k++){
1801 y[k] += x[ja[j]*dim + k];
1805 beta = (1-
alpha)/nz;
1806 for (k = 0; k < dim; k++) x[i*dim+k] = alpha*x[i*dim+k] + beta*y[k];
1813 int nc, *ia, *ja, i, j, k;
1822 for (i = 0; i < nc; i++){
1823 for (j = ia[i]+1; j < ia[i+1]; j++){
1824 for (k = 0; k < dim; k++){
1825 y[ja[j]*dim + k] += delta*(
drand() - 0.5);
1835 int *mask, m,
max = 0, i, *ia = A->
ia, *ja = A->
ja, j, deg;
1838 mask =
MALLOC(
sizeof(
int)*(m+1));
1840 for (i = 0; i < m + 1; i++){
1844 for (i = 0; i < m; i++){
1846 for (j = ia[i]; j < ia[i+1]; j++){
1847 if (i == ja[j])
continue;
1851 max =
MAX(max, mask[deg]);
1853 if (mask[1] > 0.8*max && mask[1] > 0.3*m) res =
TRUE;
1860 real y[4], axis[2], center[2],
dist, x0, x1;
1863 for (i = 0; i < dim*dim; i++) y[i] = 0;
1864 for (i = 0; i < dim; i++) center[i] = 0;
1865 for (i = 0; i < n; i++){
1866 for (k = 0; k < dim; k++){
1867 center[k] += x[i*dim+k];
1870 for (i = 0; i < dim; i++) center[i] /= n;
1871 for (i = 0; i < n; i++){
1872 for (k = 0; k < dim; k++){
1873 x[dim*i+k] = x[dim*i+k] - center[k];
1877 for (i = 0; i < n; i++){
1878 for (k = 0; k < dim; k++){
1879 for (l = 0; l < dim; l++){
1880 y[dim*k+l] += x[i*dim+k]*x[i*dim+l];
1885 axis[0] = 0; axis[1] = 1;
1893 axis[0] = -(-y[0] + y[3] - sqrt(y[0]*y[0]+4*y[1]*y[1]-2*y[0]*y[3]+y[3]*y[3]))/(2*y[1]);
1896 dist = sqrt(1+axis[0]*axis[0]);
1897 axis[0] = axis[0]/
dist;
1898 axis[1] = axis[1]/
dist;
1899 for (i = 0; i < n; i++){
1900 x0 = x[dim*i]*axis[0]+x[dim*i+1]*axis[1];
1901 x1 = -x[dim*i]*axis[1]+x[dim*i+1]*axis[0];
1910 static void rotate(
int n,
int dim,
real *x,
real angle){
1912 real axis[2], center[2], x0, x1;
1913 real radian = 3.14159/180;
1916 for (i = 0; i < dim; i++) center[i] = 0;
1917 for (i = 0; i < n; i++){
1918 for (k = 0; k < dim; k++){
1919 center[k] += x[i*dim+k];
1922 for (i = 0; i < dim; i++) center[i] /= n;
1923 for (i = 0; i < n; i++){
1924 for (k = 0; k < dim; k++){
1925 x[dim*i+k] = x[dim*i+k] - center[k];
1928 axis[0] = cos(-angle*radian);
1929 axis[1] = sin(-angle*radian);
1930 for (i = 0; i < n; i++){
1931 x0 = x[dim*i]*axis[0]+x[dim*i+1]*axis[1];
1932 x1 = -x[dim*i]*axis[1]+x[dim*i+1]*axis[0];
1940 static void attach_edge_label_coordinates(
int dim,
SparseMatrix A,
int n_edge_label_nodes,
int *edge_label_nodes,
real *x,
real *x2){
1946 mask =
MALLOC(
sizeof(
int)*A->
m);
1948 for (i = 0; i < A->
m; i++) mask[i] = 1;
1949 for (i = 0; i < n_edge_label_nodes; i++) {
1950 if (edge_label_nodes[i] >= 0 && edge_label_nodes[i] < A->
m) mask[edge_label_nodes[i]] = -1;
1953 for (i = 0; i < A->
m; i++) {
1954 if (mask[i] >= 0) mask[i] = nnodes++;
1958 for (i = 0; i < A->
m; i++){
1960 for (k = 0; k < dim; k++) x[i*dim+k] = x2[mask[i]*dim+k];
1964 for (i = 0; i < n_edge_label_nodes; i++){
1965 ii = edge_label_nodes[i];
1966 len = A->
ia[ii+1] - A->
ia[ii];
1969 for (k = 0; k < dim; k++) {
1972 for (j = A->
ia[ii]; j < A->ia[ii+1]; j++){
1973 for (k = 0; k < dim; k++){
1974 x[ii*dim+k] += x[(A->
ja[j])*dim+k];
1977 for (k = 0; k < dim; k++) {
1987 int i,
id = 0, nz, j, jj, ii;
1988 int *ia = A->
ia, *ja = A->
ja, *irn =
NULL, *jcn =
NULL;
1991 mask =
MALLOC(
sizeof(
int)*A->
m);
1993 for (i = 0; i < A->
m; i++) mask[i] = 1;
1995 for (i = 0; i < n_edge_label_nodes; i++){
1996 mask[edge_label_nodes[i]] = -1;
1999 for (i = 0; i < A->
m; i++) {
2000 if (mask[i] > 0) mask[i] =
id++;
2004 for (i = 0; i < A->
m; i++){
2005 if (mask[i] < 0)
continue;
2006 for (j = ia[i]; j < ia[i+1]; j++){
2007 if (mask[ja[j]] >= 0) {
2012 for (jj = ia[ii]; jj < ia[ii+1]; jj++){
2013 if (ja[jj] != i && mask[ja[jj]] >= 0) nz++;
2019 irn =
MALLOC(
sizeof(
int)*nz);
2020 jcn =
MALLOC(
sizeof(
int)*nz);
2024 for (i = 0; i < A->
m; i++){
2025 if (mask[i] < 0)
continue;
2026 for (j = ia[i]; j < ia[i+1]; j++){
2027 if (mask[ja[j]] >= 0) {
2029 jcn[nz++] = mask[ja[j]];
2033 for (jj = ia[ii]; jj < ia[ii+1]; jj++){
2034 if (ja[jj] != i && mask[ja[jj]] >= 0) {
2036 jcn[nz++] = mask[ja[jj]];
2037 if (mask[i] == 68 || mask[ja[jj]] == 68){
2038 fprintf(stderr,
"%d %d\n",mask[i], mask[ja[jj]]);
2056 real *x,
int n_edge_label_nodes,
int *edge_label_nodes,
int *flag){
2060 int n, plg, coarsen_scheme_used;
2078 if (n <= 0 || dim <= 0)
return;
2098 && n_edge_label_nodes > 0){
2102 A2 = shorting_edge_label_nodes(A, n_edge_label_nodes, edge_label_nodes);
2106 attach_edge_label_coordinates(dim, A, n_edge_label_nodes, edge_label_nodes, x, x2);
2130 if (plg) ctrl->
p = -1.8;
2138 fprintf(stderr,
"coarsest level -- %d, n = %d\n", grid->
level, grid->
n);
2140 fprintf(stderr,
"level -- %d, n = %d\n", grid->
level, grid->
n);
2149 fprintf(stderr,
"QUAD_TREE_HYBRID, size larger than %d, switch to fast quadtree",
QUAD_TREE_HYBRID_SIZE);
2196 prolongate(dim, grid->
A, P, grid->
R, xc, xf, coarsen_scheme_used, (ctrl->
K)*0.001);
2200 ctrl->
K = ctrl->
K * 0.75;
2212 fprintf(stderr,
"layout time %f\n",((
real) (clock() - cpu)) / CLOCKS_PER_SEC);
2218 if (
Verbose) fprintf(stderr,
"ctrl->overlap=%d\n",ctrl->
overlap);
2239 struct multilevel_spring_electrical_embedding_data {
2247 int n_edge_label_nodes;
2248 int *edge_label_nodes;
2252 void multilevel_spring_electrical_embedding_gv(
void*
data){
2253 struct multilevel_spring_electrical_embedding_data* d;
2255 d = (
struct multilevel_spring_electrical_embedding_data*) data;
2256 multilevel_spring_electrical_embedding_core(d->dim, d->A, d->D, d->ctrl, d->node_weights, d->label_sizes, d->x, d->n_edge_label_nodes, d->edge_label_nodes, d->flag);
2257 gviewer_reset_graph_coord(d->A, d->dim, d->x);
2260 real *x,
int n_edge_label_nodes,
int *edge_label_nodes,
int *flag){
2261 struct multilevel_spring_electrical_embedding_data
data = {dim, A, D, ctrl, node_weights, label_sizes, x, n_edge_label_nodes, edge_label_nodes, flag};
2266 if (!Gviewer)
return multilevel_spring_electrical_embedding_core(dim, A, D, ctrl, node_weights, label_sizes, x, n_edge_label_nodes, edge_label_nodes, flag);
2269 argvv = malloc(
sizeof(
char*)*argcc);
2270 argvv[0] = malloc(
sizeof(
char));
2273 gviewer_set_edge_color_scheme(COLOR_SCHEME_NO);
2275 gviewer_toggle_bgcolor();
2278 gviewer_init(&argcc, argvv, 0.01, 20, 60, 320, 320, A, dim, x, &(data), multilevel_spring_electrical_embedding_gv);
2284 real *x,
int n_edge_label_nodes,
int *edge_label_nodes,
int *flag){
2285 multilevel_spring_electrical_embedding_core(dim, A, D, ctrl, node_weights, label_sizes, x, n_edge_label_nodes, edge_label_nodes, flag);
#define Multilevel_is_finest(grid)
spring_electrical_control spring_electrical_control_new()
void QuadTree_get_repulsive_force(QuadTree qt, real *force, real *x, real bh, real p, real KP, real *counts, int *flag)
int multilevel_coarsen_scheme
void spring_electrical_control_delete(spring_electrical_control ctrl)
SparseMatrix SparseMatrix_symmetrize_nodiag(SparseMatrix A, int pattern_symmetric_only)
oned_optimizer oned_optimizer_new(int i)
Multilevel Multilevel_get_coarsest(Multilevel grid)
void spring_electrical_embedding(int dim, SparseMatrix A0, spring_electrical_control ctrl, real *node_weights, real *x, int *flag)
SparseMatrix SparseMatrix_remove_diagonal(SparseMatrix A)
real distance(real *x, int dim, int i, int j)
void interpolate_coord(int dim, SparseMatrix A, real *x)
void check_int_array_size(int **a, int len, int *lenmax)
void SparseMatrix_multiply_dense(SparseMatrix A, int ATransposed, real *v, int vTransposed, real **res, int res_transposed, int dim)
int multilevel_coarsen_mode
int SparseMatrix_has_diagonal(SparseMatrix A)
int SparseMatrix_is_symmetric(SparseMatrix A, int test_pattern_symmetry_only)
Multilevel Multilevel_new(SparseMatrix A0, SparseMatrix D0, real *node_weights, Multilevel_control ctrl)
#define Multilevel_is_coarsest(grid)
void spring_electrical_embedding_fast(int dim, SparseMatrix A0, spring_electrical_control ctrl, real *node_weights, real *x, int *flag)
void Multilevel_control_delete(Multilevel_control ctrl)
void oned_optimizer_delete(oned_optimizer opt)
void spring_electrical_embedding_slow(int dim, SparseMatrix A0, spring_electrical_control ctrl, real *node_weights, real *x, int *flag)
void export_embedding(FILE *fp, int dim, SparseMatrix A, real *x, real *width)
void print_matrix(real *x, int n, int dim)
void spring_electrical_spring_embedding(int dim, SparseMatrix A0, SparseMatrix D, spring_electrical_control ctrl, real *node_weights, real *x, int *flag)
void print_padding(int n)
void force_print(FILE *fp, int n, int dim, real *x, real *force)
void spring_electrical_control_print(spring_electrical_control ctrl)
SparseMatrix SparseMatrix_get_real_adjacency_matrix_symmetrized(SparseMatrix A)
real average_edge_length(SparseMatrix A, int dim, real *coord)
real get_angle(real *x, int dim, int i, int j)
Multilevel_control Multilevel_control_new(int scheme, int mode)
void QuadTree_get_supernodes(QuadTree qt, real bh, real *point, int nodeid, int *nsuper, int *nsupermax, real **center, real **supernode_wgts, real **distances, double *counts, int *flag)
void multilevel_spring_electrical_embedding(int dim, SparseMatrix A, SparseMatrix D, spring_electrical_control ctrl, real *node_weights, real *label_sizes, real *x, int n_edge_label_nodes, int *edge_label_nodes, int *flag)
SparseMatrix SparseMatrix_symmetrize(SparseMatrix A, int pattern_symmetric_only)
void pcp_rotate(int n, int dim, real *x)
void SparseMatrix_delete(SparseMatrix A)
if(aagss+aagstacksize-1<=aagssp)
void post_process_smoothing(int dim, SparseMatrix A, spring_electrical_control ctrl, real *node_weights, real *x, int *flag)
void check_real_array_size(real **a, int len, int *lenmax)
int oned_optimizer_get(oned_optimizer opt)
void QuadTree_delete(QuadTree q)
SparseMatrix SparseMatrix_from_coordinate_arrays(int nz, int m, int n, int *irn, int *jcn, void *val0, int type, size_t sz)
int power_law_graph(SparseMatrix A)
QuadTree QuadTree_new_from_point_list(int dim, int n, int max_level, real *coord, real *weight)
EXTERN unsigned char Verbose
void oned_optimizer_train(oned_optimizer opt, real work)
void spring_maxent_embedding(int dim, SparseMatrix A0, SparseMatrix D, spring_electrical_control ctrl, real *node_weights, real *x, real rho, int *flag)
double dist(Site *s, Site *t)
real distance_cropped(real *x, int dim, int i, int j)
int comp_real(const void *x, const void *y)
void Multilevel_delete(Multilevel grid)
void remove_overlap(int dim, SparseMatrix A, int m, real *x, real *label_sizes, int ntry, real initial_scaling, int do_shrinking, int *flag)