28static bool equals(
float a,
float b) {
29 const float TOLERANCE = 1e-2;
30 return fabsf(a - b) < TOLERANCE;
33float **unpackMatrix(
float *packedMat,
int n)
37 float **mat =
gv_calloc(n,
sizeof(
float *));
40 for (i = 1; i < n; i++) {
41 mat[i] = mat[0] + i * n;
44 for (i = 0, k = 0; i < n; i++) {
45 for (j = i; j < n; j++, k++) {
46 mat[j][i] = mat[i][j] = packedMat[k];
53ensureMonotonicOrderingWithGaps(
float *place,
int n,
int *ordering,
54 int *levels,
int num_levels,
62 int node, level, max_in_level;
63 float lower_bound = -1e9f;
67 for (i = 0; i < n; i++) {
68 if (i >= max_in_level) {
71 if (level == num_levels) {
75 max_in_level = levels[level];
78 i > 0 ? place[ordering[i - 1]] + levels_gap : -1e9f;
83 if (place[
node] < lower_bound) {
84 place[
node] = lower_bound;
92constrained_majorization_new_with_gaps(CMajEnv * e,
float *b,
94 int cur_axis,
int max_iterations,
97 float *place = coords[cur_axis];
100 int *ordering = e->ordering;
101 int *levels = e->levels;
102 int num_levels = e->num_levels;
104 bool converged =
false;
105 float upper_bound, lower_bound;
109 float des_place_block;
111 float toBlockConnectivity;
113 float *desired_place;
114 float *prefix_desired_place;
115 float *suffix_desired_place;
116 int first_next_level;
117 int level = -1, max_in_level = 0;
121 if (max_iterations <= 0) {
125 ensureMonotonicOrderingWithGaps(place, n, ordering, levels, num_levels,
132 desired_place = e->fArray1;
134 prefix_desired_place = e->fArray2;
136 suffix_desired_place = e->fArray3;
141 for (
int i = 0; i < n; i++) {
142 if (i >= max_in_level) {
145 if (level == num_levels) {
149 max_in_level = levels[level];
159 for (
int counter = 0; counter < max_iterations && !converged; counter++) {
165 float prefix_des_place, suffix_des_place;
169 cur_place = place[ordering[
left]];
170 target_place = cur_place;
171 gap[ordering[
left]] = 0;
175 target_place += levels_gap;
179 if (fabs(place[
node] - target_place) > 1e-9) {
182 gap[
node] = place[
node] - cur_place;
190 new_place_i = -b[
node];
191 lap_node = lap[
node];
192 for (
int j = 0; j < n; j++) {
196 new_place_i += lap_node[j] * place[j];
198 desired_place[
node] =
199 new_place_i / (-lap_node[
node]) - gap[
node];
206 first_next_level = 0;
207 for (
int i =
left; i <
right; i = first_next_level) {
208 level = lev[ordering[i]];
209 if (level == num_levels) {
211 first_next_level =
right;
213 first_next_level =
MIN(
right, levels[level]);
219 for (
int j = i; j < first_next_level; j++) {
221 if (desired_place[
node] < cur_place) {
228 for (
int j = i; j < first_next_level; j++) {
230 if (desired_place[
node] == cur_place) {
237 for (
int j = i; j < first_next_level; j++) {
239 if (desired_place[
node] > cur_place) {
248 for (
size_t i = 0; i < ints_size(&
block); i++) {
250 toBlockConnectivity = 0;
251 lap_node = lap[
node];
252 for (
size_t j = 0; j < i; j++) {
253 toBlockConnectivity -= lap_node[ints_get(&
block, j)];
255 toBlockConnectivity *= 2;
258 (block_deg * des_place_block +
259 (-lap_node[
node]) * desired_place[
node] +
260 toBlockConnectivity * cur_place) / (block_deg -
262 toBlockConnectivity);
263 prefix_desired_place[i] = des_place_block;
264 block_deg += toBlockConnectivity - lap_node[
node];
267 if (n >= 0 && ints_size(&
block) == (size_t)n) {
269 prefix_desired_place[n - 1] = cur_place;
277 toBlockConnectivity = 0;
278 lap_node = lap[
node];
279 for (
size_t j = i + 1; j < ints_size(&
block); j++) {
280 toBlockConnectivity -= lap_node[ints_get(&
block, j)];
282 toBlockConnectivity *= 2;
285 (block_deg * des_place_block +
286 (-lap_node[
node]) * desired_place[
node] +
287 toBlockConnectivity * cur_place) / (block_deg -
289 toBlockConnectivity);
290 suffix_desired_place[i] = des_place_block;
291 block_deg += toBlockConnectivity - lap_node[
node];
294 if (n >= 0 && ints_size(&
block) == (size_t)n) {
296 suffix_desired_place[0] = cur_place;
303 for (
size_t i = 0; i < ints_size(&
block); i++) {
304 suffix_des_place = suffix_desired_place[i];
306 i > 0 ? prefix_desired_place[i - 1] : suffix_des_place;
308 if (suffix_des_place < prefix_des_place) {
309 if (suffix_des_place < cur_place) {
310 if (prefix_des_place > cur_place) {
311 prefix_des_place = cur_place;
313 suffix_des_place = prefix_des_place;
314 }
else if (prefix_des_place > cur_place) {
315 prefix_des_place = suffix_des_place;
319 (float)(ints_size(&
block) - i) * fabs(suffix_des_place - cur_place) +
320 (float)i * fabs(prefix_des_place - cur_place);
321 if (movement > max_movement) {
322 max_movement = movement;
328 suffix_des_place = suffix_desired_place[best_i];
331 0 ? prefix_desired_place[best_i -
332 1] : suffix_des_place;
343 if (lev[ordering[
right]] > lev[ordering[
right - 1]]) {
345 place[ordering[
right]] - levels_gap -
349 place[ordering[
right]] -
353 suffix_des_place = fminf(suffix_des_place, upper_bound);
354 prefix_des_place = fmaxf(prefix_des_place, lower_bound);
357 if (suffix_des_place < prefix_des_place) {
358 if (suffix_des_place < cur_place) {
359 if (prefix_des_place > cur_place) {
360 prefix_des_place = cur_place;
362 suffix_des_place = prefix_des_place;
363 }
else if (prefix_des_place > cur_place) {
364 prefix_des_place = suffix_des_place;
369 for (
size_t i = 0; i < best_i; i++) {
370 place[ints_get(&
block, i)] = prefix_des_place + gap[ints_get(&
block, i)];
373 for (
size_t i = best_i; i < ints_size(&
block); i++) {
374 place[ints_get(&
block, i)] = suffix_des_place + gap[ints_get(&
block, i)];
380 && lev[ordering[
right]] > lev[ordering[
right - 1]]) {
381 lower_bound = place[ints_get(&
block, ints_size(&
block) - 1)] + levels_gap;
383 lower_bound = place[ints_get(&
block, ints_size(&
block) - 1)];
392 ordering[i] = ints_get(&
block, i - (
size_t)
left);
394 converged &= equals(prefix_des_place, cur_place)
395 && equals(suffix_des_place, cur_place);
402 && lev[ordering[
right]] > lev[ordering[
right - 1]]) {
403 lower_bound = place[ints_get(&
block, ints_size(&
block) - 1)] + levels_gap;
405 lower_bound = place[ints_get(&
block, ints_size(&
block) - 1)];
415void deleteCMajEnv(CMajEnv * e)
426CMajEnv *initConstrainedMajorization(
float *packedMat,
int n,
427 int *ordering,
int *levels,
430 CMajEnv *e =
gv_alloc(
sizeof(CMajEnv));
432 e->ordering = ordering;
434 e->num_levels = num_levels;
435 e->A = unpackMatrix(packedMat, n);
436 e->fArray1 =
gv_calloc(n,
sizeof(
float));
437 e->fArray2 =
gv_calloc(n,
sizeof(
float));
438 e->fArray3 =
gv_calloc(n,
sizeof(
float));
439 e->fArray4 =
gv_calloc(n,
sizeof(
float));
Memory allocation wrappers that exit on failure.
static void * gv_calloc(size_t nmemb, size_t size)
static void * gv_alloc(size_t size)
void quicksort_placef(float *place, int *ordering, int first, int last)
#define DEFINE_LIST(name, type)
void orthog1f(int n, float *vec)
void set_vector_valf(int n, float val, float *result)