97 int n =
grid.front().
n, level =
grid.front().level, nc = 0;
98 int *ia =
A->ia, *ja =
A->ja;
99 int i, j, k, jj, jc, jmax, ni, nj, npicks;
100 const std::vector<pedge> &edges =
grid.front().edges;
101 const std::vector<double> &inks =
grid.front().inks;
103 double gain, maxgain, minink, total_gain = 0;
105 std::vector<std::vector<int>> cedges;
107 double ink0,
ink1, grand_total_ink = 0, grand_total_gain = 0;
111 fprintf(stderr,
"level ===================== %d, n = %d\n",
112 grid.front().level, n);
114 std::vector<double> cinks(n, 0.0);
116 if (
grid.front().level > 0) {
117 ip =
grid.front().R0->ia;
118 jp =
grid.front().R0->ja;
124 for (i = 0; i < n; i++){
131 for (j = ia[i]; j < ia[i+1]; j++){
133 if (jj == i)
continue;
138 inki = inks[i]; inkj = inks[jj];
140 ni = (ip[i+1] - ip[i]);
141 nj = (ip[jj+1] - ip[jj]);
142 memcpy(pick, &(jp[ip[i]]),
sizeof(
int)*ni);
143 memcpy(pick+ni, &(jp[ip[jj]]),
sizeof(
int)*nj);
145 pick[0] = i; pick[1] = jj;
148 if (
MINGLE_DEBUG)
if (
Verbose) fprintf(stderr,
"ink(%d)=%f, ink(%d)=%f", i, inki, jj, inkj);
151 inki = inks[i]; inkj = cinks[jc];
152 if (
MINGLE_DEBUG)
if (
Verbose) fprintf(stderr,
"ink(%d)=%f, ink(%d->%d)=%f", i, inki, jj, jc, inkj);
154 ni = (ip[i+1] - ip[i]);
155 memcpy(pick, &(jp[ip[i]]),
sizeof(
int)*ni);
159 nj = cedges[jc].size();
161 for (k = 0; k < nj; k++) {
162 pick[npicks++] = cedges[jc][k];
168 ink(edges, npicks, pick, &ink0, &meet1, &meet2, angle_param, angle);
171 fprintf(stderr,
", if merging {");
172 for (k = 0; k < npicks; k++) fprintf(stderr,
"%d,", pick[k]);
173 fprintf(stderr,
"}, ");
174 fprintf(stderr,
" ink0=%f, ink1=%f", inki+inkj,
ink1);
178 gain = inki + inkj -
ink1;
196 total_gain += maxgain;
199 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);
200 matching[i] = matching[jmax] = nc;
202 for (k = ip[jmax]; k < ip[jmax+1]; k++) {
204 cedges[nc].push_back(ie);
207 cedges[nc].push_back(jmax);
212 if (
MINGLE_DEBUG)
if (
Verbose) printf(
"maxgain=%f, merge %d with existing cluster %d\n",maxgain, i, jc);
214 grand_total_ink -= cinks[jc];
218 assert(maxgain <= 0);
228 for (k = ip[i]; k < ip[i+1]; k++) {
230 cedges[jc].push_back(ie);
233 cedges[jc].push_back(i);
236 grand_total_ink += minink;
237 grand_total_gain += maxgain;
241 fprintf(stderr,
" coarse edge[%d]={",jc);
242 for (
const int &cedge : cedges[jc]) {
243 fprintf(stderr,
"%d,", cedge);
245 fprintf(stderr,
"}, grand_total_gain=%f\n",grand_total_gain);
251 if (nc >= 1 && total_gain > 0){
257 for (i = 0; i < n; i++){
275 if (
grid.front().R0) {
278 assert(
grid.front().level == 0);
281 cgrid.front().R0 = R0;
282 cgrid.front().inks = cinks;
283 cgrid.front().total_ink = grand_total_ink;
287 "level %d->%d, edges %d -> %d, ink %f->%f , gain = %f, or %f\n",
292 grid.front().total_ink,
294 grid.front().total_ink - grand_total_ink,
296 assert(fabs(
grid.front().total_ink - cgrid.front().total_ink - grand_total_gain)
297 <= 0.0001 *
grid.front().total_ink);
300 grid.insert(
grid.end(), cgrid.begin(), cgrid.end());
303 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);
331 int *recurse_level,
int MAX_RECURSE_LEVEL,
double angle_param,
double angle,
332 double *current_ink,
double *ink00) {
341 [[maybe_unused]]
const double TOL = 0.0001;
345 if (
Verbose > 1) fprintf(stderr,
"agglomerative_ink_bundling_internal, recurse level ------- %d\n",*recurse_level);
347 assert(
A->m ==
A->n);
352 fprintf(stderr,
"CPU for agglomerative bundling %f\n", ((
double) (clock() - start))/CLOCKS_PER_SEC);
353 ink0 =
grid.front().total_ink;
358 if (*current_ink < 0){
359 *current_ink = *ink00 = ink0;
361 fprintf(stderr,
"initial total ink = %f\n",*current_ink);
364 *current_ink -= ink0 -
ink1;
369 "ink: %f->%f, edges: %d->%d, current ink = %f, percentage gain over original = %f\n",
375 (ink0 -
ink1) / (*ink00));
378 if ((ink0-
ink1)/(*ink00) < 0.000001 || *recurse_level > MAX_RECURSE_LEVEL) {
384 for (i = 0; i < R->
m; i++){
388 ink1 =
ink(edges, ia[i+1]-ia[i], pick, &ink0, &meet1, &meet2, angle_param, angle);
390 assert(fabs(
ink1 -
grid.back().inks[i]) <= std::max(TOL, TOL *
ink1) &&
ink1 - ink0 <= TOL);
391 assert(
ink1 < 1000 * ink0);
393 if (ia[i+1]-ia[i] > 1){
394 for (j = ia[i]; j < ia[i+1]; j++){
400 pedge &e = edges[jj];
402 e.
x[1 *
dim] = meet1.
x;
403 e.
x[1 *
dim + 1] = meet1.
y;
404 e.
x[2 *
dim] = meet2.
x;
405 e.
x[2 *
dim + 1] = meet2.
y;
407 e.
x[3 *
dim + 1] = e.
x[4 *
dim + 1];
409 e.
wgts = std::vector<double>(4, e.
wgt);
413 for (j = ia[i]; j < ia[i+1]; j++){
414 pedge &e = edges[ja[j]];
438 std::vector<pedge> mid_edges(ne);
439 std::vector<double> xx(4 * ne);
440 for (i = 0; i < R->
m; i++){
443 for (j = ia[i]; j < ia[i+1]; j++) wgt += edges[j].wgt;
445 ink1 =
ink(edges, ia[i+1]-ia[i], pick, &ink0, &meet1, &meet2, angle_param, angle);
447 assert(fabs(
ink1 -
grid.back().inks[i]) <= std::max(TOL, TOL *
ink1) &&
ink1 - ink0 <= TOL);
448 assert(
ink1 < 1000 * ink0);
449 xx[i*4 + 0] = meet1.
x;
450 xx[i*4 + 1] = meet1.
y;
451 xx[i*4 + 2] = meet2.
x;
452 xx[i*4 + 3] = meet2.
y;
462 for (i = 0; i < R->
m; i++){
465 const pedge &midedge = mid_edges[i];
467 for (j = ia[i]; j < ia[i+1]; j++){
470 pedge &e = edges[jj];
473 for (l = 0; l <
dim; l++){
474 e.
x[(npp - 1) *
dim + l] = e.
x[1 *
dim + l];
477 for (k = 0; k < midedge.
npoints; k++){
478 for (l = 0; l <
dim; l++){
479 e.
x[(k + 1) *
dim + l] = midedge.
x[k *
dim + l];
482 if (!midedge.
wgts.empty()) {
504 std::vector<pedge> &edges,
int nneighbor,
505 int MAX_RECURSE_LEVEL,
double angle_param,
507 int recurse_level = 0;
508 double current_ink = -1, ink0;
512 MAX_RECURSE_LEVEL, angle_param, angle,
513 ¤t_ink, &ink0);
516 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)