31#define localConstrMajorIterations 15
32#define levels_sep_tol 1e-1
52 bool directionalityExist =
false;
54 float *dist_accumulator =
NULL;
55 float *tmp_coords =
NULL;
57 double *degrees =
NULL;
59 float *f_storage =
NULL;
60 float **coords =
NULL;
63 CMajEnv *cMajEnv =
NULL;
67 const double abs_tol = 1e-2;
69 const double relative_tol = levels_sep_tol;
70 int *ordering =
NULL, *levels =
NULL;
75 for (
int i = 0; i < n; i++) {
76 for (
size_t j = 1; j <
graph[i].nedges; j++) {
77 directionalityExist |=
graph[i].edists[j] != 0;
81 if (!directionalityExist) {
95 d_coords + 1, nodes,
dim - 1,
99 for (
int i = 0; i < n; i++) {
100 d_coords[
dim - 1][i] = d_coords[1][i];
104 double *
const x = d_coords[0];
105 double *
const y = d_coords[1];
106 if (compute_y_coords(
graph, n, y, n)) {
110 if (compute_hierarchy(
graph, n, abs_tol, relative_tol, y, &ordering,
111 &levels, &num_levels)) {
115 if (num_levels < 1) {
119 d_coords, nodes,
dim,
123 if (levels_gap > 0) {
125 double displacement = 0;
126 for (
int i = 0; i < num_levels; i++) {
129 levels_gap - (y[ordering[levels[i]]] +
131 y[ordering[levels[i] - 1]]));
132 const int stop = i < num_levels - 1 ? levels[i + 1] : n;
133 for (
int j = levels[i]; j < stop; j++) {
134 y[ordering[j]] += displacement;
146 if (compute_hierarchy(
graph, n, abs_tol, relative_tol,
NULL, &ordering,
147 &levels, &num_levels)) {
173 fprintf(stderr,
"Calculating subset model");
179 "graph is disconnected. Hence, the circuit model\n");
181 "is undefined. Reverting to the shortest path model.\n");
185 fprintf(stderr,
"Calculating MDS model");
190 fprintf(stderr,
"Calculating shortest paths");
195 fprintf(stderr,
"Setting initial positions");
199 const int length = n + n * (n - 1) / 2;
205 for (
int i = 0; i <
dim; i++) {
206 for (
int j = 0; j < n; j++) {
207 max = fmax(max, fabs(d_coords[i][j]));
210 for (
int i = 0; i <
dim; i++) {
211 for (
int j = 0; j < n; j++) {
212 d_coords[i][j] *= 10 / max;
217 if (levels_gap > 0) {
218 const double sum1 = n * (n - 1) / 2;
220 for (
int count = 0, i = 0; i < n - 1; i++) {
222 for (
int j = i + 1; j < n; j++, count++) {
226 const float scale_ratio = (float)(sum2 / sum1);
227 for (
int i = 0; i <
length; i++) {
228 Dij[i] *= scale_ratio;
236 for (
int i = 0; i <
dim; i++) {
241 const double y_0 = d_coords[1][0];
242 for (
int i = 0; i < n; i++) {
243 d_coords[1][i] -= y_0;
248 for (
int i = 0; i <
dim; i++) {
249 coords[i] = f_storage + i * n;
250 for (
int j = 0; j < n; j++) {
251 coords[i][j] = (float)d_coords[i][j];
258 const double constant_term = n * (n - 1) / 2;
268 const int lap_length = n + n * (n - 1) / 2;
276 for (
int i = 0, count = 0; i < n - 1; i++) {
279 for (
int j = 1; j < n - i; j++, count++) {
280 const float val = lap2[count];
282 degrees[i + j] -= val;
284 degrees[i] -= degree;
286 for (
int step = n, count = 0, i = 0; i < n; i++, count += step, step--) {
287 lap2[count] = (float) degrees[i];
296 for (
int k = 1; k <
dim; k++) {
300 tmp_coords =
gv_calloc(n,
sizeof(
float));
301 dist_accumulator =
gv_calloc(n,
sizeof(
float));
302 lap1 =
gv_calloc(lap_length,
sizeof(
float));
304 double old_stress = DBL_MAX;
307 initConstrainedMajorization(lap2, n, ordering, levels, num_levels);
309 for (converged =
false, iterations = 0;
310 iterations < maxi && !converged; iterations++) {
315 for (
int count = 0, i = 0; i < n - 1; i++) {
316 const int len = n - i - 1;
323 for (
int k = 0; k <
dim; k++) {
333 for (
int j = 0; j <
len; j++) {
334 if (dist_accumulator[j] >= FLT_MAX || dist_accumulator[j] < 0) {
335 dist_accumulator[j] = 0;
341 for (
int j = 0; j <
len; j++, count++) {
342 const float val = lap1[count] *= dist_accumulator[j];
344 degrees[i + j + 1] -= val;
346 degrees[i] -= degree;
348 for (
int step = n, count = 0, i = 0; i < n; i++, count += step, step--) {
349 lap1[count] = (float) degrees[i];
353 for (
int k = 0; k <
dim; k++) {
362 double new_stress = 0;
363 for (
int k = 0; k <
dim; k++) {
367 new_stress += constant_term;
368 for (
int k = 0; k <
dim; k++) {
375 fabs(new_stress - old_stress) / fabs(old_stress + 1e-10) <
377 converged |= iterations > 1 && new_stress > old_stress;
381 old_stress = new_stress;
383 for (
int k = 0; k <
dim; k++) {
398 constrained_majorization_new_with_gaps(cMajEnv, b[k],
400 localConstrMajorIterations,
414 for (
int i = 0; i <
dim; i++) {
415 for (
int j = 0; j < n; j++) {
416 d_coords[i][j] = coords[i][j];
421 free(dist_accumulator);
428 if (cMajEnv !=
NULL) {
429 deleteCMajEnv(cMajEnv);
Memory allocation wrappers that exit on failure.
static void * gv_calloc(size_t nmemb, size_t size)
static Extype_t length(Exid_t *rhs, Exdisc_t *disc)
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)
at present, if any nodes have pos set, smart_ini is false
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