Skip to content

Commit 4e1bf6a

Browse files
committed
* c/nondominated_kung.h: Simplify implementation by removing nondom and
setting rows to NULL instead. * c/nondominated.h (find_nondominated_set_3d_helper): Rename as find_nondominated_3d_impl. (find_nondominated_3d_impl_sorted): New. Assumes input is sorted.
1 parent f6b107b commit 4e1bf6a

2 files changed

Lines changed: 289 additions & 258 deletions

File tree

c/nondominated.h

Lines changed: 44 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -339,18 +339,16 @@ find_nondominated_set_2d_(const double * restrict points, size_t size,
339339
D. Jesus, Luís Paquete, A software library for archiving nondominated
340340
points, GECCO 2021. https://github.com/TLDart/nondLib/blob/main/nondlib.hpp
341341
342-
rows will be sorted by cmp_ppdouble_asc_rev_3d().
343-
max_dim will be != 3 only if the rows pointers have been shifted.
342+
rows should be already sorted by cmp_ppdouble_asc_rev_3d().
343+
344+
When find_one_dominated, return as soon as it finds one dominated point.
344345
*/
345-
static inline size_t
346-
find_nondominated_set_3d_helper(const double * restrict points,
347-
const double ** rows,
348-
size_t size, dimension_t max_dim,
349-
const bool keep_weakly, boolvec * restrict nondom)
346+
static __force_inline__ size_t
347+
find_nondominated_3d_impl_sorted(const double ** restrict rows, size_t size,
348+
const bool keep_weakly,
349+
const bool find_one_dominated)
350350
{
351351
ASSUME(size > 1);
352-
// Sort in ascending lexicographic order from the last dimension.
353-
qsort_typesafe(rows, size, cmp_ppdouble_asc_rev_3d);
354352

355353
avl_tree_t tree;
356354
avl_init_tree(&tree, qsort_cmp_pdouble_asc_x_nonzero);
@@ -428,16 +426,13 @@ find_nondominated_set_3d_helper(const double * restrict points,
428426
DEBUG2(printf_point("weakly dominated by pk: ", pk, 3, "\n"));
429427
}
430428
if (dominated) { // pj is dominated by a point in the tree or by prev.
431-
/* Map the order in rows[], which is sorted, to the original order
432-
in points. */
433-
size_t pos_last_dom = row_index_from_ptr(points, pj, max_dim);
434-
if (unlikely(nondom == NULL)) {
429+
if (find_one_dominated) {
435430
// In this context, it means "position of the first dominated solution found".
436-
new_size = pos_last_dom;
431+
new_size = j;
437432
goto early_end;
438433
}
439-
nondom[pos_last_dom] = false;
440434
last_dom = pj;
435+
rows[j] = NULL;
441436
new_size--;
442437
} else {
443438
pk = pj;
@@ -450,13 +445,30 @@ find_nondominated_set_3d_helper(const double * restrict points,
450445
return new_size;
451446
}
452447

448+
static __force_inline__ size_t
449+
find_nondominated_3d_impl(const double ** restrict rows, size_t size,
450+
const bool keep_weakly,
451+
const bool find_one_dominated)
452+
{
453+
// Sort in ascending lexicographic order from the last dimension.
454+
qsort_typesafe(rows, size, cmp_ppdouble_asc_rev_3d);
455+
// Help GCC generate all possible specializations of this function.
456+
return find_one_dominated
457+
? (keep_weakly
458+
? find_nondominated_3d_impl_sorted(rows, size, true, true)
459+
: find_nondominated_3d_impl_sorted(rows, size, false, true))
460+
: (keep_weakly
461+
? find_nondominated_3d_impl_sorted(rows, size, true, false)
462+
: find_nondominated_3d_impl_sorted(rows, size, false, false));
463+
}
464+
453465
static inline size_t
454466
find_dominated_3d_(const double * restrict points, size_t size, bool keep_weakly)
455467
{
456468
const double ** rows = generate_row_pointers(points, size, 3);
457-
size_t pos = keep_weakly
458-
? find_nondominated_set_3d_helper(points, rows, size, 3, true, /* nondom=*/NULL)
459-
: find_nondominated_set_3d_helper(points, rows, size, 3, false, /* nondom=*/NULL);
469+
size_t pos = find_nondominated_3d_impl(rows, size, keep_weakly, /* find_one_dominated=*/true);
470+
if (pos < size)
471+
pos = row_index_from_ptr(points, rows[pos], 3);
460472
free(rows);
461473
return pos;
462474
}
@@ -469,11 +481,20 @@ static inline size_t
469481
find_nondominated_set_3d_(const double * restrict points, size_t size,
470482
const bool keep_weakly, boolvec * restrict nondom)
471483
{
472-
const double ** rows = generate_row_pointers(points, size, 3);
473484
ASSUME(nondom != NULL);
474-
size_t new_size = keep_weakly
475-
? find_nondominated_set_3d_helper(points, rows, size, 3, true, nondom)
476-
: find_nondominated_set_3d_helper(points, rows, size, 3, false, nondom);
485+
const double ** rows = generate_row_pointers(points, size, 3);
486+
size_t new_size = find_nondominated_3d_impl(rows, size, keep_weakly, /* find_one_dominated=*/false);
487+
488+
if (new_size < size) {
489+
memset(nondom, 0, size * sizeof(*nondom));
490+
size_t k = 0, n = 0;
491+
do {
492+
while (rows[k] == NULL) k++; // Find next nondominated (there must be at least one).
493+
nondom[row_index_from_ptr(points, rows[k], 3)] = true;
494+
n++;
495+
k++;
496+
} while (n < new_size);
497+
}
477498
free(rows);
478499
return new_size;
479500
}
@@ -675,7 +696,7 @@ find_nondominated_set_(const double * restrict points, size_t size, dimension_t
675696
} else if (dim == 3) {
676697
new_size = find_nondominated_set_3d_(pp, size, keep_weakly, nondom);
677698
} else {
678-
new_size = find_nondominated_set_agree_kung(pp, size, dim, keep_weakly, nondom);
699+
new_size = find_nondominated_set_kung(pp, size, dim, keep_weakly, nondom);
679700
}
680701
if (pp != points)
681702
free((void *) pp);

0 commit comments

Comments
 (0)