-
Notifications
You must be signed in to change notification settings - Fork 449
Faster Bi-Objective Non-Dominated Sorting with O(N log N) Complexity #754
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Faster Bi-Objective Non-Dominated Sorting with O(N log N) Complexity #754
Conversation
This PR introduces a faster non-dominated sorting algorithm that leverages geometric properties to reduce complexity from O(N^2) to O(N log N), resulting in up to 60.92x faster performance for bi-objective problems.
Before (O(N^2) for all cases):
```python
# Original algorithm for all objective counts
for i in range(n):
for j in range(i + 1, n):
rel = M[i, j] # Full dominance matrix calculation
if rel == 1:
is_dominating[i].append(j)
n_dominated[j] += 1
elif rel == -1:
is_dominating[j].append(i)
n_dominated[i] += 1
```
After (O(N log N) for bi-objective, O(N^2) for others):
```python
# Specialized algorithm for bi-objective problems
if n_objectives == 2:
return _fast_biobjective_nondominated_sort(F) # O(N log N) algorithm
else:
# Fall back to optimized original approach for multi-objective
```
📊 Performance Results
| Size | Original (s) | Evolved (s) | Speedup |
|------|--------------|-------------|---------|
| 50 | 0.000328 | 0.000036 | 9.00x |
| 100 | 0.001024 | 0.000078 | 13.18x |
| 500 | 0.034089 | 0.000842 | 40.49x |
| 1000 | 0.104040 | 0.002246 | 46.33x |
| 2000 | 0.278000 | 0.004547 | 60.92x |
|------|--------------|-------------|---------|
Average speedup: 33.98x
Added comprehensive performance test (`test_comparison.py`) that:
- Uses the same interface as the original `pymoo` implementation
- Tests with actual bi-objective optimization scenarios
- Verifies identical results between original and optimized methods
- Demonstrates performance improvements across multiple problem sizes
|
Amazing thanks for your contribution! I was under the impression that this already exists somewhere in the codebase, but doesn't seem like it! |
|
How does this new implementation compare with https://multi-objective.github.io/moocore/python/reference/generated/moocore.pareto_rank.html#moocore.pareto_rank which already uses the O(n log n) algorithm by Jensen? Of course, you do whatever you want with For benchmarking, you could use the benchmarking code of |
|
Also, why would you want the file |
…nyoptimization#754) This PR introduces a faster non-dominated sorting algorithm that leverages geometric properties to reduce complexity from O(N^2) to O(N log N), resulting in up to 60.92x faster performance for bi-objective problems. Before (O(N^2) for all cases): ```python # Original algorithm for all objective counts for i in range(n): for j in range(i + 1, n): rel = M[i, j] # Full dominance matrix calculation if rel == 1: is_dominating[i].append(j) n_dominated[j] += 1 elif rel == -1: is_dominating[j].append(i) n_dominated[i] += 1 ``` After (O(N log N) for bi-objective, O(N^2) for others): ```python # Specialized algorithm for bi-objective problems if n_objectives == 2: return _fast_biobjective_nondominated_sort(F) # O(N log N) algorithm else: # Fall back to optimized original approach for multi-objective ``` 📊 Performance Results | Size | Original (s) | Evolved (s) | Speedup | |------|--------------|-------------|---------| | 50 | 0.000328 | 0.000036 | 9.00x | | 100 | 0.001024 | 0.000078 | 13.18x | | 500 | 0.034089 | 0.000842 | 40.49x | | 1000 | 0.104040 | 0.002246 | 46.33x | | 2000 | 0.278000 | 0.004547 | 60.92x | |------|--------------|-------------|---------| Average speedup: 33.98x Added comprehensive performance test (`test_comparison.py`) that: - Uses the same interface as the original `pymoo` implementation - Tests with actual bi-objective optimization scenarios - Verifies identical results between original and optimized methods - Demonstrates performance improvements across multiple problem sizes
|
all fair points. benchmark against the current implementation as well: Decided not to make it default. and thanks for the callout. decided to make a benchmark folder within tests. |
…754 - Add native_biobj_sorting parameter to fast_non_dominated_sort (default False) - Move test_comparison.py from pymoo/ to tests/benchmark/run_native_biobj.py - Simplify benchmark to use actual pymoo implementation Benchmark results show minimal performance improvement: Size Default (ms) Native BiObj (ms) Speedup Correct 50 0.107 0.036 2.98x Yes 100 0.103 0.100 1.03x Yes 500 1.038 1.065 0.98x Yes 1000 3.205 3.094 1.04x Yes 2000 8.615 8.642 1.00x Yes Not much improvement compared to moocore, thus not enabled by default. Addresses review comments from @MLopez-Ibanez
I recently added As you can see the current implementation of |
This PR introduces a faster non-dominated sorting algorithm that leverages geometric properties to reduce complexity from O(N^2) to O(N log N), resulting in up to 60.92x faster performance for bi-objective problems.
Before (O(N^2) for all cases):
After (O(N log N) for bi-objective, O(N^2) for others):
📊 Performance Results
Average speedup: 33.98x
Added comprehensive performance test (
test_comparison.py) that:pymooimplementation