34#define stress_pca_dim 50
49 double sum,
dist, Dij;
51 for (count = 0, i = 0; i < n - 1; i++) {
53 for (j = 1; j < n - i; j++, count++) {
56 for (l = 0; l <
dim; l++) {
58 (coords[l][i] - coords[l][
neighbor]) * (coords[l][i] -
64 Dij = 1.0 / sqrt(lap[count]);
65 sum += (Dij -
dist) * (Dij -
dist) * lap[count];
67 Dij = 1.0 / lap[count];
68 sum += (Dij -
dist) * (Dij -
dist) * lap[count];
82 double sum,
dist, Dij;
85 for (i = 0; i < n; i++) {
86 for (
size_t j = 0; j < distances[i].
nedges; j++) {
92 for (l = 0; l <
dim; l++) {
94 (coords[l][i] - coords[l][
node]) * (coords[l][i] -
99 Dij = distances[i].
edist[j];
100 sum += (Dij -
dist) * (Dij -
dist) / (Dij * Dij);
104 for (i = 0; i < n; i++) {
105 for (
size_t j = 0; j < distances[i].
nedges; j++) {
111 for (l = 0; l <
dim; l++) {
113 (coords[l][i] - coords[l][
node]) * (coords[l][i] -
118 Dij = distances[i].
edist[j];
119 sum += (Dij -
dist) * (Dij -
dist) / Dij;
141 for (i = 0; i < n; i++) {
148 for (d = 2; d <
dim; d++)
149 coords[d][i] = *pt++;
157 for (d = 2; d <
dim; d++)
163 for (d = 0; d <
dim; d++)
172 float *Dij =
gv_calloc(nG * (nG + 1) / 2,
sizeof(
float));
181 for (i = 0; i < nG; i++) {
182 for (
size_t e = 1; e <
graph[i].nedges; e++) {
183 j =
graph[i].edges[e];
185 Gm[i][j] = Gm[j][i] = -1.0 /
graph[i].ewgts[e];
189 for (i = 0; i < nG; i++) {
190 for (
size_t e = 1; e <
graph[i].nedges; e++) {
191 j =
graph[i].edges[e];
193 Gm[i][j] = Gm[j][i] = -1.0;
203 for (i = 0; i < nG; i++) {
204 for (j = i; j < nG; j++) {
208 v = (float) (Gm_inv[i][i] + Gm_inv[j][j] -
257 double **subspace =
gv_calloc(subspace_dim,
sizeof(
double *));
258 double *d_storage =
gv_calloc(subspace_dim * n,
sizeof(
double));
259 int num_centers_local;
272 int *storage1 =
NULL;
274 int num_visited_nodes;
286 double *b_restricted;
288 double old_stress, new_stress;
291 for (i = 0; i < subspace_dim; i++) {
292 subspace[i] = d_storage + i * n;
296 num_centers_local =
MIN(n,
MAX(2 * subspace_dim, 50));
303 PCA_alloc(full_coords, num_centers_local, n, subspace, subspace_dim);
305 free(full_coords[0]);
312 int *CenterIndex =
gv_calloc(n,
sizeof(
int));
313 for (i = 0; i < n; i++) {
316 invCenterIndex =
NULL;
318 old_weights =
graph[0].ewgts;
320 if (reweight_graph) {
332 if (num_centers == 0) {
333 goto after_pivots_selection;
336 invCenterIndex =
gv_calloc(num_centers,
sizeof(
int));
340 for (i = 0; i < num_centers; i++)
341 Dij[i] = storage + i * n;
347 CenterIndex[
node] = 0;
348 invCenterIndex[0] =
node;
350 if (reweight_graph) {
358 for (i = 0; i < n; i++) {
360 if (
dist[i] > max_dist) {
366 for (i = 1; i < num_centers; i++) {
367 CenterIndex[
node] = i;
368 invCenterIndex[i] =
node;
369 if (reweight_graph) {
375 for (
int j = 0; j < n; j++) {
377 if (
dist[j] > max_dist
378 || (
dist[j] == max_dist && rand() % (j + 1) == 0)) {
385 after_pivots_selection:
390 for (i = 0; i < n; i++) {
394 visited_nodes =
gv_calloc(n,
sizeof(
int));
398 for (i = 0; i < n; i++) {
399 if (CenterIndex[i] >= 0) {
402 distances[i].
nedges = (size_t)n - 1;
405 index = CenterIndex[i];
406 for (
int j = 0; j < i; j++) {
407 distances[i].
edges[j] = j;
408 distances[i].
edist[j] = Dij[index][j];
410 for (
int j = i + 1; j < n; j++) {
411 distances[i].
edges[j - 1] = j;
412 distances[i].
edist[j - 1] = Dij[index][j];
419 num_visited_nodes = 0;
420 num_neighbors = num_visited_nodes + num_centers;
421 if (num_neighbors > available_space) {
423 storage1 =
gv_calloc(available_space,
sizeof(
int));
429 distances[i].
edges = storage1;
430 distances[i].
edist = storage2;
431 distances[i].
nedges = (size_t)num_neighbors;
432 nedges += (size_t)num_neighbors;
433 for (
int j = 0; j < num_visited_nodes; j++) {
434 storage1[j] = visited_nodes[j];
435 storage2[j] =
dist[visited_nodes[j]];
436 dist[visited_nodes[j]] = -1;
439 for (
int j = num_visited_nodes; j < num_neighbors; j++) {
440 index = j - num_visited_nodes;
441 storage1[j] = invCenterIndex[index];
442 storage2[j] = Dij[index][i];
445 storage1 += num_neighbors;
446 storage2 += num_neighbors;
447 available_space -= num_neighbors;
465 for (i = 0; i < n; i++) {
466 lap[i].
edges = edges;
467 lap[i].
ewgts = ewgts;
469 dist_list = distances[i].
edist - 1;
472 for (
size_t j = 1; j < lap[i].
nedges; j++) {
473 edges[j] = distances[i].
edges[j - 1];
474 ewgts[j] = -1.0f / ((float)dist_list[j] * (
float)dist_list[j]);
478 for (
size_t j = 1; j < lap[i].
nedges; j++) {
479 edges[j] = distances[i].
edges[j - 1];
480 ewgts[j] = -1.0f / (float) dist_list[j];
485 ewgts[0] = (float) degree;
497 directions[0] =
gv_calloc(
dim * subspace_dim,
sizeof(
double));
498 for (i = 1; i <
dim; i++) {
499 directions[i] = directions[0] + i * subspace_dim;
504 for (k = 0; k <
dim; k++) {
505 for (i = 0; i < subspace_dim; i++) {
506 directions[k][i] = 0;
512 for (k = 0; k <
dim; k++) {
513 directions[k][k] = 1;
520 directions[0][0] = 1;
522 for (k = 0; k < subspace_dim; k++) {
523 directions[1][k] = 0;
525 directions[1][1] = 1;
531 for (k = 0; k <
dim; k++) {
532 for (i = 0; i < subspace_dim; i++) {
533 directions[k][i] = (double) rand() / RAND_MAX;
540 for (k = 0; k <
dim; k++) {
542 directions[k], coords[k]);
550 double **matrix =
NULL;
553 mult_dense_mat_d(subspace, tmp_mat, subspace_dim, n, subspace_dim, &matrix);
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;
777#define DegType long double
795 float **coords =
NULL;
796 float *f_storage =
NULL;
805 double old_stress, new_stress;
808 float *tmp_coords =
NULL;
809 float *dist_accumulator =
NULL;
835 fprintf(stderr,
"Calculating subset model");
841 "graph is disconnected. Hence, the circuit model\n");
843 "is undefined. Reverting to the shortest path model.\n");
847 fprintf(stderr,
"Calculating MDS model");
852 fprintf(stderr,
"Calculating shortest paths");
861 fprintf(stderr,
"Setting initial positions");
869 if (smart_ini && n > 1) {
875 d_coords,
dim, smart_ini, exp,
882 for (i = 0; i <
dim; i++) {
885 for (j = 0; j < n; j++) {
886 if (fabs(d_coords[i][j]) > max) {
887 max = fabs(d_coords[i][j]);
890 for (j = 0; j < n; j++) {
891 d_coords[i][j] /= max;
894 for (j = 0; j < n; j++) {
895 d_coords[i][j] += 1e-6 * (
drand48() - 0.5);
904 if (n == 1 || maxi == 0) {
911 fprintf(stderr,
"Setting up stress function");
916 for (i = 0; i <
dim; i++) {
917 coords[i] = f_storage + i * n;
918 for (j = 0; j < n; j++) {
919 coords[i][j] = (float)d_coords[i][j];
925 assert(exp == 1 || exp == 2);
926 constant_term = (float)n * (n - 1) / 2;
932 lap_length = n * (n + 1) / 2;
943 for (i = 0; i < n - 1; i++) {
946 for (j = 1; j < n - i; j++, count++) {
949 degrees[i + j] -= val;
951 degrees[i] -= degree;
953 for (step = n, count = 0, i = 0; i < n; i++, count += step, step--) {
954 lap2[count] = degrees[i];
963 for (k = 1; k <
dim; k++) {
967 tmp_coords =
gv_calloc(n,
sizeof(
float));
968 dist_accumulator =
gv_calloc(n,
sizeof(
float));
969 lap1 =
gv_calloc(lap_length,
sizeof(
float));
972 old_stress = DBL_MAX;
975 fprintf(stderr,
"Solving model: ");
979 for (converged =
false, iterations = 0;
980 iterations < maxi && !converged; iterations++) {
984 memset(degrees, 0, n *
sizeof(
DegType));
988 for (count = 0, i = 0; i < n - 1; i++) {
994 for (k = 0; k <
dim; k++) {
996 for (x = 0; x < (size_t)
len; ++x) {
997 float tmp = coords[k][i] + -1.0f * (coords[k] + i + 1)[x];
998 dist_accumulator[x] += tmp * tmp;
1005 for (j = 0; j <
len; j++) {
1006 if (dist_accumulator[j] >= FLT_MAX || dist_accumulator[j] < 0) {
1007 dist_accumulator[j] = 0;
1014 for (j = 0; j <
len; j++, count++) {
1015 val = lap1[count] *= dist_accumulator[j];
1017 degrees[i + j + 1] -= val;
1020 for (j = 0; j <
len; j++, count++) {
1021 val = lap1[count] = dist_accumulator[j];
1023 degrees[i + j + 1] -= val;
1026 degrees[i] -= degree;
1028 for (step = n, count = 0, i = 0; i < n; i++, count += step, step--) {
1029 lap1[count] = degrees[i];
1033 for (k = 0; k <
dim; k++) {
1042 for (k = 0; k <
dim; k++) {
1046 new_stress += constant_term;
1047 for (k = 0; k <
dim; k++) {
1055 double diff = old_stress - new_stress;
1056 double change = fabs(diff);
1057 converged = change / old_stress <
Epsilon || new_stress <
Epsilon;
1059 old_stress = new_stress;
1061 for (k = 0; k <
dim; k++) {
1070 for (i = 0; i < n; i++) {
1073 coords[k][i] = tmp_coords[i];
1083 if (
Verbose && iterations % 5 == 0) {
1084 fprintf(stderr,
"%.3f ", new_stress);
1085 if ((iterations + 5) % 50 == 0)
1086 fprintf(stderr,
"\n");
1090 fprintf(stderr,
"\nfinal e = %f %d iterations %.2f sec\n",
1095 for (i = 0; i <
dim; i++) {
1096 for (j = 0; j < n; j++) {
1097 d_coords[i][j] = coords[i][j];
1110 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_d(double **A, double *x, double *b, int n, double tol, int max_iterations, bool ortho1)
int conjugate_gradient_mkernel(float *A, float *x, float *b, int n, double tol, int max_iterations)
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_d(double *const *matrix, int dim1, int dim2, const double *vector, double *restrict result)
void right_mult_with_vector_transpose(double **matrix, int dim1, int dim2, double *vector, double *result)
void invert_vec(int n, float *vec)
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 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 mult_dense_mat_d(double **A, float **B, int dim1, int dim2, int dim3, double ***CC)
void square_vec(int n, float *vec)
void right_mult_with_vector_ff(const float *packed_matrix, int n, const float *vector, float *restrict result)
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
size_t nedges
no. of neighbors, including self