return grid;
}
-
-#ifndef NOTUSED
-static Agglomerative_Ink_Bundling Agglomerative_Ink_Bundling_aggressive_establish(Agglomerative_Ink_Bundling grid, int *pick, real angle_param, real angle){
- /* this does a true single-linkage clustering: find the edge that gives the best saving, merge, find again.
- As oppose to: find the edge of node i that gives the best ink saving, merge, then do the same for node i+1, etc etc.
- Right now it is implemented as a quick hack to check whether it is worth while: it saves about 3% extra ink on airlines: from
- 59% to 62%
- */
- /* pick is a work array of dimension n, with n the total number of original edges */
- int *matching;
- SparseMatrix A = grid->A;
- int n = grid->n, level = grid->level, nc = 0;
- int *ia = A->ia, *ja = A->ja;
- // real *a;
- int i, j, k, jj, jc = -1, jmax, imax, ni, nj, npicks;
- int *mask;
- pedge *edges = grid->edges;
- real *inks = grid->inks, *cinks, inki, inkj;
- real gain, maxgain, minink, total_gain = 0;
- int *ip = NULL, *jp = NULL, ie;
- Vector *cedges;/* a table listing the content of bundled edges in the coarsen grid.
- cedges[i] contain the list of origonal edges that make up the bundle i in the next level */
- real ink0, ink1, grand_total_ink = 0, grand_total_gain = 0;
- point_t meet1, meet2;
-
- if (Verbose > 1) fprintf(stderr,"level ===================== %d, n = %d\n",grid->level, n);
- cedges = MALLOC(sizeof(Vector)*n);
- cinks = MALLOC(sizeof(real)*n);
- for (i = 0; i < n; i++) cedges[i] = Vector_new(1, sizeof(int), NULL);
-
- if (grid->level > 0){
- ip = grid->R0->ia;
- jp = grid->R0->ja;
- }
-
- matching = MALLOC(sizeof(int)*n);
- mask = MALLOC(sizeof(real)*n);
- for (i = 0; i < n; i++) mask[i] = -1;
-
- assert(n == A->n);
- for (i = 0; i < n; i++) matching[i] = UNMATCHED;
-
- //a = (real*) A->a;
-
- do {
- maxgain = 0;
- imax = -1;
- jmax = -1;
- minink = -1;
- for (i = 0; i < n; i++){
- if (matching[i] != UNMATCHED) continue;
-
- /* find the best matching in ink saving */
- for (j = ia[i]; j < ia[i+1]; j++){
- jj = ja[j];
- if (jj == i) continue;
-
- /* ink saving of merging i and j */
- if ((jc=matching[jj]) == UNMATCHED){
- /* neither i nor jj are matched */
- inki = inks[i]; inkj = inks[jj];
- if (ip && jp){/* not the first level */
- ni = (ip[i+1] - ip[i]);/* number of edges represented by i */
- nj = (ip[jj+1] - ip[jj]);/* number of edges represented by jj */
- memcpy(pick, &(jp[ip[i]]), sizeof(int)*ni);
- memcpy(pick+ni, &(jp[ip[jj]]), sizeof(int)*nj);
- } else {/* first level */
- pick[0] = i; pick[1] = jj;
- ni = nj = 1;
- }
- if (Verbose && DEBUG) fprintf(stderr, "ink(%d)=%f, ink(%d)=%f", i, inki, jj, inkj);
- } else {
- /* j is already matched. Its content is on cedges[jc] */
- inki = inks[i]; inkj = cinks[jc];
- if (Verbose && DEBUG) fprintf(stderr, "ink(%d)=%f, ink(%d->%d)=%f", i, inki, jj, jc, inkj);
- if (ip) {
- ni = (ip[i+1] - ip[i]);/* number of edges represented by i */
- memcpy(pick, &(jp[ip[i]]), sizeof(int)*ni);
- } else {
- ni = 1; pick[0] = i;
- }
- nj = Vector_get_length(cedges[jc]);
- npicks = ni;
- for (k = 0; k < nj; k++) {
- pick[npicks++] = *((int*) Vector_get(cedges[jc], k));
- }
- }
-
- npicks = ni + nj;
- ink1 = ink(edges, npicks, pick, &ink0, &meet1, &meet2, angle_param, angle);
- if (Verbose && DEBUG) {
- fprintf(stderr,", if merging {");
- for (k = 0; k < npicks; k++) fprintf(stderr,"%d,", pick[k]);
- fprintf(stderr,"}, ");
- fprintf(stderr, " ink0=%f, ink1=%f", inki+inkj, ink1);
- }
-
- gain = inki + inkj - ink1;
- if (Verbose && DEBUG) fprintf(stderr, " gain=%f", gain);
- if (gain > maxgain){
- maxgain = gain;
- minink = ink1;
- jmax = jj;
- imax = i;
- if (Verbose && DEBUG) fprintf(stderr, "maxgain=%f", maxgain);
- }
- if (Verbose && DEBUG) fprintf(stderr, "\n");
-
-
-
- }
- }
-
- /* now merge i and jmax */
- if (maxgain > 0){
- /* a good bundling of i and another edge jmax is found */
- total_gain += maxgain;
- jc = matching[jmax];
- if (jc == UNMATCHED){/* i and j both unmatched. Add j in the table first */
- if (Verbose && DEBUG) printf("maxgain=%f, merge %d with best edge: %d to form coarsen edge %d. Ink=%f\n",maxgain, imax, jmax, nc, minink);
- matching[imax] = matching[jmax] = nc;
- if (ip){
- for (k = ip[jmax]; k < ip[jmax+1]; k++) {
- ie = jp[k];
- Vector_add(cedges[nc], (void*) (&ie));
- }
- } else {
- Vector_add(cedges[nc], (void*) (&jmax));
- }
- jc = nc;
- nc++;
- } else {/*j is already matched */
- if (Verbose && DEBUG) printf("maxgain=%f, merge %d with existing cluster %d\n",maxgain, i, jc);
- matching[imax] = jc;
- grand_total_ink -= cinks[jc];/* ink of cluster jc was already added, and will be added again as part of a larger cluster with i, so dicount */
- }
- /* add i to the appropriate table */
- if (ip){
- for (k = ip[imax]; k < ip[imax+1]; k++) {
- ie = jp[k];
- Vector_add(cedges[jc], (void*) (&ie));
- }
- } else {
- Vector_add(cedges[jc], (void*) (&imax));
- }
- cinks[jc] = minink;
- grand_total_ink += minink;
- grand_total_gain += maxgain;
- } else {/*i can not match/bundle successfully */
- if (Verbose && DEBUG) fprintf(stderr, "no gain in bundling node %d\n",i);
- for (i = 0; i < n; i++){
- assert(maxgain <= 0);
- if (matching[i] == UNMATCHED){
- imax = i;
- matching[imax] = nc;
- jc = nc;
- minink = inks[imax];
- nc++;
-
- if (ip){
- for (k = ip[imax]; k < ip[imax+1]; k++) {
- ie = jp[k];
- Vector_add(cedges[jc], (void*) (&ie));
- }
- } else {
- Vector_add(cedges[jc], (void*) (&imax));
- }
- cinks[jc] = minink;
- grand_total_ink += minink;
- grand_total_gain += maxgain;
-
-
-
-
- }
- }
- }
-
- } while (maxgain > 0);
-
-
- if (Verbose && DEBUG){
- fprintf(stderr," coarse edge[%d]={",jc);
- for (k = 0; k < Vector_get_length(cedges[jc]); k++) {
- fprintf(stderr,"%d,", *((int*) Vector_get(cedges[jc], k)));
- }
- fprintf(stderr,"}\n");
- }
-
- if (nc >= 1 && total_gain > 0){
- /* now set up restriction and prolongation operator */
- SparseMatrix P, R, R1, R0, B, cA;
- real one = 1.;
- Agglomerative_Ink_Bundling cgrid;
-
- R1 = SparseMatrix_new(nc, n, 1, MATRIX_TYPE_REAL, FORMAT_COORD);
- for (i = 0; i < n; i++){
- jj = matching[i];
- SparseMatrix_coordinate_form_add_entries(R1, 1, &jj, &i, &one);
- }
- R = SparseMatrix_from_coordinate_format(R1);
- SparseMatrix_delete(R1);
- P = SparseMatrix_transpose(R);
- B = SparseMatrix_multiply(R, A);
- if (!B) goto RETURN;
- cA = SparseMatrix_multiply(B, P);
- if (!cA) goto RETURN;
- SparseMatrix_delete(B);
- grid->P = P;
- grid->R = R;
-
- level++;
- cgrid = Agglomerative_Ink_Bundling_init(cA, edges, level);
-
-
- /* set up R0!!! */
- if (grid->R0){
- R0 = SparseMatrix_multiply(R, grid->R0);
- } else {
- assert(grid->level == 0);
- R0 = R;
- }
- cgrid->R0 = R0;
- cgrid->inks = cinks;
- cgrid->total_ink = grand_total_ink;
-
- if (Verbose > 1) fprintf(stderr,"level %d->%d, edges %d -> %d, ink %f->%f , gain = %f, or %f\n", grid->level, cgrid->level, grid->n,
- cgrid->n, grid->total_ink, grand_total_ink, grid->total_ink - grand_total_ink, grand_total_gain);
- assert(fabs(grid->total_ink - cgrid->total_ink - grand_total_gain) <= 0.0001*grid->total_ink);
-
- cgrid = Agglomerative_Ink_Bundling_aggressive_establish(cgrid, pick, angle_param, angle);
- grid->next = cgrid;
- cgrid->prev = grid;
-
- } else {
- if (Verbose > 1) fprintf(stderr,"no more improvement, orig ink = %f, gain = %f, stop and final bundling found\n", grand_total_ink, grand_total_gain);
- /* no more improvement, stop and final bundling found */
- for (i = 0; i < n; i++) matching[i] = i;
- }
-
- RETURN:
- FREE(matching);
- for (i = 0; i < n; i++) Vector_delete(cedges[i]);
- FREE(mask);
- return grid;
-}
-#endif
-
static Agglomerative_Ink_Bundling Agglomerative_Ink_Bundling_new(SparseMatrix A0, pedge *edges, real angle_param, real angle){
/* give a link of edges and their nearest neighbor graph, return a multilevel of edge bundling based on ink saving */
Agglomerative_Ink_Bundling grid;
pick = MALLOC(sizeof(int)*A0->m);
- //grid = Agglomerative_Ink_Bundling_aggressive_establish(grid, pick, angle_param, angle);
grid = Agglomerative_Ink_Bundling_establish(grid, pick, angle_param, angle);
FREE(pick);