Skip to content

Evaluate solutions

The lifecycle of metaheuristics often requires evaluating a list of solutions on every iteration. In evolutionary algorithms, for example, this list of solutions is known as population.

In order to evaluate a population, NSGA-II (and in general, any generational algorithm in jMetalPy) uses an evaluator object.

Sequential

The default evaluator runs in a sequential fashion (i.e., one solution at a time):

from jmetal.util.evaluator import SequentialEvaluator

algorithm = NSGAII(
   problem=problem,
   population_size=100,
   offspring_population_size=100,
   ...
   population_evaluator = SequentialEvaluator(),
 )

API

SequentialEvaluator

Bases: Evaluator[S]

Parallel

Solutions can also be evaluated in parallel, using threads or processes:

from jmetal.util.evaluator import MapEvaluator
from jmetal.util.evaluator import MultiprocessEvaluator

jMetalPy also includes evaluators based on Apache Spark and Dask, useful when a single solution evaluation is itself expensive (e.g. simulation-based problems):

from jmetal.util.evaluator import SparkEvaluator

algorithm = NSGAII(
   problem=problem,
   population_size=100,
   offspring_population_size=100,
   ...
   population_evaluator = SparkEvaluator(processes=8),
 )

Or by means of Dask:

from jmetal.util.evaluator import DaskEvaluator

algorithm = NSGAII(
   problem=problem,
   population_size=100,
   offspring_population_size=100,
   ...
   population_evaluator = DaskEvaluator(),
 )

Warning

SparkEvaluator and DaskEvaluator require pySpark and Dask, respectively (install via pip install "jmetalpy[distributed]"). Both currently run against a local Spark/Dask scheduler (local[n]) — they parallelize evaluation across the cores of one machine, not across a cluster, regardless of the processes argument.

API

MapEvaluator(processes=None)

Bases: Evaluator[S]

Source code in src/jmetal/util/evaluator.py
def __init__(self, processes: int = None):
    self.pool = ThreadPool(processes)

MultiprocessEvaluator(processes=None)

Bases: Evaluator[S]

Source code in src/jmetal/util/evaluator.py
def __init__(self, processes: int = None):
    super().__init__()
    self.pool = Pool(processes)

SparkEvaluator(processes=8)

Bases: Evaluator[S]

Source code in src/jmetal/util/evaluator.py
def __init__(self, processes: int = 8):
    self.spark_conf = SparkConf().setAppName("jmetalpy").setMaster(f"local[{processes}]")
    self.spark_context = SparkContext(conf=self.spark_conf)

    logger = self.spark_context._jvm.org.apache.log4j
    logger.LogManager.getLogger("org").setLevel(logger.Level.WARN)

DaskEvaluator(scheduler='processes', number_of_cores=4)

Bases: Evaluator[S]

Source code in src/jmetal/util/evaluator.py
def __init__(self, scheduler="processes", number_of_cores=4):
    self.scheduler = scheduler
    self.number_of_cores = number_of_cores