29#define localConstrMajorIterations 15
30#define levels_sep_tol 1e-1
51 bool directionalityExist =
false;
53 float *dist_accumulator =
NULL;
54 float *tmp_coords =
NULL;
56 double *degrees =
NULL;
59 float *f_storage =
NULL;
60 float **coords =
NULL;
63 CMajEnv *cMajEnv =
NULL;
70 double abs_tol = 1e-2;
72 double relative_tol = levels_sep_tol;
73 int *ordering =
NULL, *levels =
NULL;
78 double old_stress, new_stress;
84 for (i = 0; i < n; i++) {
85 for (
size_t j = 1; j <
graph[i].nedges; j++) {
86 directionalityExist |=
graph[i].edists[j] != 0;
90 if (!directionalityExist) {
106 d_coords + 1, nodes,
dim - 1,
107 opts, model, 15) < 0)
110 for (i = 0; i < n; i++) {
111 d_coords[
dim - 1][i] = d_coords[1][i];
117 if (compute_y_coords(
graph, n, y, n)) {
121 if (compute_hierarchy(
graph, n, abs_tol, relative_tol, y, &ordering,
122 &levels, &num_levels)) {
126 if (num_levels < 1) {
130 d_coords, nodes,
dim,
134 if (levels_gap > 0) {
136 double displacement = 0;
138 for (i = 0; i < num_levels; i++) {
141 levels_gap - (y[ordering[levels[i]]] +
143 y[ordering[levels[i] - 1]]));
144 stop = i < num_levels - 1 ? levels[i + 1] : n;
145 for (
int j = levels[i]; j < stop; j++) {
146 y[ordering[j]] += displacement;
158 if (compute_hierarchy(
graph, n, abs_tol, relative_tol,
NULL, &ordering,
159 &levels, &num_levels)) {
185 fprintf(stderr,
"Calculating subset model");
191 "graph is disconnected. Hence, the circuit model\n");
193 "is undefined. Reverting to the shortest path model.\n");
197 fprintf(stderr,
"Calculating MDS model");
202 fprintf(stderr,
"Calculating shortest paths");
207 fprintf(stderr,
"Setting initial positions");
212 length = n + n * (n - 1) / 2;
213 for (i = 0; i < length; i++) {
214 if (Dij[i] > diameter) {
215 diameter = (int) Dij[i];
223 for (i = 0; i <
dim; i++) {
224 for (
int j = 0; j < n; j++) {
225 max = fmax(max, fabs(d_coords[i][j]));
228 for (i = 0; i <
dim; i++) {
229 for (
int j = 0; j < n; j++) {
230 d_coords[i][j] *= 10 / max;
235 if (levels_gap > 0) {
236 double sum1, sum2, scale_ratio;
238 sum1 = (float) (n * (n - 1) / 2);
240 for (count = 0, i = 0; i < n - 1; i++) {
242 for (
int j = i + 1; j < n; j++, count++) {
246 scale_ratio = sum2 / sum1;
248 for (i = 0; i < length; i++) {
249 Dij[i] *= (float) scale_ratio;
257 for (i = 0; i <
dim; i++) {
262 y_0 = d_coords[1][0];
263 for (i = 0; i < n; i++) {
264 d_coords[1][i] -= y_0;
269 for (i = 0; i <
dim; i++) {
270 coords[i] = f_storage + i * n;
271 for (
int j = 0; j < n; j++) {
272 coords[i][j] = (float)d_coords[i][j];
279 constant_term = (float) (n * (n - 1) / 2);
289 lap_length = n + n * (n - 1) / 2;
298 for (i = 0; i < n - 1; i++) {
301 for (
int j = 1; j < n - i; j++, count++) {
304 degrees[i + j] -= val;
306 degrees[i] -= degree;
308 for (step = n, count = 0, i = 0; i < n; i++, count += step, step--) {
309 lap2[count] = (float) degrees[i];
318 for (k = 1; k <
dim; k++) {
322 tmp_coords =
gv_calloc(n,
sizeof(
float));
323 dist_accumulator =
gv_calloc(n,
sizeof(
float));
324 lap1 =
gv_calloc(lap_length,
sizeof(
float));
326 old_stress = DBL_MAX;
329 initConstrainedMajorization(lap2, n, ordering, levels, num_levels);
331 for (converged =
false, iterations = 0;
332 iterations < maxi && !converged; iterations++) {
337 for (count = 0, i = 0; i < n - 1; i++) {
345 for (k = 0; k <
dim; k++) {
355 for (
int j = 0; j <
len; j++) {
356 if (dist_accumulator[j] >= FLT_MAX || dist_accumulator[j] < 0) {
357 dist_accumulator[j] = 0;
363 for (
int j = 0; j <
len; j++, count++) {
364 val = lap1[count] *= dist_accumulator[j];
366 degrees[i + j + 1] -= val;
368 degrees[i] -= degree;
370 for (step = n, count = 0, i = 0; i < n; i++, count += step, step--) {
371 lap1[count] = (float) degrees[i];
375 for (k = 0; k <
dim; k++) {
385 for (k = 0; k <
dim; k++) {
389 new_stress += constant_term;
390 for (k = 0; k <
dim; k++) {
397 fabs(new_stress - old_stress) / fabs(old_stress + 1e-10) <
399 converged |= iterations > 1 && new_stress > old_stress;
403 old_stress = new_stress;
405 for (k = 0; k <
dim; k++) {
420 constrained_majorization_new_with_gaps(cMajEnv, b[k],
422 localConstrMajorIterations,
436 if (coords !=
NULL) {
437 for (i = 0; i <
dim; i++) {
438 for (
int j = 0; j < n; j++) {
439 d_coords[i][j] = coords[i][j];
447 free(dist_accumulator);
454 if (cMajEnv !=
NULL) {
455 deleteCMajEnv(cMajEnv);
Memory allocation wrappers that exit on failure.
static void * gv_calloc(size_t nmemb, size_t size)
int conjugate_gradient_mkernel(float *A, float *x, float *b, int n, double tol, int max_iterations)
static double len(glCompPoint p)
void agwarningf(const char *fmt,...)
int agerr(agerrlevel_t level, const char *fmt,...)
Agraph_t * graph(char *name)
double distance_kD(double **coords, int dim, int i, int j)
void invert_vec(int n, float *vec)
void invert_sqrt_vec(int n, float *vec)
void vectors_additionf(int n, float *vector1, float *vector2, float *result)
void set_vector_valf(int n, float val, float *result)
void orthog1(int n, double *vec)
void sqrt_vecf(int n, float *source, float *target)
void set_vector_val(int n, double val, double *result)
void right_mult_with_vector_ff(float *packed_matrix, int n, float *vector, float *result)
void vectors_mult_additionf(int n, float *vector1, float alpha, float *vector2)
void square_vec(int n, float *vec)
double vectors_inner_productf(int n, float *vector1, float *vector2)
float * compute_apsp_artificial_weights_packed(vtx_data *graph, int n)
int stress_majorization_kD_mkernel(vtx_data *graph, int n, double **d_coords, node_t **nodes, int dim, int opts, int model, int maxi)
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)
float * compute_apsp_packed(vtx_data *graph, int n)