Skip to content

Commit

Permalink
Merge pull request #318 from AureumChaos/317-crowding-distance-calc-n…
Browse files Browse the repository at this point in the history
…eeds-to-handle-single-individual-pops

317 crowding distance calc needs to handle single individual pops
  • Loading branch information
markcoletti authored Feb 1, 2024
2 parents 3c1b24d + e5f7246 commit 2145ab2
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 6 deletions.
1 change: 0 additions & 1 deletion .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ python:
install:
- requirements: docs/requirements.txt


build:
os: ubuntu-22.04
tools:
Expand Down
11 changes: 9 additions & 2 deletions leap_ec/multiobjective/ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,12 @@ def per_rank_crowding_calc(ranked_population: list, is_maximizing) -> list:
:param ranked_population: A population of entirely one rank
:returns: population with crowding distance calculate for one rank
"""
if len(ranked_population) == 1:
# There is just one individual in this rank, so set their distance to 0
# since there are no neighbors.
ranked_population[0].distance = 0
return ranked_population

# Presuming this is a population with homogeneous objectives, then the size of
# the optimization directions array should be equal to the number of objectives.
num_objectives = is_maximizing.shape[0]
Expand Down Expand Up @@ -212,7 +218,7 @@ def per_rank_crowding_calc(ranked_population: list, is_maximizing) -> list:
sorted_pop = []

for objective in range(num_objectives):
if objective_ranges[objective] == 0:
if objective_ranges[objective] == 0 or objective_ranges[objective] == np.nan:
continue

# sort by objective being mindful that maximization vs. minimization may
Expand All @@ -239,7 +245,8 @@ def per_rank_crowding_calc(ranked_population: list, is_maximizing) -> list:
objective]) / objective_ranges[
objective]

return sorted_pop
# return ranked_population not sorted since sometimes sorted_pop will be empty
return ranked_population

@wrap_curry
@listlist_op
Expand Down
6 changes: 3 additions & 3 deletions tests/distributed/test_evaluate.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""
import numpy as np
import pytest
from distributed import Client
from distributed import Client, LocalCluster

from leap_ec.binary_rep.problems import MaxOnes
from leap_ec.distrib.evaluate import evaluate, is_viable
Expand All @@ -18,7 +18,7 @@ def test_good_eval():
leap_ec.distrib.evaluate works for normal circumstances.
"""
# set up a basic dask local cluster
with Client() as client:
with Client(LocalCluster(n_workers=1, threads_per_worker=1)) as client:
# hand craft an individual that should evaluate fine
# Let's try evaluating a single individual
individual = Individual(np.array([1, 1]),
Expand All @@ -40,7 +40,7 @@ def test_broken_individual_eval():
TODO implement this
"""
# set up a basic dask local cluster
with Client() as client:
with Client(LocalCluster(n_workers=1, threads_per_worker=1)) as client:
# hand craft an individual that will intentionally fail by not
# assigning it a Problem class
individual = DistributedIndividual(np.array([1, 1]),
Expand Down

0 comments on commit 2145ab2

Please sign in to comment.