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;
90constrained_majorization_new_with_gaps(CMajEnv * e,
float *b,
92 int cur_axis,
int max_iterations,
95 float *place = coords[cur_axis];
98 int *ordering = e->ordering;
99 int *levels = e->levels;
100 int num_levels = e->num_levels;
102 bool converged =
false;
103 float upper_bound, lower_bound;
107 float des_place_block;
109 float toBlockConnectivity;
111 float *desired_place;
112 float *prefix_desired_place;
113 float *suffix_desired_place;
114 int first_next_level;
115 int level = -1, max_in_level = 0;
119 if (max_iterations <= 0) {
123 ensureMonotonicOrderingWithGaps(place, n, ordering, levels, num_levels,
130 desired_place = e->fArray1;
132 prefix_desired_place = e->fArray2;
134 suffix_desired_place = e->fArray3;
139 for (
int i = 0; i < n; i++) {
140 if (i >= max_in_level) {
143 if (level == num_levels) {
147 max_in_level = levels[level];
157 for (
int counter = 0; counter < max_iterations && !converged; counter++) {
163 float prefix_des_place, suffix_des_place;
167 cur_place = place[ordering[
left]];
168 target_place = cur_place;
169 gap[ordering[
left]] = 0;
173 target_place += levels_gap;
177 if (fabs(place[
node] - target_place) > 1e-9) {
180 gap[
node] = place[
node] - cur_place;
188 new_place_i = -b[
node];
189 lap_node = lap[
node];
190 for (
int j = 0; j < n; j++) {
194 new_place_i += lap_node[j] * place[j];
196 desired_place[
node] =
197 new_place_i / (-lap_node[
node]) - gap[
node];
204 first_next_level = 0;
205 for (
int i =
left; i <
right; i = first_next_level) {
206 level = lev[ordering[i]];
207 if (level == num_levels) {
209 first_next_level =
right;
211 first_next_level =
MIN(
right, levels[level]);
217 for (
int j = i; j < first_next_level; j++) {
219 if (desired_place[
node] < cur_place) {
226 for (
int j = i; j < first_next_level; j++) {
228 if (desired_place[
node] == cur_place) {
235 for (
int j = i; j < first_next_level; j++) {
237 if (desired_place[
node] > cur_place) {
248 toBlockConnectivity = 0;
249 lap_node = lap[
node];
250 for (
size_t j = 0; j < i; j++) {
253 toBlockConnectivity *= 2;
256 (block_deg * des_place_block +
257 (-lap_node[
node]) * desired_place[
node] +
258 toBlockConnectivity * cur_place) / (block_deg -
260 toBlockConnectivity);
261 prefix_desired_place[i] = des_place_block;
262 block_deg += toBlockConnectivity - lap_node[
node];
267 prefix_desired_place[n - 1] = cur_place;
275 toBlockConnectivity = 0;
276 lap_node = lap[
node];
280 toBlockConnectivity *= 2;
283 (block_deg * des_place_block +
284 (-lap_node[
node]) * desired_place[
node] +
285 toBlockConnectivity * cur_place) / (block_deg -
287 toBlockConnectivity);
288 suffix_desired_place[i] = des_place_block;
289 block_deg += toBlockConnectivity - lap_node[
node];
294 suffix_desired_place[0] = cur_place;
302 suffix_des_place = suffix_desired_place[i];
304 i > 0 ? prefix_desired_place[i - 1] : suffix_des_place;
306 if (suffix_des_place < prefix_des_place) {
307 if (suffix_des_place < cur_place) {
308 if (prefix_des_place > cur_place) {
309 prefix_des_place = cur_place;
311 suffix_des_place = prefix_des_place;
312 }
else if (prefix_des_place > cur_place) {
313 prefix_des_place = suffix_des_place;
317 (float)(
LIST_SIZE(&
block) - i) * fabs(suffix_des_place - cur_place) +
318 (float)i * fabs(prefix_des_place - cur_place);
319 if (movement > max_movement) {
320 max_movement = movement;
326 suffix_des_place = suffix_desired_place[best_i];
329 0 ? prefix_desired_place[best_i -
330 1] : suffix_des_place;
341 if (lev[ordering[
right]] > lev[ordering[
right - 1]]) {
343 place[ordering[
right]] - levels_gap -
347 place[ordering[
right]] -
351 suffix_des_place = fminf(suffix_des_place, upper_bound);
352 prefix_des_place = fmaxf(prefix_des_place, lower_bound);
355 if (suffix_des_place < prefix_des_place) {
356 if (suffix_des_place < cur_place) {
357 if (prefix_des_place > cur_place) {
358 prefix_des_place = cur_place;
360 suffix_des_place = prefix_des_place;
361 }
else if (prefix_des_place > cur_place) {
362 prefix_des_place = suffix_des_place;
367 for (
size_t i = 0; i < best_i; i++) {
378 && lev[ordering[
right]] > lev[ordering[
right - 1]]) {
392 converged &= equals(prefix_des_place, cur_place)
393 && equals(suffix_des_place, cur_place);
400 && lev[ordering[
right]] > lev[ordering[
right - 1]]) {
413void deleteCMajEnv(CMajEnv * e)
424CMajEnv *initConstrainedMajorization(
float *packedMat,
int n,
425 int *ordering,
int *levels,
428 CMajEnv *e =
gv_alloc(
sizeof(CMajEnv));
430 e->ordering = ordering;
432 e->num_levels = num_levels;
433 e->A = unpackMatrix(packedMat, n);
434 e->fArray1 =
gv_calloc(n,
sizeof(
float));
435 e->fArray2 =
gv_calloc(n,
sizeof(
float));
436 e->fArray3 =
gv_calloc(n,
sizeof(
float));
437 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)