32#define stress_pca_dim 50
47 double sum,
dist, Dij;
49 for (count = 0, i = 0; i < n - 1; i++) {
51 for (j = 1; j < n - i; j++, count++) {
54 for (l = 0; l <
dim; l++) {
56 (coords[l][i] - coords[l][
neighbor]) * (coords[l][i] -
62 Dij = 1.0 / sqrt(lap[count]);
63 sum += (Dij -
dist) * (Dij -
dist) * lap[count];
65 Dij = 1.0 / lap[count];
66 sum += (Dij -
dist) * (Dij -
dist) * lap[count];
80 double sum,
dist, Dij;
83 for (i = 0; i < n; i++) {
84 for (
size_t j = 0; j < distances[i].
nedges; j++) {
90 for (l = 0; l <
dim; l++) {
92 (coords[l][i] - coords[l][
node]) * (coords[l][i] -
97 Dij = distances[i].
edist[j];
98 sum += (Dij -
dist) * (Dij -
dist) / (Dij * Dij);
102 for (i = 0; i < n; i++) {
103 for (
size_t j = 0; j < distances[i].
nedges; j++) {
109 for (l = 0; l <
dim; l++) {
111 (coords[l][i] - coords[l][
node]) * (coords[l][i] -
116 Dij = distances[i].
edist[j];
117 sum += (Dij -
dist) * (Dij -
dist) / Dij;
139 for (i = 0; i < n; i++) {
146 for (d = 2; d <
dim; d++)
147 coords[d][i] = *pt++;
155 for (d = 2; d <
dim; d++)
161 for (d = 0; d <
dim; d++)
170 float *Dij =
gv_calloc(nG * (nG + 1) / 2,
sizeof(
float));
179 for (i = 0; i < nG; i++) {
180 for (
size_t e = 1; e <
graph[i].nedges; e++) {
181 j =
graph[i].edges[e];
183 Gm[i][j] = Gm[j][i] = -1.0 /
graph[i].ewgts[e];
187 for (i = 0; i < nG; i++) {
188 for (
size_t e = 1; e <
graph[i].nedges; e++) {
189 j =
graph[i].edges[e];
191 Gm[i][j] = Gm[j][i] = -1.0;
201 for (i = 0; i < nG; i++) {
202 for (j = i; j < nG; j++) {
206 v = (float) (Gm_inv[i][i] + Gm_inv[j][j] -
255 double **subspace =
gv_calloc(subspace_dim,
sizeof(
double *));
256 double *d_storage =
gv_calloc(subspace_dim * n,
sizeof(
double));
257 int num_centers_local;
270 int *storage1 =
NULL;
272 int num_visited_nodes;
285 double *b_restricted;
287 double old_stress, new_stress;
290 for (i = 0; i < subspace_dim; i++) {
291 subspace[i] = d_storage + i * n;
295 num_centers_local =
MIN(n,
MAX(2 * subspace_dim, 50));
302 PCA_alloc(full_coords, num_centers_local, n, subspace, subspace_dim);
304 free(full_coords[0]);
311 int *CenterIndex =
gv_calloc(n,
sizeof(
int));
312 for (i = 0; i < n; i++) {
315 invCenterIndex =
NULL;
317 old_weights =
graph[0].ewgts;
319 if (reweight_graph) {
331 if (num_centers == 0) {
332 goto after_pivots_selection;
335 invCenterIndex =
gv_calloc(num_centers,
sizeof(
int));
339 for (i = 0; i < num_centers; i++)
340 Dij[i] = storage + i * n;
346 CenterIndex[
node] = 0;
347 invCenterIndex[0] =
node;
349 if (reweight_graph) {
357 for (i = 0; i < n; i++) {
359 if (
dist[i] > max_dist) {
365 for (i = 1; i < num_centers; i++) {
366 CenterIndex[
node] = i;
367 invCenterIndex[i] =
node;
368 if (reweight_graph) {
374 for (
int j = 0; j < n; j++) {
376 if (
dist[j] > max_dist
377 || (
dist[j] == max_dist && rand() % (j + 1) == 0)) {
384 after_pivots_selection:
389 for (i = 0; i < n; i++) {
393 visited_nodes =
gv_calloc(n,
sizeof(
int));
397 for (i = 0; i < n; i++) {
398 if (CenterIndex[i] >= 0) {
401 distances[i].
nedges = (size_t)n - 1;
404 index = CenterIndex[i];
405 for (
int j = 0; j < i; j++) {
406 distances[i].
edges[j] = j;
407 distances[i].
edist[j] = Dij[index][j];
409 for (
int j = i + 1; j < n; j++) {
410 distances[i].
edges[j - 1] = j;
411 distances[i].
edist[j - 1] = Dij[index][j];
418 num_visited_nodes = 0;
419 num_neighbors = num_visited_nodes + num_centers;
420 if (num_neighbors > available_space) {
422 storage1 =
gv_calloc(available_space,
sizeof(
int));
428 distances[i].
edges = storage1;
429 distances[i].
edist = storage2;
430 distances[i].
nedges = (size_t)num_neighbors;
431 nedges += (size_t)num_neighbors;
432 for (
int j = 0; j < num_visited_nodes; j++) {
433 storage1[j] = visited_nodes[j];
434 storage2[j] =
dist[visited_nodes[j]];
435 dist[visited_nodes[j]] = -1;
438 for (
int j = num_visited_nodes; j < num_neighbors; j++) {
439 index = j - num_visited_nodes;
440 storage1[j] = invCenterIndex[index];
441 storage2[j] = Dij[index][i];
444 storage1 += num_neighbors;
445 storage2 += num_neighbors;
446 available_space -= num_neighbors;
464 for (i = 0; i < n; i++) {
465 lap[i].
edges = edges;
466 lap[i].
ewgts = ewgts;
468 dist_list = distances[i].
edist - 1;
471 for (
size_t j = 1; j < lap[i].
nedges; j++) {
472 edges[j] = distances[i].
edges[j - 1];
473 ewgts[j] = (float) -1.0 / ((
float) dist_list[j] * (float) dist_list[j]);
477 for (
size_t j = 1; j < lap[i].
nedges; j++) {
478 edges[j] = distances[i].
edges[j - 1];
479 ewgts[j] = -1.0f / (float) dist_list[j];
484 ewgts[0] = (float) degree;
496 directions[0] =
gv_calloc(
dim * subspace_dim,
sizeof(
double));
497 for (i = 1; i <
dim; i++) {
498 directions[i] = directions[0] + i * subspace_dim;
503 for (k = 0; k <
dim; k++) {
504 for (i = 0; i < subspace_dim; i++) {
505 directions[k][i] = 0;
511 for (k = 0; k <
dim; k++) {
512 directions[k][k] = 1;
519 directions[0][0] = 1;
521 for (k = 0; k < subspace_dim; k++) {
522 directions[1][k] = 0;
524 directions[1][1] = 1;
530 for (k = 0; k <
dim; k++) {
531 for (i = 0; i < subspace_dim; i++) {
532 directions[k][i] = (double) rand() / RAND_MAX;
539 for (k = 0; k <
dim; k++) {
541 directions[k], coords[k]);
562 b_restricted =
gv_calloc(subspace_dim,
sizeof(
double));
564 for (converged =
false, iterations = 0;
565 iterations < n_iterations && !converged; iterations++) {
568 for (k = 0; k <
dim; k++) {
572 for (i = 0; i < n; i++) {
575 dist_list = distances[i].
edist - 1;
576 edges = lap[i].
edges;
577 ewgts = lap[i].
ewgts;
578 for (
size_t j = 1; j < lap[i].
nedges; j++) {
581 if (dist_ij > 1e-30) {
582 L_ij = -ewgts[j] * dist_list[j] / dist_ij;
584 b[i] += L_ij * coords[k][
node];
587 b[i] += degree * coords[k][i];
592 subspace_dim, conj_tol, subspace_dim,
598 directions[k], coords[k]);
601 if (iterations % 2 == 0) {
603 converged = fabs(new_stress - old_stress) / (new_stress + 1e-10) <
Epsilon;
604 old_stress = new_stress;
611 if (reweight_graph) {
615 for (i = 0; i < n; i++) {
616 if (distances[i].free_mem) {
617 free(distances[i].edges);
618 free(distances[i].edist);
627 free(invCenterIndex);
630 if (matrix !=
NULL) {
646 float *Dij =
gv_calloc(n * (n + 1) / 2,
sizeof(
float));
651 for (i = 0; i < n; i++) {
653 for (j = i; j < n; j++) {
654 Dij[count++] = Di[j];
677 for (i = 0; i < nG; i++) {
679 for (
size_t e = 1; e <
graph[i].nedges; e++) {
680 j =
graph[i].edges[e];
683 delta += fabsf(Dij[i * nG + j - shift] -
graph[i].ewgts[e]);
684 Dij[i * nG + j - shift] =
graph[i].ewgts[e];
688 fprintf(stderr,
"mdsModel: delta = %f\n",
delta);
697 float *Dij =
gv_calloc(n * (n + 1) / 2,
sizeof(
float));
702 for (i = 0; i < n; i++) {
704 for (j = i; j < n; j++) {
705 Dij[count++] = (float)Di[j];
718 float *old_weights =
graph[0].ewgts;
723 for (i = 0; i < n; i++) {
728 int *vtx_vec =
gv_calloc(n,
sizeof(
int));
731 for (i = 0; i < n; i++) {
733 deg_i =
graph[i].nedges - 1;
734 for (
size_t j = 1; j <= deg_i; j++) {
737 weights[j] = fmaxf((
float)(deg_i + deg_j -
741 graph[i].ewgts = weights;
742 weights +=
graph[i].nedges;
746 for (i = 0; i < n; i++) {
747 graph[i].ewgts = weights;
749 deg_i =
graph[i].nedges - 1;
750 for (
size_t j = 1; j <= deg_i; j++) {
757 weights +=
graph[i].nedges;
765 if (old_weights !=
NULL) {
766 for (i = 0; i < n; i++) {
767 graph[i].ewgts = old_weights;
768 old_weights +=
graph[i].nedges;
774#if defined(DEBUG) && DEBUG > 1
775static void dumpMatrix(
float *Dij,
int n)
778 for (i = 0; i < n; i++) {
779 for (j = i; j < n; j++) {
780 fprintf(stderr,
"%.02f ", Dij[count++]);
790#define DegType long double
808 float **coords =
NULL;
809 float *f_storage =
NULL;
818 double old_stress, new_stress;
821 float *tmp_coords =
NULL;
822 float *dist_accumulator =
NULL;
848 fprintf(stderr,
"Calculating subset model");
854 "graph is disconnected. Hence, the circuit model\n");
856 "is undefined. Reverting to the shortest path model.\n");
860 fprintf(stderr,
"Calculating MDS model");
865 fprintf(stderr,
"Calculating shortest paths");
874 fprintf(stderr,
"Setting initial positions");
882 if (smart_ini && n > 1) {
888 d_coords,
dim, smart_ini, exp,
895 for (i = 0; i <
dim; i++) {
898 for (j = 0; j < n; j++) {
899 if (fabs(d_coords[i][j]) > max) {
900 max = fabs(d_coords[i][j]);
903 for (j = 0; j < n; j++) {
904 d_coords[i][j] /= max;
907 for (j = 0; j < n; j++) {
908 d_coords[i][j] += 1e-6 * (
drand48() - 0.5);
917 if (n == 1 || maxi == 0) {
924 fprintf(stderr,
"Setting up stress function");
929 for (i = 0; i <
dim; i++) {
930 coords[i] = f_storage + i * n;
931 for (j = 0; j < n; j++) {
932 coords[i][j] = (float)d_coords[i][j];
938 assert(exp == 1 || exp == 2);
939 constant_term = (float)n * (n - 1) / 2;
945 lap_length = n * (n + 1) / 2;
956 for (i = 0; i < n - 1; i++) {
959 for (j = 1; j < n - i; j++, count++) {
962 degrees[i + j] -= val;
964 degrees[i] -= degree;
966 for (step = n, count = 0, i = 0; i < n; i++, count += step, step--) {
967 lap2[count] = degrees[i];
976 for (k = 1; k <
dim; k++) {
980 tmp_coords =
gv_calloc(n,
sizeof(
float));
981 dist_accumulator =
gv_calloc(n,
sizeof(
float));
982 lap1 =
gv_calloc(lap_length,
sizeof(
float));
985 old_stress = DBL_MAX;
988 fprintf(stderr,
"Solving model: ");
992 for (converged =
false, iterations = 0;
993 iterations < maxi && !converged; iterations++) {
997 memset(degrees, 0, n *
sizeof(
DegType));
1001 for (count = 0, i = 0; i < n - 1; i++) {
1007 for (k = 0; k <
dim; k++) {
1009 for (x = 0; x < (size_t)
len; ++x) {
1010 float tmp = coords[k][i] + -1.0f * (coords[k] + i + 1)[x];
1011 dist_accumulator[x] += tmp * tmp;
1018 for (j = 0; j <
len; j++) {
1019 if (dist_accumulator[j] >= FLT_MAX || dist_accumulator[j] < 0) {
1020 dist_accumulator[j] = 0;
1027 for (j = 0; j <
len; j++, count++) {
1028 val = lap1[count] *= dist_accumulator[j];
1030 degrees[i + j + 1] -= val;
1033 for (j = 0; j <
len; j++, count++) {
1034 val = lap1[count] = dist_accumulator[j];
1036 degrees[i + j + 1] -= val;
1039 degrees[i] -= degree;
1041 for (step = n, count = 0, i = 0; i < n; i++, count += step, step--) {
1042 lap1[count] = degrees[i];
1046 for (k = 0; k <
dim; k++) {
1055 for (k = 0; k <
dim; k++) {
1059 new_stress += constant_term;
1060 for (k = 0; k <
dim; k++) {
1068 double diff = old_stress - new_stress;
1069 double change = fabs(diff);
1070 converged = change / old_stress <
Epsilon || new_stress <
Epsilon;
1072 old_stress = new_stress;
1074 for (k = 0; k <
dim; k++) {
1083 for (i = 0; i < n; i++) {
1086 coords[k][i] = tmp_coords[i];
1096 if (
Verbose && iterations % 5 == 0) {
1097 fprintf(stderr,
"%.3f ", new_stress);
1098 if ((iterations + 5) % 50 == 0)
1099 fprintf(stderr,
"\n");
1103 fprintf(stderr,
"\nfinal e = %f %d iterations %.2f sec\n",
1108 for (i = 0; i <
dim; i++) {
1109 for (j = 0; j < n; j++) {
1110 d_coords[i][j] = coords[i][j];
1123 free(dist_accumulator);
Memory allocation wrappers that exit on failure.
static void * gv_calloc(size_t nmemb, size_t size)
void bfs(int vertex, vtx_data *graph, int n, DistType *dist)
compute vector dist of distances of all nodes from vertex
int solveCircuit(int nG, double **Gm, double **Gm_inv)
int conjugate_gradient_mkernel(float *A, float *x, float *b, int n, double tol, int max_iterations)
int conjugate_gradient_f(float **A, double *x, double *b, int n, double tol, int max_iterations, bool ortho1)
void embed_graph(vtx_data *graph, int n, int dim, DistType ***Coords, int reweight_graph)
void center_coordinate(DistType **coords, int n, int dim)
static double dist(int dim, double *x, double *y)
static double len(glCompPoint p)
void agwarningf(const char *fmt,...)
int agerr(agerrlevel_t level, const char *fmt,...)
Agraph_t * graph(char *name)
void compute_new_weights(vtx_data *graph, int n)
double distance_kD(double **coords, int dim, int i, int j)
void fill_neighbors_vec_unweighted(vtx_data *graph, int vtx, int *vtx_vec)
size_t common_neighbors(vtx_data *graph, int u, int *v_vector)
void restore_old_weights(vtx_data *graph, int n, float *old_weights)
void empty_neighbors_vec(vtx_data *graph, int vtx, int *vtx_vec)
void dijkstra_f(int vertex, vtx_data *graph, int n, float *dist)
void ngdijkstra(int vertex, vtx_data *graph, int n, DistType *dist)
#define neighbor(t, i, edim, elist)
void right_mult_with_vector_transpose(double **matrix, int dim1, int dim2, double *vector, double *result)
void invert_vec(int n, float *vec)
void right_mult_with_vector_d(double **matrix, int dim1, int dim2, double *vector, double *result)
void mult_sparse_dense_mat_transpose(vtx_data *A, double **B, int dim1, int dim2, float ***CC)
void invert_sqrt_vec(int n, float *vec)
void mult_dense_mat(double **A, float **B, int dim1, int dim2, int dim3, float ***CC)
void set_vector_valf(int n, float val, float *result)
void orthog1(int n, double *vec)
void copy_vectorf(int n, float *source, float *dest)
void sqrt_vecf(int n, float *source, float *target)
void right_mult_with_vector_ff(float *packed_matrix, int n, float *vector, float *result)
void square_vec(int n, float *vec)
double vectors_inner_productf(int n, float *vector1, float *vector2)
NEATOPROCS_API void free_array(double **rv)
NEATOPROCS_API double ** new_array(int i, int j, double val)
void PCA_alloc(DistType **coords, int dim, int n, double **new_coords, int new_dim)
bool iterativePCA_1D(double **coords, int dim, int n, double *new_direction)
static int nedges
total no. of edges used in routing
float * compute_apsp_artificial_weights_packed(vtx_data *graph, int n)
static double compute_stressf(float **coords, float *lap, int dim, int n, int exp)
int stress_majorization_kD_mkernel(vtx_data *graph, int n, double **d_coords, node_t **nodes, int dim, int opts, int model, int maxi)
at present, if any nodes have pos set, smart_ini is false
static float * compute_weighted_apsp_packed(vtx_data *graph, int n)
static int sparse_stress_subspace_majorization_kD(vtx_data *graph, int n, double **coords, int dim, int smart_ini, int exp, int reweight_graph, int n_iterations, int num_centers)
float * circuitModel(vtx_data *graph, int nG)
int initLayout(int n, int dim, double **coords, node_t **nodes)
float * mdsModel(vtx_data *graph, int nG)
update matrix with actual edge lengths
float * compute_apsp_packed(vtx_data *graph, int n)
assumes integral weights > 0
static double compute_stress1(double **coords, dist_data *distances, int dim, int n, int exp)
#define num_pivots_stress