30static bool equals(
float a,
float b) {
31 const float TOLERANCE = 1e-2;
32 return fabsf(a - b) < TOLERANCE;
35float **unpackMatrix(
float *packedMat,
int n)
39 float **mat =
gv_calloc(n,
sizeof(
float *));
42 for (i = 1; i < n; i++) {
43 mat[i] = mat[0] + i * n;
46 for (i = 0, k = 0; i < n; i++) {
47 for (j = i; j < n; j++, k++) {
48 mat[j][i] = mat[i][j] = packedMat[k];
55ensureMonotonicOrderingWithGaps(
float *place,
int n,
int *ordering,
56 int *levels,
int num_levels,
64 int node, level, max_in_level;
65 float lower_bound = -1e9f;
69 for (i = 0; i < n; i++) {
70 if (i >= max_in_level) {
73 if (level == num_levels) {
77 max_in_level = levels[level];
80 i > 0 ? place[ordering[i - 1]] + levels_gap : -1e9f;
85 if (place[
node] < lower_bound) {
86 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) {
250 toBlockConnectivity = 0;
251 lap_node = lap[
node];
252 for (
size_t j = 0; j < i; 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];
269 prefix_desired_place[n - 1] = cur_place;
277 toBlockConnectivity = 0;
278 lap_node = lap[
node];
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];
296 suffix_desired_place[0] = cur_place;
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)(
LIST_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++) {
380 && lev[ordering[
right]] > lev[ordering[
right - 1]]) {
394 converged &= equals(prefix_des_place, cur_place)
395 && equals(suffix_des_place, cur_place);
402 && lev[ordering[
right]] > lev[ordering[
right - 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)
type-generic dynamically expanding list
#define LIST_APPEND(list, item)
#define LIST_GET(list, index)
void orthog1f(int n, float *vec)
void set_vector_valf(int n, float val, float *result)