103 int n =
grid.front().
n, level =
grid.front().level, nc = 0;
104 int *ia =
A->ia, *ja =
A->ja;
105 int i, j, k, jj, jc, jmax, ni, nj, npicks;
106 const std::vector<pedge> &edges =
grid.front().edges;
107 const std::vector<double> &inks =
grid.front().inks;
109 double gain, maxgain, minink, total_gain = 0;
110 int *ip =
nullptr, *jp =
nullptr, ie;
111 std::vector<std::vector<int>>
115 double ink0,
ink1, grand_total_ink = 0, grand_total_gain = 0;
119 fprintf(stderr,
"level ===================== %d, n = %d\n",
120 grid.front().level, n);
122 std::vector<double> cinks(n, 0.0);
124 if (
grid.front().level > 0) {
125 ip =
grid.front().R0->ia;
126 jp =
grid.front().R0->ja;
132 for (i = 0; i < n; i++) {
140 for (j = ia[i]; j < ia[i + 1]; j++) {
151 ni = ip[i + 1] - ip[i];
152 nj = ip[jj + 1] - ip[jj];
153 memcpy(pick, &jp[ip[i]],
sizeof(
int) * ni);
154 memcpy(pick + ni, &jp[ip[jj]],
sizeof(
int) * nj);
162 fprintf(stderr,
"ink(%d)=%f, ink(%d)=%f", i, inki, jj, inkj);
169 fprintf(stderr,
"ink(%d)=%f, ink(%d->%d)=%f", i, inki, jj, jc,
172 ni = ip[i + 1] - ip[i];
173 memcpy(pick, &jp[ip[i]],
sizeof(
int) * ni);
178 nj = cedges[jc].size();
180 for (k = 0; k < nj; k++) {
181 pick[npicks++] = cedges[jc][k];
187 ink(edges, npicks, pick, &ink0, &meet1, &meet2, angle_param, angle);
190 fprintf(stderr,
", if merging {");
191 for (k = 0; k < npicks; k++)
192 fprintf(stderr,
"%d,", pick[k]);
193 fprintf(stderr,
"}, ");
194 fprintf(stderr,
" ink0=%f, ink1=%f", inki + inkj,
ink1);
198 gain = inki + inkj -
ink1;
201 fprintf(stderr,
" gain=%f", gain);
202 if (gain > maxgain) {
208 fprintf(stderr,
"maxgain=%f", maxgain);
212 fprintf(stderr,
"\n");
218 total_gain += maxgain;
224 printf(
"maxgain=%f, merge %d with best edge: %d to form coarsen "
226 maxgain, i, jmax, nc, minink);
227 matching[i] = matching[jmax] = nc;
229 for (k = ip[jmax]; k < ip[jmax + 1]; k++) {
231 cedges[nc].push_back(ie);
234 cedges[nc].push_back(jmax);
241 printf(
"maxgain=%f, merge %d with existing cluster %d\n", maxgain,
244 grand_total_ink -= cinks[jc];
251 fprintf(stderr,
"no gain in bundling node %d\n", i);
252 assert(maxgain <= 0);
261 for (k = ip[i]; k < ip[i + 1]; k++) {
263 cedges[jc].push_back(ie);
266 cedges[jc].push_back(i);
269 grand_total_ink += minink;
270 grand_total_gain += maxgain;
274 fprintf(stderr,
" coarse edge[%d]={", jc);
275 for (
const int &cedge : cedges[jc]) {
276 fprintf(stderr,
"%d,", cedge);
278 fprintf(stderr,
"}, grand_total_gain=%f\n", grand_total_gain);
283 if (nc >= 1 && total_gain > 0) {
289 for (i = 0; i < n; i++) {
309 if (
grid.front().R0) {
312 assert(
grid.front().level == 0);
315 cgrid.front().R0 = R0;
316 cgrid.front().inks = cinks;
317 cgrid.front().total_ink = grand_total_ink;
321 "level %d->%d, edges %d -> %d, ink %f->%f , gain = %f, or %f\n",
322 grid.front().level, cgrid.front().level,
grid.front().n,
323 cgrid.front().n,
grid.front().total_ink, grand_total_ink,
324 grid.front().total_ink - grand_total_ink, grand_total_gain);
325 assert(fabs(
grid.front().total_ink - cgrid.front().total_ink -
326 grand_total_gain) <= 0.0001 *
grid.front().total_ink);
329 grid.insert(
grid.end(), cgrid.begin(), cgrid.end());
334 "no more improvement, orig ink = %f, gain = %f, stop and final "
336 grand_total_ink, grand_total_gain);
365 int *recurse_level,
int MAX_RECURSE_LEVEL,
double angle_param,
double angle,
366 double *current_ink,
double *ink00) {
375 [[maybe_unused]]
const double TOL = 0.0001;
381 "agglomerative_ink_bundling_internal, recurse level ------- %d\n",
384 assert(
A->m == (
size_t)
A->n);
389 fprintf(stderr,
"CPU for agglomerative bundling %f\n",
390 (
double)(clock() - start) / CLOCKS_PER_SEC);
391 ink0 =
grid.front().total_ink;
396 if (*current_ink < 0) {
397 *current_ink = *ink00 = ink0;
399 fprintf(stderr,
"initial total ink = %f\n", *current_ink);
402 *current_ink -= ink0 -
ink1;
407 "ink: %f->%f, edges: %d->%d, current ink = %f, percentage gain "
408 "over original = %f\n",
409 ink0,
ink1,
grid.front().n,
grid.back().n, *current_ink,
410 (ink0 -
ink1) / *ink00);
414 if ((ink0 -
ink1) / *ink00 < 0.000001 || *recurse_level > MAX_RECURSE_LEVEL) {
420 for (
size_t i = 0; i < R->
m; i++) {
425 fprintf(stderr,
"calling ink2...\n");
426 ink1 =
ink(edges, ia[i + 1] - ia[i], pick, &ink0, &meet1, &meet2,
430 fprintf(stderr,
"finish calling ink2...\n");
431 assert(fabs(
ink1 -
grid.back().inks[i]) <= std::max(TOL, TOL *
ink1) &&
433 assert(
ink1 < 1000 * ink0);
435 if (ia[i + 1] - ia[i] > 1) {
436 for (j = ia[i]; j < ia[i + 1]; j++) {
444 pedge &e = edges[jj];
446 e.
x[1 *
dim] = meet1.
x;
447 e.
x[1 *
dim + 1] = meet1.
y;
448 e.
x[2 *
dim] = meet2.
x;
449 e.
x[2 *
dim + 1] = meet2.
y;
451 e.
x[3 *
dim + 1] = e.
x[4 *
dim + 1];
453 e.
wgts = std::vector<double>(4, e.
wgt);
456 for (j = ia[i]; j < ia[i + 1]; j++) {
457 pedge &e = edges[ja[j]];
483 std::vector<pedge> mid_edges(ne);
484 std::vector<double> xx(4 * ne);
485 for (
size_t i = 0; i < R->
m; i++) {
488 for (j = ia[i]; j < ia[i + 1]; j++)
492 fprintf(stderr,
"calling ink3...\n");
493 ink1 =
ink(edges, ia[i + 1] - ia[i], pick, &ink0, &meet1, &meet2,
497 fprintf(stderr,
"done calling ink3...\n");
498 assert(fabs(
ink1 -
grid.back().inks[i]) <= std::max(TOL, TOL *
ink1) &&
500 assert(
ink1 < 1000 * ink0);
501 xx[i * 4 + 0] = meet1.
x;
502 xx[i * 4 + 1] = meet1.
y;
503 xx[i * 4 + 2] = meet2.
x;
504 xx[i * 4 + 3] = meet2.
y;
511 recurse_level, MAX_RECURSE_LEVEL,
512 angle_param, angle, current_ink, ink00);
516 for (
size_t i = 0; i < R->
m; i++) {
518 const pedge &midedge = mid_edges[i];
520 for (j = ia[i]; j < ia[i + 1]; j++) {
523 pedge &e = edges[jj];
526 for (l = 0; l <
dim; l++) {
527 e.
x[(npp - 1) *
dim + l] = e.
x[1 *
dim + l];
530 for (k = 0; k < midedge.
npoints; k++) {
531 for (l = 0; l <
dim; l++) {
532 e.
x[(k + 1) *
dim + l] = midedge.
x[k *
dim + l];
535 if (!midedge.
wgts.empty()) {
549 for (
int i = 0; i < ne; i++)
557 std::vector<pedge> &edges,
int nneighbor,
558 int MAX_RECURSE_LEVEL,
double angle_param,
560 int recurse_level = 0;
561 double current_ink = -1, ink0;
565 MAX_RECURSE_LEVEL, angle_param, angle,
566 ¤t_ink, &ink0);
570 "initial total ink = %f, final total ink = %f, inksaving = %f "
571 "percent, total ink_calc = %f, avg ink_calc per edge = %f\n",
572 ink0, current_ink, (ink0 - current_ink) / ink0,
ink_count,
static void agglomerative_ink_bundling_internal(int dim, SparseMatrix A, std::vector< pedge > &edges, int nneighbors, int *recurse_level, int MAX_RECURSE_LEVEL, double angle_param, double angle, double *current_ink, double *ink00)
double ink(const std::vector< pedge > &edges, int numEdges, int *pick, double *ink0, point_t *meet1, point_t *meet2, double angle_param, double angle)