99 int n =
grid.front().
n, level =
grid.front().level, nc = 0;
100 int *ia =
A->ia, *ja =
A->ja;
101 int i, j, k, jj, jc, jmax, ni, nj, npicks;
102 const std::vector<pedge> &edges =
grid.front().edges;
103 const std::vector<double> &inks =
grid.front().inks;
105 double gain, maxgain, minink, total_gain = 0;
107 std::vector<std::vector<int>> cedges;
109 double ink0,
ink1, grand_total_ink = 0, grand_total_gain = 0;
113 fprintf(stderr,
"level ===================== %d, n = %d\n",
114 grid.front().level, n);
116 std::vector<double> cinks(n, 0.0);
118 if (
grid.front().level > 0) {
119 ip =
grid.front().R0->ia;
120 jp =
grid.front().R0->ja;
126 for (i = 0; i < n; i++){
133 for (j = ia[i]; j < ia[i+1]; j++){
135 if (jj == i)
continue;
140 inki = inks[i]; inkj = inks[jj];
142 ni = ip[i + 1] - ip[i];
143 nj = ip[jj + 1] - ip[jj];
144 memcpy(pick, &jp[ip[i]],
sizeof(
int) * ni);
145 memcpy(pick + ni, &jp[ip[jj]],
sizeof(
int) * nj);
147 pick[0] = i; pick[1] = jj;
150 if (
MINGLE_DEBUG)
if (
Verbose) fprintf(stderr,
"ink(%d)=%f, ink(%d)=%f", i, inki, jj, inkj);
153 inki = inks[i]; inkj = cinks[jc];
154 if (
MINGLE_DEBUG)
if (
Verbose) fprintf(stderr,
"ink(%d)=%f, ink(%d->%d)=%f", i, inki, jj, jc, inkj);
156 ni = ip[i + 1] - ip[i];
157 memcpy(pick, &jp[ip[i]],
sizeof(
int) * ni);
161 nj = cedges[jc].size();
163 for (k = 0; k < nj; k++) {
164 pick[npicks++] = cedges[jc][k];
170 ink(edges, npicks, pick, &ink0, &meet1, &meet2, angle_param, angle);
173 fprintf(stderr,
", if merging {");
174 for (k = 0; k < npicks; k++) fprintf(stderr,
"%d,", pick[k]);
175 fprintf(stderr,
"}, ");
176 fprintf(stderr,
" ink0=%f, ink1=%f", inki+inkj,
ink1);
180 gain = inki + inkj -
ink1;
198 total_gain += maxgain;
201 if (
MINGLE_DEBUG)
if (
Verbose) printf(
"maxgain=%f, merge %d with best edge: %d to form coarsen edge %d. Ink=%f\n",maxgain, i, jmax, nc, minink);
202 matching[i] = matching[jmax] = nc;
204 for (k = ip[jmax]; k < ip[jmax+1]; k++) {
206 cedges[nc].push_back(ie);
209 cedges[nc].push_back(jmax);
214 if (
MINGLE_DEBUG)
if (
Verbose) printf(
"maxgain=%f, merge %d with existing cluster %d\n",maxgain, i, jc);
216 grand_total_ink -= cinks[jc];
220 assert(maxgain <= 0);
230 for (k = ip[i]; k < ip[i+1]; k++) {
232 cedges[jc].push_back(ie);
235 cedges[jc].push_back(i);
238 grand_total_ink += minink;
239 grand_total_gain += maxgain;
243 fprintf(stderr,
" coarse edge[%d]={",jc);
244 for (
const int &cedge : cedges[jc]) {
245 fprintf(stderr,
"%d,", cedge);
247 fprintf(stderr,
"}, grand_total_gain=%f\n",grand_total_gain);
253 if (nc >= 1 && total_gain > 0){
259 for (i = 0; i < n; i++){
277 if (
grid.front().R0) {
280 assert(
grid.front().level == 0);
283 cgrid.front().R0 = R0;
284 cgrid.front().inks = cinks;
285 cgrid.front().total_ink = grand_total_ink;
289 "level %d->%d, edges %d -> %d, ink %f->%f , gain = %f, or %f\n",
294 grid.front().total_ink,
296 grid.front().total_ink - grand_total_ink,
298 assert(fabs(
grid.front().total_ink - cgrid.front().total_ink - grand_total_gain)
299 <= 0.0001 *
grid.front().total_ink);
302 grid.insert(
grid.end(), cgrid.begin(), cgrid.end());
305 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);
333 int *recurse_level,
int MAX_RECURSE_LEVEL,
double angle_param,
double angle,
334 double *current_ink,
double *ink00) {
343 [[maybe_unused]]
const double TOL = 0.0001;
347 if (
Verbose > 1) fprintf(stderr,
"agglomerative_ink_bundling_internal, recurse level ------- %d\n",*recurse_level);
349 assert(
A->m ==
A->n);
354 fprintf(stderr,
"CPU for agglomerative bundling %f\n", (
double)(clock() - start) / CLOCKS_PER_SEC);
355 ink0 =
grid.front().total_ink;
360 if (*current_ink < 0){
361 *current_ink = *ink00 = ink0;
363 fprintf(stderr,
"initial total ink = %f\n",*current_ink);
366 *current_ink -= ink0 -
ink1;
371 "ink: %f->%f, edges: %d->%d, current ink = %f, percentage gain over original = %f\n",
377 (ink0 -
ink1) / *ink00);
380 if ((ink0 -
ink1) / *ink00 < 0.000001 || *recurse_level > MAX_RECURSE_LEVEL) {
386 for (i = 0; i < R->
m; i++){
390 ink1 =
ink(edges, ia[i+1]-ia[i], pick, &ink0, &meet1, &meet2, angle_param, angle);
392 assert(fabs(
ink1 -
grid.back().inks[i]) <= std::max(TOL, TOL *
ink1) &&
ink1 - ink0 <= TOL);
393 assert(
ink1 < 1000 * ink0);
395 if (ia[i+1]-ia[i] > 1){
396 for (j = ia[i]; j < ia[i+1]; j++){
402 pedge &e = edges[jj];
404 e.
x[1 *
dim] = meet1.
x;
405 e.
x[1 *
dim + 1] = meet1.
y;
406 e.
x[2 *
dim] = meet2.
x;
407 e.
x[2 *
dim + 1] = meet2.
y;
409 e.
x[3 *
dim + 1] = e.
x[4 *
dim + 1];
411 e.
wgts = std::vector<double>(4, e.
wgt);
415 for (j = ia[i]; j < ia[i+1]; j++){
416 pedge &e = edges[ja[j]];
440 std::vector<pedge> mid_edges(ne);
441 std::vector<double> xx(4 * ne);
442 for (i = 0; i < R->
m; i++){
445 for (j = ia[i]; j < ia[i+1]; j++) wgt += edges[j].wgt;
447 ink1 =
ink(edges, ia[i+1]-ia[i], pick, &ink0, &meet1, &meet2, angle_param, angle);
449 assert(fabs(
ink1 -
grid.back().inks[i]) <= std::max(TOL, TOL *
ink1) &&
ink1 - ink0 <= TOL);
450 assert(
ink1 < 1000 * ink0);
451 xx[i*4 + 0] = meet1.
x;
452 xx[i*4 + 1] = meet1.
y;
453 xx[i*4 + 2] = meet2.
x;
454 xx[i*4 + 3] = meet2.
y;
464 for (i = 0; i < R->
m; i++){
466 const pedge &midedge = mid_edges[i];
468 for (j = ia[i]; j < ia[i+1]; j++){
471 pedge &e = edges[jj];
474 for (l = 0; l <
dim; l++){
475 e.
x[(npp - 1) *
dim + l] = e.
x[1 *
dim + l];
478 for (k = 0; k < midedge.
npoints; k++){
479 for (l = 0; l <
dim; l++){
480 e.
x[(k + 1) *
dim + l] = midedge.
x[k *
dim + l];
483 if (!midedge.
wgts.empty()) {
505 std::vector<pedge> &edges,
int nneighbor,
506 int MAX_RECURSE_LEVEL,
double angle_param,
508 int recurse_level = 0;
509 double current_ink = -1, ink0;
513 MAX_RECURSE_LEVEL, angle_param, angle,
514 ¤t_ink, &ink0);
517 fprintf(stderr,
"initial total ink = %f, final total ink = %f, inksaving = %f percent, total ink_calc = %f, avg ink_calc per edge = %f\n", ink0, current_ink, (ink0-current_ink)/ink0,
ink_count,
ink_count/(
double)
A->m);
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)