31#define node_degree(i) (ia[(i)+1] - ia[(i)])
37 int *ia, *ja, i, j, k, l, nz;
39 double len, di, sum, sumd;
54 for (i = 0; i <
D->m; i++) mask[i] = -1;
56 for (i = 0; i <
D->m; i++){
59 for (j = ia[i]; j < ia[i+1]; j++){
60 if (i == ja[j])
continue;
63 for (j = ia[i]; j < ia[i+1]; j++){
67 for (l = ia[k]; l < ia[k+1]; l++){
68 if (mask[ja[l]] == i)
len--;
78 for (i = 0; i <
D->m; i++){
79 for (j = ia[i]; j < ia[i+1]; j++){
80 if (i == ja[j])
continue;
86 sum /= nz; sumd /= nz;
89 for (i = 0; i <
D->m; i++){
90 for (j = ia[i]; j < ia[i+1]; j++){
91 if (i == ja[j])
continue;
102 int ideal_dist_scheme){
106 int i, j, k, l, m =
A->m, *ia =
A->ia, *ja =
A->ja, *iw, *jw, *
id, *jd;
108 double *d, *w, *lambda;
109 double diag_d, diag_w,
dist,
s = 0, stop = 0, sbot = 0;
124 for (i = 0; i < m; i++) sm->
lambda[i] = lambda0;
127 double *avg_dist =
gv_calloc(m,
sizeof(
double));
129 for (i = 0; i < m ;i++){
132 for (j = ia[i]; j < ia[i+1]; j++){
133 if (i == ja[j])
continue;
142 for (i = 0; i < m; i++) mask[i] = -1;
145 for (i = 0; i < m; i++){
147 for (j = ia[i]; j < ia[i+1]; j++){
154 for (j = ia[i]; j < ia[i+1]; j++){
156 for (l = ia[k]; l < ia[k+1]; l++){
157 if (mask[ja[l]] != i){
167 if (!(sm->
Lw) || !(sm->
Lwd)) {
181 for (i = 0; i < m; i++){
184 for (j = ia[i]; j < ia[i+1]; j++){
193 dist = (avg_dist[i] + avg_dist[k])*0.5;
197 fprintf(stderr,
"ideal_dist_scheme value wrong");
226 for (j = ia[i]; j < ia[i+1]; j++){
228 for (l = ia[k]; l < ia[k+1]; l++){
229 if (mask[ja[l]] != i+m){
235 dist = (avg_dist[i] + 2*avg_dist[k] + avg_dist[ja[l]])*0.5;
239 fprintf(stderr,
"ideal_dist_scheme value wrong");
270 lambda[i] *= (-diag_w);
272 w[nz] = -diag_w + lambda[i];
281 for (i = 0; i < nz; i++) d[i] *=
s;
297 int i, j, k, m =
A->m, *ia, *ja, *iw, *jw, *
id, *jd;
299 double *d, *w, *lambda;
300 double diag_d, diag_w, *a,
dist,
s = 0, stop = 0, sbot = 0;
306 for (i = 0; i < m*
dim; i++)
xdot += x[i]*x[i];
308 for (i = 0; i < m*
dim; i++) x[i] = 72*
drand();
329 if (!(sm->
Lw) || !(sm->
Lwd)) {
341 for (i = 0; i < m; i++){
343 for (j = ia[i]; j < ia[i+1]; j++){
363 lambda[i] *= (-diag_w);
364 w[nz] = -diag_w + lambda[i];
378 for (i = 0; i < nz; i++) d[i] *=
s;
389 double total = 0,
dist = 0;
392 for (i = 0; i < m; i++){
394 for (j = 0; j <
dim; j++){
415 int edge_labeling_scheme =
data->edge_labeling_scheme;
416 int n_constr_nodes =
data->n_constr_nodes;
417 int *constr_nodes =
data->constr_nodes;
419 int *ia = A_constr->
ia, *ja = A_constr->
ja, ii, jj, nz, l, ll, i, j;
420 int *irn =
data->irn, *jcn =
data->jcn;
421 double *val =
data->val,
dist, kk, k;
424 double constr_penalty =
data->constr_penalty;
443 assert((!jcn) && (!val));
445 for (i = 0; i < n_constr_nodes; i++){
446 ii = constr_nodes[i];
447 k = ia[ii+1] - ia[ii];
448 nz += (int)((k+1)*(k+1));
456 for (i = 0; i < n_constr_nodes; i++){
457 ii = constr_nodes[i];
458 jj = ja[ia[ii]]; ll = ja[ia[ii] + 1];
459 if (jj == ll)
continue;
463 k = ia[ii+1] - ia[ii];
465 irn[nz] = ii; jcn[nz] = ii; val[nz++] = constr_penalty/(
dist);
466 k = constr_penalty/(k*
dist); kk = constr_penalty/(kk*
dist);
467 for (j = ia[ii]; j < ia[ii+1]; j++){
468 irn[nz] = ii; jcn[nz] = ja[j]; val[nz++] = -k;
470 for (j = ia[ii]; j < ia[ii+1]; j++){
472 irn[nz] = jj; jcn[nz] = ii; val[nz++] = -k;
473 for (l = ia[ii]; l < ia[ii+1]; l++){
475 irn[nz] = jj; jcn[nz] = ll; val[nz++] = kk;
485 assert((!jcn) && (!val));
493 for (i = 0; i < n_constr_nodes; i++){
494 ii = constr_nodes[i];
495 jj = ja[ia[ii]]; ll = ja[ia[ii] + 1];
497 irn[nz] = ii; jcn[nz] = ii; val[nz++] = constr_penalty/(
dist);
498 for (j = ia[ii]; j < ia[ii+1]; j++){
500 for (l = 0; l <
dim; l++){
501 x00[ii*
dim+l] += x[jj*
dim+l];
504 for (l = 0; l <
dim; l++) {
505 x00[ii*
dim+l] *= constr_penalty/(
dist)/(ia[ii+1] - ia[ii]);
516 double *d,
double *x,
double scaling) {
518 double res = 0.,
dist;
520 for (i = 0; i < m; i++){
521 for (j = iw[i]; j < iw[i+1]; j++){
529 return 0.5*res/scaling/scaling;
535 int i, j, k, m, *
id, *jd, *iw, *jw, idiag, iter = 0;
536 double *w, *dd, *d, *y =
NULL, *x0 =
NULL, *x00 =
NULL, diag, diff = 1, *lambda = sm->
lambda;
540 const double tol = 0.001;
545 x0 = calloc(
dim*m,
sizeof(
double));
548 memcpy(x0, x,
sizeof(
double)*
dim*m);
549 y = calloc(
dim*m,
sizeof(
double));
552 id = Lwd->ia; jd = Lwd->ja;
556 iw = Lw->
ia; jw = Lw->
ja;
570 while (iter++ < maxit_sm && diff >
tol){
572 for (i = 0; i < m; i++){
575 for (j =
id[i]; j <
id[i+1]; j++){
588 for (k = 0; k <
dim; k++) x[jd[j]*
dim+k] += 0.0001*(
drand()+.0001)*dij;
603 for (i = 0; i < m; i++){
604 for (j = 0; j <
dim; j++){
605 y[i*
dim+j] += lambda[i]*x0[i*
dim+j];
613 for (i = 0; i < m; i++){
614 for (j = 0; j <
dim; j++){
615 y[i*
dim+j] += x00[i*
dim+j];
638 fprintf(stderr,
"Outer iter = %d, cg res = %g, ||x_{k+1}-x_k||/||x_k|| = %g\n",iter, res, diff);
643 memcpy(x, y,
sizeof(
double)*m*
dim);
647 _statistics[1] += iter-1;
651 if (
Verbose) fprintf(stderr,
"iter = %d, final stress = %f\n", iter,
get_stress(m,
dim, iw, jw, w, d, x, sm->
scaling));
678 bool use_triangularization) {
679 int i, j, k, m =
A->m, *ia =
A->ia, *ja =
A->ja, *iw, *jw, jdiag, nz;
681 double *d, *w, diag_d, diag_w,
dist;
682 double s = 0, stop = 0, sbot = 0;
686 double *avg_dist =
gv_calloc(m,
sizeof(
double));
688 for (i = 0; i < m ;i++){
691 for (j = ia[i]; j < ia[i+1]; j++){
692 if (i == ja[j])
continue;
710 if (use_triangularization){
725 if (!(sm->
Lw) || !(sm->
Lwd)) {
735 for (i = 0; i < m; i++){
738 for (j = iw[i]; j < iw[i+1]; j++){
760 lambda[i] *= (-diag_w);
763 w[jdiag] = -diag_w + lambda[i];
768 for (i = 0; i < iw[m]; i++) d[i] *=
s;
788 int i, j, k, l, m =
A->m, *ia =
A->ia, *ja =
A->ja, *
id, *jd;
801 double *avg_dist =
gv_calloc(m,
sizeof(
double));
803 for (i = 0; i < m ;i++){
806 for (j = ia[i]; j < ia[i+1]; j++){
807 if (i == ja[j])
continue;
816 for (i = 0; i < m; i++) mask[i] = -1;
819 for (i = 0; i < m; i++){
821 for (j = ia[i]; j < ia[i+1]; j++){
828 for (j = ia[i]; j < ia[i+1]; j++){
830 for (l = ia[k]; l < ia[k+1]; l++){
831 if (mask[ja[l]] != i){
845 id = sm->
D->
ia; jd = sm->
D->
ja;
850 for (i = 0; i < m; i++){
852 for (j = ia[i]; j < ia[i+1]; j++){
857 d[nz] = (avg_dist[i] + avg_dist[k])*0.5;
863 for (j = ia[i]; j < ia[i+1]; j++){
865 for (l = ia[k]; l < ia[k+1]; l++){
866 if (mask[ja[l]] != i+m){
869 d[nz] = (avg_dist[i] + 2*avg_dist[k] + avg_dist[ja[l]])*0.5;
968 if (
Verbose) fprintf(stderr,
"post processing %f\n",((
double) (clock() - cpu)) / CLOCKS_PER_SEC);
void SparseMatrix_multiply_dense(SparseMatrix A, const double *v, double *res, int dim)
bool SparseMatrix_is_symmetric(SparseMatrix A, bool test_pattern_symmetry_only)
SparseMatrix SparseMatrix_from_coordinate_arrays(int nz, int m, int n, int *irn, int *jcn, void *val0, int type, size_t sz)
void SparseMatrix_delete(SparseMatrix A)
SparseMatrix SparseMatrix_copy(SparseMatrix A)
SparseMatrix SparseMatrix_add(SparseMatrix A, SparseMatrix B)
SparseMatrix SparseMatrix_new(int m, int n, int nz, int type, int format)
Memory allocation wrappers that exit on failure.
static void * gv_calloc(size_t nmemb, size_t size)
static void * gv_alloc(size_t size)
SparseMatrix call_tri2(int n, int dim, double *xx)
SparseMatrix call_tri(int n, double *x)
static NORETURN void graphviz_exit(int status)
static double dist(int dim, double *x, double *y)
double distance(double *x, int dim, int i, int j)
double vector_product(int n, double *x, double *y)
double distance_cropped(double *x, int dim, int i, int j)
static double len(glCompPoint p)
static double drand(void)
@ ELSCHEME_STRAIGHTLINE_PENALTY2
@ ELSCHEME_STRAIGHTLINE_PENALTY
static void get_edge_label_matrix(relative_position_constraints data, int m, int dim, double *x, SparseMatrix *LL, double **rhs)
StressMajorizationSmoother SparseStressMajorizationSmoother_new(SparseMatrix A, int dim, double *x)
static double total_distance(int m, int dim, double *x, double *y)
static SparseMatrix ideal_distance_matrix(SparseMatrix A, int dim, double *x)
void SparseStressMajorizationSmoother_delete(SparseStressMajorizationSmoother sm)
TriangleSmoother TriangleSmoother_new(SparseMatrix A, int dim, double *x, bool use_triangularization)
double StressMajorizationSmoother_smooth(StressMajorizationSmoother sm, int dim, double *x, int maxit_sm)
void SpringSmoother_delete(SpringSmoother sm)
double SparseStressMajorizationSmoother_smooth(SparseStressMajorizationSmoother sm, int dim, double *x, int maxit_sm)
void post_process_smoothing(int dim, SparseMatrix A, spring_electrical_control ctrl, double *x)
void TriangleSmoother_smooth(TriangleSmoother sm, int dim, double *x)
void StressMajorizationSmoother_delete(StressMajorizationSmoother sm)
SpringSmoother SpringSmoother_new(SparseMatrix A, int dim, spring_electrical_control ctrl, double *x)
StressMajorizationSmoother StressMajorizationSmoother2_new(SparseMatrix A, int dim, double lambda0, double *x, int ideal_dist_scheme)
static UNUSED double get_stress(int m, int dim, int *iw, int *jw, double *w, double *d, double *x, double scaling)
void TriangleSmoother_delete(TriangleSmoother sm)
void SpringSmoother_smooth(SpringSmoother sm, SparseMatrix A, int dim, double *x)
@ SM_SCHEME_NORMAL_ELABEL
#define TriangleSmoother_struct
double SparseMatrix_solve(SparseMatrix A, int dim, double *x0, double *rhs, double tol, double maxit)
spring_electrical_control spring_electrical_control_new(void)
void spring_electrical_spring_embedding(int dim, SparseMatrix A0, SparseMatrix D, spring_electrical_control ctrl, double *x, int *flag)
void spring_electrical_control_delete(spring_electrical_control ctrl)
@ SMOOTHING_STRESS_MAJORIZATION_GRAPH_DIST
@ SMOOTHING_STRESS_MAJORIZATION_POWER_DIST
@ SMOOTHING_STRESS_MAJORIZATION_AVG_DIST
spring_electrical_control ctrl
void(* data_deallocator)(void *)
bool random_start
whether to apply SE from a random layout, or from exisiting layout
graphs, nodes and edges info: Agraphinfo_t, Agnodeinfo_t and Agedgeinfo_t
abstraction for squashing compiler warnings for unused symbols