Skip to content

EMO Pydantic Interface

This page documents the Pydantic interfaces for configuring Evolutionary Multi-Objective Optimization (EMO) algorithms in DESDEO. Essentially, create a complete EMOOptions model by specifying options for the various components of the algorithm. Pass the created model, along with the problem to be solved, to emo_constructor to create an instance of the desired algorithm. Popular pre-configured EMO methods include NSGA-III, RVEA, and IBEA. You can find the actual implementation of these components in the EMO page.

Algorithms

Define popular MOEAs as Pydantic models.

ibea_mixed_integer_options

ibea_mixed_integer_options() -> EMOOptions

Get default IBEA options for mixed integer problems as a Pydantic model.

References

Zitzler, E., Künzli, S. (2004). Indicator-Based Selection in Multiobjective Search. In: Yao, X., et al. Parallel Problem Solving from Nature - PPSN VIII. PPSN 2004. Lecture Notes in Computer Science, vol 3242. Springer, Berlin, Heidelberg. https://doi.org/10.1007/978-3-540-30217-9_84

Returns:

Name Type Description
EMOOptions EMOOptions

The default IBEA mixed integer options as a Pydantic model

Source code in desdeo/emo/options/algorithms.py
def ibea_mixed_integer_options() -> EMOOptions:
    """Get default IBEA options for mixed integer problems as a Pydantic model.

    References:
        Zitzler, E., Künzli, S. (2004). Indicator-Based Selection in Multiobjective Search. In: Yao, X., et al.
        Parallel Problem Solving from Nature - PPSN VIII. PPSN 2004. Lecture Notes in Computer Science, vol 3242.
        Springer, Berlin, Heidelberg. https://doi.org/10.1007/978-3-540-30217-9_84

    Returns:
        EMOOptions: The default IBEA mixed integer options as a Pydantic model
    """
    return EMOOptions(
        preference=None,
        template=Template2Options(
            algorithm_name="IBEA_Mixed_Integer",
            crossover=UniformMixedIntegerCrossoverOptions(),
            mutation=MixedIntegerRandomMutationOptions(),
            selection=IBEASelectorOptions(
                name="IBEASelector",
                binary_indicator="eps",
                kappa=0.05,
                population_size=100,
            ),
            mate_selection=TournamentSelectionOptions(
                name="TournamentSelection",
                tournament_size=2,
                winner_size=100,
            ),
            generator=RandomMixedIntegerGeneratorOptions(n_points=100),
            repair=NoRepairOptions(
                name="NoRepair",
            ),
            termination=MaxGenerationsTerminatorOptions(
                name="MaxGenerationsTerminator",
                max_generations=100,
            ),
            use_archive=True,
            verbosity=2,
            seed=42,
        ),
    )

ibea_options

ibea_options() -> EMOOptions

Get default IBEA options as a Pydantic model.

References

Zitzler, E., Künzli, S. (2004). Indicator-Based Selection in Multiobjective Search. In: Yao, X., et al. Parallel Problem Solving from Nature - PPSN VIII. PPSN 2004. Lecture Notes in Computer Science, vol 3242. Springer, Berlin, Heidelberg. https://doi.org/10.1007/978-3-540-30217-9_84

Returns:

Name Type Description
EMOOptions EMOOptions

The default IBEA options as a Pydantic model.

Source code in desdeo/emo/options/algorithms.py
def ibea_options() -> EMOOptions:
    """Get default IBEA options as a Pydantic model.

    References:
        Zitzler, E., Künzli, S. (2004). Indicator-Based Selection in Multiobjective Search. In: Yao, X., et al.
        Parallel Problem Solving from Nature - PPSN VIII. PPSN 2004. Lecture Notes in Computer Science, vol 3242.
        Springer, Berlin, Heidelberg. https://doi.org/10.1007/978-3-540-30217-9_84

    Returns:
        EMOOptions: The default IBEA options as a Pydantic model.
    """
    return EMOOptions(
        preference=None,
        template=Template2Options(
            algorithm_name="IBEA",
            crossover=SimulatedBinaryCrossoverOptions(
                name="SimulatedBinaryCrossover",
                xover_distribution=20,  # Note that the operator defaults are different in Template2
                xover_probability=0.5,
            ),
            mutation=BoundedPolynomialMutationOptions(
                name="BoundedPolynomialMutation",
                distribution_index=20,
                mutation_probability=0.01,
            ),
            selection=IBEASelectorOptions(
                name="IBEASelector",
                binary_indicator="eps",
                kappa=0.05,
                population_size=100,
            ),
            mate_selection=TournamentSelectionOptions(
                name="TournamentSelection",
                tournament_size=2,
                winner_size=100,
            ),
            generator=LHSGeneratorOptions(
                name="LHSGenerator",
                n_points=100,
            ),
            repair=NoRepairOptions(
                name="NoRepair",
            ),
            termination=MaxGenerationsTerminatorOptions(
                name="MaxGenerationsTerminator",
                max_generations=100,
            ),
            use_archive=True,
            verbosity=2,
            seed=42,
        ),
    )

nsga2_options

nsga2_options() -> EMOOptions

Get default NSGA-II options as a Pydantic model.

Deb, K., Pratap, A., Agarwal, S., & Meyarivan, T. A. M. T.

(2002). A fast and elitist multiobjective genetic algorithm: NSGA-II. IEEE transactions on evolutionary computation, 6(2), 182-197.

Returns:

Name Type Description
EMOOptions EMOOptions

The default NSGA-II options as a Pydantic model.

Source code in desdeo/emo/options/algorithms.py
def nsga2_options() -> EMOOptions:
    """Get default NSGA-II options as a Pydantic model.

    Reference: Deb, K., Pratap, A., Agarwal, S., & Meyarivan, T. A. M. T.
        (2002). A fast and elitist multiobjective genetic algorithm: NSGA-II. IEEE
        transactions on evolutionary computation, 6(2), 182-197.

    Returns:
        EMOOptions: The default NSGA-II options as a Pydantic model.
    """
    return EMOOptions(
        preference=None,
        template=Template2Options(
            algorithm_name="NSGA-II",
            crossover=SimulatedBinaryCrossoverOptions(
                name="SimulatedBinaryCrossover",
                xover_distribution=20,  # Note that the operator defaults are different in Template2
                xover_probability=0.9,
            ),
            mutation=BoundedPolynomialMutationOptions(
                name="BoundedPolynomialMutation",
                distribution_index=20,
                mutation_probability=0.01,
            ),
            selection=NSGA2SelectorOptions(
                name="NSGA2Selector",
                population_size=100,
            ),
            mate_selection=TournamentSelectionOptions(
                name="TournamentSelection",
                tournament_size=2,
                winner_size=100,
            ),
            generator=LHSGeneratorOptions(
                name="LHSGenerator",
                n_points=100,
            ),
            repair=NoRepairOptions(
                name="NoRepair",
            ),
            termination=MaxGenerationsTerminatorOptions(
                name="MaxGenerationsTerminator",
                max_generations=100,
            ),
            use_archive=True,
            verbosity=2,
            seed=42,
        ),
    )

nsga3_mixed_integer_options

nsga3_mixed_integer_options() -> EMOOptions

Get default NSGA3 options for mixed integer problems as a Pydantic model.

References

K. Deb and H. Jain, “An Evolutionary Many-Objective Optimization Algorithm Using Reference-Point-Based Nondominated Sorting Approach, Part I: Solving Problems With Box Constraints,” IEEE Transactions on Evolutionary Computation, vol. 18, no. 4, pp. 577-601, Aug. 2014.

J. Hakanen, T. Chugh, K. Sindhya, Y. Jin, and K. Miettinen, “Connections of reference vectors and different types of preference information in interactive multiobjective evolutionary algorithms,” in 2016 IEEE Symposium Series on Computational Intelligence (SSCI), Athens, Greece: IEEE, Dec. 2016, pp. 1-8.

Returns:

Name Type Description
EMOOptions EMOOptions

The default NSGA3 mixed integer options as a Pydantic model

Source code in desdeo/emo/options/algorithms.py
def nsga3_mixed_integer_options() -> EMOOptions:
    """Get default NSGA3 options for mixed integer problems as a Pydantic model.

    References:
        K. Deb and H. Jain, “An Evolutionary Many-Objective Optimization Algorithm Using Reference-Point-Based
        Nondominated Sorting Approach, Part I: Solving Problems With Box Constraints,” IEEE Transactions on Evolutionary
        Computation, vol. 18, no. 4, pp. 577-601, Aug. 2014.

        J. Hakanen, T. Chugh, K. Sindhya, Y. Jin, and K. Miettinen, “Connections of reference vectors and different
        types of preference information in interactive multiobjective evolutionary algorithms,” in 2016 IEEE Symposium
        Series on Computational Intelligence (SSCI), Athens, Greece: IEEE, Dec. 2016, pp. 1-8.

    Returns:
        EMOOptions: The default NSGA3 mixed integer options as a Pydantic model
    """
    return EMOOptions(
        preference=None,
        template=Template1Options(
            algorithm_name="NSGA3_Mixed_Integer",
            crossover=UniformMixedIntegerCrossoverOptions(),
            mutation=MixedIntegerRandomMutationOptions(),
            selection=NSGA3SelectorOptions(
                name="NSGA3Selector",
                reference_vector_options=ReferenceVectorOptions(
                    adaptation_frequency=0,
                    creation_type="simplex",
                    vector_type="planar",
                    lattice_resolution=None,
                    number_of_vectors=100,
                    adaptation_distance=0.2,
                    reference_point=None,
                    preferred_solutions=None,
                    non_preferred_solutions=None,
                    preferred_ranges=None,
                ),
            ),
            generator=RandomMixedIntegerGeneratorOptions(n_points=100),
            repair=NoRepairOptions(
                name="NoRepair",
            ),
            termination=MaxGenerationsTerminatorOptions(
                name="MaxGenerationsTerminator",
                max_generations=100,
            ),
            use_archive=True,
            verbosity=2,
            seed=42,
        ),
    )

nsga3_options

nsga3_options() -> EMOOptions

Get default NSGA-III options as a Pydantic model.

References

K. Deb and H. Jain, “An Evolutionary Many-Objective Optimization Algorithm Using Reference-Point-Based Nondominated Sorting Approach, Part I: Solving Problems With Box Constraints,” IEEE Transactions on Evolutionary Computation, vol. 18, no. 4, pp. 577-601, Aug. 2014.

J. Hakanen, T. Chugh, K. Sindhya, Y. Jin, and K. Miettinen, “Connections of reference vectors and different types of preference information in interactive multiobjective evolutionary algorithms,” in 2016 IEEE Symposium Series on Computational Intelligence (SSCI), Athens, Greece: IEEE, Dec. 2016, pp. 1-8.

Returns:

Name Type Description
EMOOptions EMOOptions

The default NSGA-III options as a Pydantic model.

Source code in desdeo/emo/options/algorithms.py
def nsga3_options() -> EMOOptions:
    """Get default NSGA-III options as a Pydantic model.

    References:
        K. Deb and H. Jain, “An Evolutionary Many-Objective Optimization Algorithm Using Reference-Point-Based
        Nondominated Sorting Approach, Part I: Solving Problems With Box Constraints,” IEEE Transactions on Evolutionary
        Computation, vol. 18, no. 4, pp. 577-601, Aug. 2014.

        J. Hakanen, T. Chugh, K. Sindhya, Y. Jin, and K. Miettinen, “Connections of reference vectors and different
        types of preference information in interactive multiobjective evolutionary algorithms,” in 2016 IEEE Symposium
        Series on Computational Intelligence (SSCI), Athens, Greece: IEEE, Dec. 2016, pp. 1-8.

    Returns:
        EMOOptions: The default NSGA-III options as a Pydantic model.
    """
    return EMOOptions(
        preference=None,
        template=Template1Options(
            algorithm_name="NSGA3",
            crossover=SimulatedBinaryCrossoverOptions(
                name="SimulatedBinaryCrossover",
                xover_distribution=30,
                xover_probability=0.5,
            ),
            mutation=BoundedPolynomialMutationOptions(
                name="BoundedPolynomialMutation",
                distribution_index=20,
                mutation_probability=None,
            ),
            selection=NSGA3SelectorOptions(
                name="NSGA3Selector",
                reference_vector_options=ReferenceVectorOptions(
                    adaptation_frequency=0,
                    creation_type="simplex",
                    vector_type="planar",
                    lattice_resolution=None,
                    number_of_vectors=100,
                    adaptation_distance=0.2,
                    reference_point=None,
                    preferred_solutions=None,
                    non_preferred_solutions=None,
                    preferred_ranges=None,
                ),
            ),
            generator=LHSGeneratorOptions(
                name="LHSGenerator",
                n_points=100,
            ),
            repair=NoRepairOptions(
                name="NoRepair",
            ),
            termination=MaxGenerationsTerminatorOptions(
                name="MaxGenerationsTerminator",
                max_generations=100,
            ),
            use_archive=True,
            verbosity=2,
            seed=42,
        ),
    )

rvea_mixed_integer_options

rvea_mixed_integer_options() -> EMOOptions

Get default RVEA options for mixed integer problems as a Pydantic model.

References

R. Cheng, Y. Jin, M. Olhofer and B. Sendhoff, "A Reference Vector Guided Evolutionary Algorithm for Many- Objective Optimization," in IEEE Transactions on Evolutionary Computation, vol. 20, no. 5, pp. 773-791, Oct. 2016, doi: 10.1109/TEVC.2016.2519378.

J. Hakanen, T. Chugh, K. Sindhya, Y. Jin, and K. Miettinen, “Connections of reference vectors and different types of preference information in interactive multiobjective evolutionary algorithms,” in 2016 IEEE Symposium Series on Computational Intelligence (SSCI), Athens, Greece: IEEE, Dec. 2016, pp. 1-8.

Returns:

Name Type Description
EMOOptions EMOOptions

The default RVEA mixed integer options as a Pydantic model

Source code in desdeo/emo/options/algorithms.py
def rvea_mixed_integer_options() -> EMOOptions:
    """Get default RVEA options for mixed integer problems as a Pydantic model.

    References:
        R. Cheng, Y. Jin, M. Olhofer and B. Sendhoff, "A Reference Vector Guided Evolutionary Algorithm for Many-
        Objective Optimization," in IEEE Transactions on Evolutionary Computation, vol. 20, no. 5, pp. 773-791,
        Oct. 2016, doi: 10.1109/TEVC.2016.2519378.

        J. Hakanen, T. Chugh, K. Sindhya, Y. Jin, and K. Miettinen, “Connections of reference vectors and different
        types of preference information in interactive multiobjective evolutionary algorithms,” in 2016 IEEE Symposium
        Series on Computational Intelligence (SSCI), Athens, Greece: IEEE, Dec. 2016, pp. 1-8.

    Returns:
        EMOOptions: The default RVEA mixed integer options as a Pydantic model
    """
    return EMOOptions(
        preference=None,
        template=Template1Options(
            algorithm_name="RVEA_Mixed_Integer",
            crossover=UniformMixedIntegerCrossoverOptions(),
            mutation=MixedIntegerRandomMutationOptions(),
            selection=RVEASelectorOptions(
                name="RVEASelector",
                alpha=2,
                parameter_adaptation_strategy=ParameterAdaptationStrategy.GENERATION_BASED,
                reference_vector_options=ReferenceVectorOptions(
                    adaptation_frequency=100,
                    creation_type="simplex",
                    vector_type="spherical",
                    lattice_resolution=None,
                    number_of_vectors=100,
                    adaptation_distance=0.2,
                    reference_point=None,
                    preferred_solutions=None,
                    non_preferred_solutions=None,
                    preferred_ranges=None,
                ),
            ),
            generator=RandomMixedIntegerGeneratorOptions(n_points=100),
            repair=NoRepairOptions(
                name="NoRepair",
            ),
            termination=MaxGenerationsTerminatorOptions(
                name="MaxGenerationsTerminator",
                max_generations=100,
            ),
            use_archive=True,
            verbosity=2,
            seed=42,
        ),
    )

rvea_options

rvea_options() -> EMOOptions

Get default Reference Vector Guided Evolutionary Algorithm (RVEA) options as a Pydantic model.

References

R. Cheng, Y. Jin, M. Olhofer and B. Sendhoff, "A Reference Vector Guided Evolutionary Algorithm for Many- Objective Optimization," in IEEE Transactions on Evolutionary Computation, vol. 20, no. 5, pp. 773-791, Oct. 2016, doi: 10.1109/TEVC.2016.2519378.

J. Hakanen, T. Chugh, K. Sindhya, Y. Jin, and K. Miettinen, “Connections of reference vectors and different types of preference information in interactive multiobjective evolutionary algorithms,” in 2016 IEEE Symposium Series on Computational Intelligence (SSCI), Athens, Greece: IEEE, Dec. 2016, pp. 1-8.

Returns:

Name Type Description
EMOOptions EMOOptions

The default RVEA options as a Pydantic model.

Source code in desdeo/emo/options/algorithms.py
def rvea_options() -> EMOOptions:
    """Get default Reference Vector Guided Evolutionary Algorithm (RVEA) options as a Pydantic model.

    References:
        R. Cheng, Y. Jin, M. Olhofer and B. Sendhoff, "A Reference Vector Guided Evolutionary Algorithm for Many-
        Objective Optimization," in IEEE Transactions on Evolutionary Computation, vol. 20, no. 5, pp. 773-791,
        Oct. 2016, doi: 10.1109/TEVC.2016.2519378.

        J. Hakanen, T. Chugh, K. Sindhya, Y. Jin, and K. Miettinen, “Connections of reference vectors and different
        types of preference information in interactive multiobjective evolutionary algorithms,” in 2016 IEEE Symposium
        Series on Computational Intelligence (SSCI), Athens, Greece: IEEE, Dec. 2016, pp. 1-8.

    Returns:
        EMOOptions: The default RVEA options as a Pydantic model.
    """
    return EMOOptions(
        preference=None,
        template=Template1Options(
            algorithm_name="RVEA",
            crossover=SimulatedBinaryCrossoverOptions(
                name="SimulatedBinaryCrossover",
                xover_distribution=30,
                xover_probability=0.5,
            ),
            mutation=BoundedPolynomialMutationOptions(
                name="BoundedPolynomialMutation",
                distribution_index=20,
                mutation_probability=None,
            ),
            selection=RVEASelectorOptions(
                name="RVEASelector",
                alpha=2,
                parameter_adaptation_strategy=ParameterAdaptationStrategy.GENERATION_BASED,
                reference_vector_options=ReferenceVectorOptions(
                    adaptation_frequency=100,
                    creation_type="simplex",
                    vector_type="spherical",
                    lattice_resolution=None,
                    number_of_vectors=100,
                    adaptation_distance=0.2,
                    reference_point=None,
                    preferred_solutions=None,
                    non_preferred_solutions=None,
                    preferred_ranges=None,
                ),
            ),
            generator=LHSGeneratorOptions(
                name="LHSGenerator",
                n_points=100,
            ),
            repair=NoRepairOptions(
                name="NoRepair",
            ),
            termination=MaxGenerationsTerminatorOptions(
                name="MaxGenerationsTerminator",
                max_generations=100,
            ),
            use_archive=True,
            verbosity=2,
            seed=42,
        ),
    )

Templates

JSON Schema for template options.

BaseTemplateOptions

Bases: BaseModel

Base class for template options.

Source code in desdeo/emo/options/templates.py
class BaseTemplateOptions(BaseModel):
    """Base class for template options."""

    model_config = {"use_attribute_docstrings": True}

    crossover: CrossoverOptions
    """The crossover operator options."""
    mutation: MutationOptions
    """The mutation operator options."""
    selection: SelectorOptions
    """The selection operator options."""
    termination: TerminatorOptions
    """The termination operator options."""
    generator: GeneratorOptions
    """The population generator options."""
    repair: RepairOptions = Field(default=NoRepairOptions())
    """The repair operator options."""
    use_archive: bool = Field(default=True)
    """Whether to use an archive."""
    seed: int = Field(default=0)
    """The seed for random number generation."""
    verbosity: int = Field(default=2)
    """The verbosity level of the operators."""
    algorithm_name: str
    """The unique name of the algorithm."""

algorithm_name instance-attribute

algorithm_name: str

The unique name of the algorithm.

crossover instance-attribute

crossover: CrossoverOptions

The crossover operator options.

generator instance-attribute

generator: GeneratorOptions

The population generator options.

mutation instance-attribute

mutation: MutationOptions

The mutation operator options.

repair class-attribute instance-attribute

repair: RepairOptions = Field(default=NoRepairOptions())

The repair operator options.

seed class-attribute instance-attribute

seed: int = Field(default=0)

The seed for random number generation.

selection instance-attribute

selection: SelectorOptions

The selection operator options.

termination instance-attribute

termination: TerminatorOptions

The termination operator options.

use_archive class-attribute instance-attribute

use_archive: bool = Field(default=True)

Whether to use an archive.

verbosity class-attribute instance-attribute

verbosity: int = Field(default=2)

The verbosity level of the operators.

ConstructorExtras dataclass

Extra information returned by the emo_constructor.

Source code in desdeo/emo/options/templates.py
@dataclass
class ConstructorExtras:
    """Extra information returned by the emo_constructor."""

    problem: Problem
    """New problem generated by the constructor (e.g. to handle preferences via IOPIS). If no new problem is generated,
    the original problem is returned."""
    publisher: Publisher
    """The publisher associated with the current solver."""
    archive: NonDominatedArchive | None
    """The archive associated with the current solver, if any."""

archive instance-attribute

archive: NonDominatedArchive | None

The archive associated with the current solver, if any.

problem instance-attribute

problem: Problem

New problem generated by the constructor (e.g. to handle preferences via IOPIS). If no new problem is generated, the original problem is returned.

publisher instance-attribute

publisher: Publisher

The publisher associated with the current solver.

DesirableRangesOptions

Bases: BaseModel

Options for providing desirable ranges for an EA.

Source code in desdeo/emo/options/templates.py
class DesirableRangesOptions(BaseModel):
    """Options for providing desirable ranges for an EA."""

    name: Literal["preferred_ranges"] = Field(
        default="preferred_ranges", frozen=True, description="The name of the preferred ranges option."
    )
    """The name of the preferred ranges option."""
    aspiration_levels: dict[str, float] = Field(
        description="The aspiration levels as a dictionary with objective function symbols as the keys."
    )
    """The aspiration levels as a dictionary with objective function symbols as the keys."""
    reservation_levels: dict[str, float] = Field(
        description="The reservation levels as a dictionary with objective function symbols as the keys."
    )
    """The reservation levels as a dictionary with objective function symbols as the keys."""
    method: Literal["Hakanen", "DF transformation"] = Field(
        default="Hakanen", description="The method for handling the desirable ranges."
    )
    """The method for handling the desirable ranges."""
    desirability_levels: tuple[float, float] = Field(
        default=(0.9, 0.1),
        description=(
            "The desirability levels as a tuple (high, low). Used if method is DF transformation."
            " If None, default levels (0.9, 0.1) are used."
        ),
    )

aspiration_levels class-attribute instance-attribute

aspiration_levels: dict[str, float] = Field(
    description="The aspiration levels as a dictionary with objective function symbols as the keys."
)

The aspiration levels as a dictionary with objective function symbols as the keys.

method class-attribute instance-attribute

method: Literal["Hakanen", "DF transformation"] = Field(
    default="Hakanen",
    description="The method for handling the desirable ranges.",
)

The method for handling the desirable ranges.

name class-attribute instance-attribute

name: Literal["preferred_ranges"] = Field(
    default="preferred_ranges",
    frozen=True,
    description="The name of the preferred ranges option.",
)

The name of the preferred ranges option.

reservation_levels class-attribute instance-attribute

reservation_levels: dict[str, float] = Field(
    description="The reservation levels as a dictionary with objective function symbols as the keys."
)

The reservation levels as a dictionary with objective function symbols as the keys.

EMOOptions

Bases: BaseModel

Options for configuring the EMO algorithm.

Source code in desdeo/emo/options/templates.py
class EMOOptions(BaseModel):
    """Options for configuring the EMO algorithm."""

    model_config = {"use_attribute_docstrings": True}

    preference: PreferenceOptions | None
    """The preference information for the EMO algorithm."""
    template: TemplateOptions
    """The template options for the EMO algorithm."""

preference instance-attribute

preference: PreferenceOptions | None

The preference information for the EMO algorithm.

template instance-attribute

template: TemplateOptions

The template options for the EMO algorithm.

InvalidTemplateError

Bases: Exception

Exception raised for invalid template configurations.

Source code in desdeo/emo/options/templates.py
class InvalidTemplateError(Exception):
    """Exception raised for invalid template configurations."""

NonPreferredSolutionsOptions

Bases: BaseModel

Options for providing non-preferred solutions for an EA.

Source code in desdeo/emo/options/templates.py
class NonPreferredSolutionsOptions(BaseModel):
    """Options for providing non-preferred solutions for an EA."""

    name: Literal["non_preferred_solutions"] = Field(
        default="non_preferred_solutions", frozen=True, description="The name of the non-preferred solutions option."
    )
    """The name of the non-preferred solutions option."""
    preference: dict[str, list[float]] = Field(
        description="The non-preferred solutions as a dictionary with objective function symbols as the keys."
    )
    """The non-preferred solutions as a dictionary with objective function symbols as the keys."""
    method: Literal["Hakanen"] = Field(
        default="Hakanen", description="The method for handling the non-preferred solutions."
    )
    """The method for handling the non-preferred solutions."""

method class-attribute instance-attribute

method: Literal["Hakanen"] = Field(
    default="Hakanen",
    description="The method for handling the non-preferred solutions.",
)

The method for handling the non-preferred solutions.

name class-attribute instance-attribute

name: Literal["non_preferred_solutions"] = Field(
    default="non_preferred_solutions",
    frozen=True,
    description="The name of the non-preferred solutions option.",
)

The name of the non-preferred solutions option.

preference class-attribute instance-attribute

preference: dict[str, list[float]] = Field(
    description="The non-preferred solutions as a dictionary with objective function symbols as the keys."
)

The non-preferred solutions as a dictionary with objective function symbols as the keys.

PreferredSolutionsOptions

Bases: BaseModel

Options for providing preferred solutions for an EA.

Source code in desdeo/emo/options/templates.py
class PreferredSolutionsOptions(BaseModel):
    """Options for providing preferred solutions for an EA."""

    name: Literal["preferred_solutions"] = Field(
        default="preferred_solutions", frozen=True, description="The name of the preferred solutions option."
    )
    """The name of the preferred solutions option."""
    preference: dict[str, list[float]] = Field(
        description="The preferred solutions as a dictionary with objective function symbols as the keys."
    )
    """The preferred solutions as a dictionary with objective function symbols as the keys."""
    method: Literal["Hakanen"] = Field(
        default="Hakanen", description="The method for handling the preferred solutions."
    )
    """The method for handling the preferred solutions."""

method class-attribute instance-attribute

method: Literal["Hakanen"] = Field(
    default="Hakanen",
    description="The method for handling the preferred solutions.",
)

The method for handling the preferred solutions.

name class-attribute instance-attribute

name: Literal["preferred_solutions"] = Field(
    default="preferred_solutions",
    frozen=True,
    description="The name of the preferred solutions option.",
)

The name of the preferred solutions option.

preference class-attribute instance-attribute

preference: dict[str, list[float]] = Field(
    description="The preferred solutions as a dictionary with objective function symbols as the keys."
)

The preferred solutions as a dictionary with objective function symbols as the keys.

ReferencePointOptions

Bases: BaseModel

Options for providing a reference point for an EA.

Source code in desdeo/emo/options/templates.py
class ReferencePointOptions(BaseModel):
    """Options for providing a reference point for an EA."""

    name: Literal["reference_point"] = Field(
        default="reference_point", frozen=True, description="The name of the reference point option."
    )
    """The name of the reference point option."""
    preference: dict[str, float] = Field(
        description="The reference point as a dictionary with objective function symbols as the keys."
    )
    """The reference point as a dictionary with objective function symbols as the keys."""
    method: Literal["Hakanen", "IOPIS"] = Field(
        default="Hakanen", description="The method for handling the reference point."
    )
    """The method for handling the reference point."""

method class-attribute instance-attribute

method: Literal["Hakanen", "IOPIS"] = Field(
    default="Hakanen",
    description="The method for handling the reference point.",
)

The method for handling the reference point.

name class-attribute instance-attribute

name: Literal["reference_point"] = Field(
    default="reference_point",
    frozen=True,
    description="The name of the reference point option.",
)

The name of the reference point option.

preference class-attribute instance-attribute

preference: dict[str, float] = Field(
    description="The reference point as a dictionary with objective function symbols as the keys."
)

The reference point as a dictionary with objective function symbols as the keys.

Template1Options

Bases: BaseTemplateOptions

Options for template 1.

Template 1 is used by methods such as NSGA-III and RVEA. See template1 for more details.

Source code in desdeo/emo/options/templates.py
class Template1Options(BaseTemplateOptions):
    """Options for template 1.

    Template 1 is used by methods such as NSGA-III and RVEA. See
    [template1][desdeo.emo.methods.templates.template1] for
    more details.
    """

    name: Literal["Template1"] = Field(default="Template1", frozen=True, description="The name of the template.")
    """The name of the template."""

name class-attribute instance-attribute

name: Literal["Template1"] = Field(
    default="Template1",
    frozen=True,
    description="The name of the template.",
)

The name of the template.

Template2Options

Bases: BaseTemplateOptions

Options for template 2.

Template 2 is used by methods such as IBEA. See template2 for more details.

Source code in desdeo/emo/options/templates.py
class Template2Options(BaseTemplateOptions):
    """Options for template 2.

    Template 2 is used by methods such as IBEA. See
    [template2][desdeo.emo.methods.templates.template2] for
    more details.
    """

    name: Literal["Template2"] = Field(default="Template2", frozen=True, description="The name of the template.")
    """The name of the template."""
    mate_selection: ScalarSelectionOptions = Field(description="The mate selection operator options.")

name class-attribute instance-attribute

name: Literal["Template2"] = Field(
    default="Template2",
    frozen=True,
    description="The name of the template.",
)

The name of the template.

emo_constructor

emo_constructor(
    emo_options: EMOOptions,
    problem: Problem,
    external_check: Callable[[], bool] | None = None,
) -> tuple[Callable[[], EMOResult], ConstructorExtras]

Construct an evolutionary algorithm from the given options.

Parameters:

Name Type Description Default
emo_options EMOOptions

The options for the EMO algorithm.

required
problem Problem

The optimization problem to solve.

required
external_check Callable[[], bool] | None

A callable that returns True if the algorithm should stop, False otherwise. By default, None.

None

Returns:

Type Description
Callable[[], EMOResult]

tuple[Callable[[], EMOResult], ConstructorExtras]: A tuple containing the template function

ConstructorExtras

and extra information such as the (possibly modified) problem, publisher, and archive. Run the template

tuple[Callable[[], EMOResult], ConstructorExtras]

function to execute the algorithm.

Raises:

Type Description
InvalidTemplateError

If the template configuration is invalid.

Source code in desdeo/emo/options/templates.py
def emo_constructor(
    emo_options: EMOOptions, problem: Problem, external_check: Callable[[], bool] | None = None
) -> tuple[Callable[[], EMOResult], ConstructorExtras]:
    """Construct an evolutionary algorithm from the given options.

    Args:
        emo_options (EMOOptions): The options for the EMO algorithm.
        problem (Problem): The optimization problem to solve.
        external_check (Callable[[], bool] | None): A callable that returns True if the algorithm should stop,
            False otherwise. By default, None.

    Returns:
        tuple[Callable[[], EMOResult], ConstructorExtras]: A tuple containing the template function
        and extra information such as the (possibly modified) problem, publisher, and archive. Run the template
        function to execute the algorithm.

    Raises:
        InvalidTemplateError: If the template configuration is invalid.
    """
    publisher = Publisher()

    template = emo_options.template

    problem_, selector_options = preference_handler(
        preference=emo_options.preference, problem=problem, selection=template.selection
    )

    evaluator = EMOEvaluator(problem=problem_, publisher=publisher, verbosity=template.verbosity)

    selector = selection_constructor(
        problem=problem_,
        options=selector_options,
        publisher=publisher,
        verbosity=template.verbosity,
        seed=template.seed,
    )

    generator = generator_constructor(
        problem=problem_,
        options=template.generator,
        evaluator=evaluator,
        publisher=publisher,
        verbosity=template.verbosity,
        seed=template.seed,
    )

    crossover = crossover_constructor(
        problem=problem_,
        options=template.crossover,
        publisher=publisher,
        verbosity=template.verbosity,
        seed=template.seed,
    )

    mutation = mutation_constructor(
        problem=problem_,
        options=template.mutation,
        publisher=publisher,
        verbosity=template.verbosity,
        seed=template.seed,
    )

    terminator = terminator_constructor(
        options=template.termination,
        publisher=publisher,
        external_check=external_check,
    )

    repair = repair_constructor(options=template.repair, problem=problem_)

    components = {
        "evaluator": evaluator,
        "generator": generator,
        "crossover": crossover,
        "mutation": mutation,
        "selection": selector,
        "terminator": terminator,
    }

    if template.use_archive:
        archive = NonDominatedArchive(
            problem=problem_,
            publisher=publisher,
        )
        components["archive"] = archive

    if template.name == "Template2":
        scalar_selector = scalar_selector_constructor(
            options=template.mate_selection,
            publisher=publisher,
            verbosity=template.verbosity,
            seed=template.seed,
        )
        components["mate_selection"] = scalar_selector

    [publisher.auto_subscribe(x) for x in components.values()]
    [publisher.register_topics(x.provided_topics[x.verbosity], x.__class__.__name__) for x in components.values()]

    consistency = publisher.check_consistency()

    if not consistency[0]:
        raise InvalidTemplateError(f"Inconsistent template configuration. See details:\n {consistency[1]}")
    archive = components.pop("archive", None)
    template_funcs = {
        "Template1": template1,
        "Template2": template2,
    }

    constructor_extras = ConstructorExtras(problem=problem_, publisher=publisher, archive=archive)

    return (partial(template_funcs[template.name], **components, repair=repair), constructor_extras)

preference_handler

preference_handler(
    preference: PreferenceOptions | None,
    problem: Problem,
    selection: SelectorOptions,
) -> tuple[Problem, SelectorOptions]

Handle the preference options for the EMO algorithm.

This function modifies the problem and selection operator based on the provided preference options. E.g., if the preference method is "Hakanen", the reference vector options of the selection operator are modified to include the preference information. If the preference method is "IOPIS" or "DF transformation", the problem is modified to include desirability functions or IOPIS functions.

Parameters:

Name Type Description Default
preference PreferenceOptions | None

The preference options.

required
problem Problem

The optimization problem.

required
selection SelectorOptions

The selection operator options.

required

Returns:

Type Description
tuple[Problem, SelectorOptions]

tuple[Problem, SelectorOptions]: The (modified, if necessary) problem and selection operator options.

Raises:

Type Description
InvalidTemplateError

If the preference handling method is incompatible with the selection operator.

Source code in desdeo/emo/options/templates.py
def preference_handler(
    preference: PreferenceOptions | None, problem: Problem, selection: SelectorOptions
) -> tuple[Problem, SelectorOptions]:
    """Handle the preference options for the EMO algorithm.

    This function modifies the problem and selection operator based on the provided preference options. E.g., if
    the preference method is "Hakanen", the reference vector options of the selection operator are modified to
    include the preference information. If the preference method is "IOPIS" or "DF transformation", the problem is
    modified to include desirability functions or IOPIS functions.

    Args:
        preference (PreferenceOptions | None): The preference options.
        problem (Problem): The optimization problem.
        selection (SelectorOptions): The selection operator options.

    Returns:
        tuple[Problem, SelectorOptions]: The (modified, if necessary) problem and selection operator options.

    Raises:
        InvalidTemplateError: If the preference handling method is incompatible with the selection operator.
    """
    if preference is None:
        return problem, selection

    if preference.method == "Hakanen":
        if "reference_vector_options" not in type(selection).model_fields:
            raise InvalidTemplateError(
                "Preference handling with Hakanen method requires a selection operator with reference vectors."
            )
        if selection.name == "IBEASelector":  # Technically not needed due to check above, but for shutting up linters
            raise InvalidTemplateError("Preference handling with Hakanen method is not supported for IBEASelector.")
        if selection.reference_vector_options is None:
            reference_vector_options = ReferenceVectorOptions()  # Use default reference vector options
        else:
            reference_vector_options = selection.reference_vector_options
        if isinstance(preference, DesirableRangesOptions):
            preference_value = {
                obj.symbol: [preference.aspiration_levels[obj.symbol], preference.reservation_levels[obj.symbol]]
                for obj in problem.objectives
            }
        else:
            preference_value = preference.preference
        setattr(reference_vector_options, preference.name, preference_value)
        selection.reference_vector_options = reference_vector_options
        return problem, selection
    if preference.method == "IOPIS":
        iopis_problem, _ = add_iopis_funcs(
            problem=problem,
            reference_point=preference.preference,
        )
        return iopis_problem, selection
    if preference.method == "DF transformation":
        df_problem, _ = add_desirability_funcs(
            problem=problem,
            aspiration_levels=preference.aspiration_levels,
            reservation_levels=preference.reservation_levels,
            desirability_levels={name: preference.desirability_levels for name in preference.aspiration_levels},
            desirability_func="MaoMao",
        )
        return df_problem, selection
    raise InvalidTemplateError(f"Unknown preference handling method: {preference.method}")

Crossover Operators

JSON Schema for crossover operator options.

BlendAlphaCrossoverOptions

Bases: BaseModel

Options for Blend Alpha Crossover.

Source code in desdeo/emo/options/crossover.py
class BlendAlphaCrossoverOptions(BaseModel):
    """Options for Blend Alpha Crossover."""

    name: Literal["BlendAlphaCrossover"] = Field(
        default="BlendAlphaCrossover", frozen=True, description="The name of the crossover operator."
    )
    """The name of the crossover operator."""
    alpha: float = Field(
        default=0.5,
        ge=0.0,
        description=(
            "Non-negative blending factor 'alpha' that controls the extent to which offspring"
            " may be sampled outside the interval defined by each pair of parent genes. "
            "alpha = 0 restricts children strictly within the parents range, larger alpha allows some outliers."
        ),
    )
    """
    Non-negative blending factor 'alpha' that controls the extent to which offspring
    may be sampled outside the interval defined by each pair of parent genes.
    alpha = 0 restricts children strictly within the parents range, larger alpha allows some outliers.
    """
    xover_probability: float = Field(default=1.0, ge=0.0, le=1.0)

alpha class-attribute instance-attribute

alpha: float = Field(
    default=0.5,
    ge=0.0,
    description="Non-negative blending factor 'alpha' that controls the extent to which offspring may be sampled outside the interval defined by each pair of parent genes. alpha = 0 restricts children strictly within the parents range, larger alpha allows some outliers.",
)

Non-negative blending factor 'alpha' that controls the extent to which offspring may be sampled outside the interval defined by each pair of parent genes. alpha = 0 restricts children strictly within the parents range, larger alpha allows some outliers.

name class-attribute instance-attribute

name: Literal["BlendAlphaCrossover"] = Field(
    default="BlendAlphaCrossover",
    frozen=True,
    description="The name of the crossover operator.",
)

The name of the crossover operator.

BoundedExponentialCrossoverOptions

Bases: BaseModel

Options for Bounded Exponential Crossover.

Source code in desdeo/emo/options/crossover.py
class BoundedExponentialCrossoverOptions(BaseModel):
    """Options for Bounded Exponential Crossover."""

    name: Literal["BoundedExponentialCrossover"] = Field(
        default="BoundedExponentialCrossover", frozen=True, description="The name of the crossover operator."
    )
    """The name of the crossover operator."""
    xover_probability: float = Field(default=1.0, ge=0.0, le=1.0, description="The crossover probability.")
    """The crossover probability."""
    lambda_: float = Field(default=1.0, gt=0.0, description="Positive scale λ for the exponential distribution.")
    """Positive scale λ for the exponential distribution."""

lambda_ class-attribute instance-attribute

lambda_: float = Field(
    default=1.0,
    gt=0.0,
    description="Positive scale λ for the exponential distribution.",
)

Positive scale λ for the exponential distribution.

name class-attribute instance-attribute

name: Literal["BoundedExponentialCrossover"] = Field(
    default="BoundedExponentialCrossover",
    frozen=True,
    description="The name of the crossover operator.",
)

The name of the crossover operator.

xover_probability class-attribute instance-attribute

xover_probability: float = Field(
    default=1.0,
    ge=0.0,
    le=1.0,
    description="The crossover probability.",
)

The crossover probability.

LocalCrossoverOptions

Bases: BaseModel

Options for Local Crossover.

Source code in desdeo/emo/options/crossover.py
class LocalCrossoverOptions(BaseModel):
    """Options for Local Crossover."""

    name: Literal["LocalCrossover"] = Field(
        default="LocalCrossover", frozen=True, description="The name of the crossover operator."
    )
    """The name of the crossover operator."""
    xover_probability: float = Field(default=1.0, ge=0.0, le=1.0, description="The crossover probability.")
    """The crossover probability."""

name class-attribute instance-attribute

name: Literal["LocalCrossover"] = Field(
    default="LocalCrossover",
    frozen=True,
    description="The name of the crossover operator.",
)

The name of the crossover operator.

xover_probability class-attribute instance-attribute

xover_probability: float = Field(
    default=1.0,
    ge=0.0,
    le=1.0,
    description="The crossover probability.",
)

The crossover probability.

SimulatedBinaryCrossoverOptions

Bases: BaseModel

Options for Simulated Binary Crossover (SBX).

Source code in desdeo/emo/options/crossover.py
class SimulatedBinaryCrossoverOptions(BaseModel):
    """Options for Simulated Binary Crossover (SBX)."""

    name: Literal["SimulatedBinaryCrossover"] = Field(
        default="SimulatedBinaryCrossover", frozen=True, description="The name of the crossover operator."
    )
    """The name of the crossover operator."""
    xover_probability: float = Field(default=0.5, ge=0.0, le=1.0, description="The SBX crossover probability.")
    """The SBX crossover probability."""
    xover_distribution: float = Field(default=30.0, gt=0.0, description="The SBX distribution index.")
    """The SBX distribution index."""

name class-attribute instance-attribute

name: Literal["SimulatedBinaryCrossover"] = Field(
    default="SimulatedBinaryCrossover",
    frozen=True,
    description="The name of the crossover operator.",
)

The name of the crossover operator.

xover_distribution class-attribute instance-attribute

xover_distribution: float = Field(
    default=30.0,
    gt=0.0,
    description="The SBX distribution index.",
)

The SBX distribution index.

xover_probability class-attribute instance-attribute

xover_probability: float = Field(
    default=0.5,
    ge=0.0,
    le=1.0,
    description="The SBX crossover probability.",
)

The SBX crossover probability.

SingleArithmeticCrossoverOptions

Bases: BaseModel

Options for Single Arithmetic Crossover.

Source code in desdeo/emo/options/crossover.py
class SingleArithmeticCrossoverOptions(BaseModel):
    """Options for Single Arithmetic Crossover."""

    name: Literal["SingleArithmeticCrossover"] = Field(
        default="SingleArithmeticCrossover", frozen=True, description="The name of the crossover operator."
    )
    """The name of the crossover operator."""
    xover_probability: float = Field(default=1.0, ge=0.0, le=1.0, description="The crossover probability.")
    """The crossover probability."""

name class-attribute instance-attribute

name: Literal["SingleArithmeticCrossover"] = Field(
    default="SingleArithmeticCrossover",
    frozen=True,
    description="The name of the crossover operator.",
)

The name of the crossover operator.

xover_probability class-attribute instance-attribute

xover_probability: float = Field(
    default=1.0,
    ge=0.0,
    le=1.0,
    description="The crossover probability.",
)

The crossover probability.

SinglePointBinaryCrossoverOptions

Bases: BaseModel

Options for Single Point Binary Crossover.

Source code in desdeo/emo/options/crossover.py
class SinglePointBinaryCrossoverOptions(BaseModel):
    """Options for Single Point Binary Crossover."""

    name: Literal["SinglePointBinaryCrossover"] = Field(
        default="SinglePointBinaryCrossover", frozen=True, description="The name of the crossover operator."
    )
    """The name of the crossover operator."""

name class-attribute instance-attribute

name: Literal["SinglePointBinaryCrossover"] = Field(
    default="SinglePointBinaryCrossover",
    frozen=True,
    description="The name of the crossover operator.",
)

The name of the crossover operator.

UniformIntegerCrossoverOptions

Bases: BaseModel

Options for Uniform Integer Crossover.

Source code in desdeo/emo/options/crossover.py
class UniformIntegerCrossoverOptions(BaseModel):
    """Options for Uniform Integer Crossover."""

    name: Literal["UniformIntegerCrossover"] = Field(
        default="UniformIntegerCrossover", frozen=True, description="The name of the crossover operator."
    )
    """The name of the crossover operator."""

name class-attribute instance-attribute

name: Literal["UniformIntegerCrossover"] = Field(
    default="UniformIntegerCrossover",
    frozen=True,
    description="The name of the crossover operator.",
)

The name of the crossover operator.

UniformMixedIntegerCrossoverOptions

Bases: BaseModel

Options for Uniform Mixed Integer Crossover.

Source code in desdeo/emo/options/crossover.py
class UniformMixedIntegerCrossoverOptions(BaseModel):
    """Options for Uniform Mixed Integer Crossover."""

    name: Literal["UniformMixedIntegerCrossover"] = Field(
        default="UniformMixedIntegerCrossover", frozen=True, description="The name of the crossover operator."
    )
    """The name of the crossover operator."""

name class-attribute instance-attribute

name: Literal["UniformMixedIntegerCrossover"] = Field(
    default="UniformMixedIntegerCrossover",
    frozen=True,
    description="The name of the crossover operator.",
)

The name of the crossover operator.

crossover_constructor

crossover_constructor(
    problem: Problem,
    publisher: Publisher,
    seed: int,
    verbosity: int,
    options: CrossoverOptions,
) -> BaseCrossover

Construct a crossover operator.

Parameters:

Name Type Description Default
problem Problem

The optimization problem to solve.

required
publisher Publisher

The publisher for communication.

required
seed int

The random seed for reproducibility.

required
verbosity int

The verbosity level of the output.

required
options CrossoverOptions

The options for the crossover operator.

required

Returns:

Name Type Description
BaseCrossover BaseCrossover

The constructed crossover operator.

Source code in desdeo/emo/options/crossover.py
def crossover_constructor(
    problem: Problem, publisher: Publisher, seed: int, verbosity: int, options: CrossoverOptions
) -> BaseCrossover:
    """Construct a crossover operator.

    Args:
        problem (Problem): The optimization problem to solve.
        publisher (Publisher): The publisher for communication.
        seed (int): The random seed for reproducibility.
        verbosity (int): The verbosity level of the output.
        options (CrossoverOptions): The options for the crossover operator.

    Returns:
        BaseCrossover: The constructed crossover operator.
    """
    crossover_types = {
        "SimulatedBinaryCrossover": SimulatedBinaryCrossover,
        "SinglePointBinaryCrossover": SinglePointBinaryCrossover,
        "UniformIntegerCrossover": UniformIntegerCrossover,
        "UniformMixedIntegerCrossover": UniformMixedIntegerCrossover,
        "BlendAlphaCrossover": BlendAlphaCrossover,
        "SingleArithmeticCrossover": SingleArithmeticCrossover,
        "LocalCrossover": LocalCrossover,
        "BoundedExponentialCrossover": BoundedExponentialCrossover,
    }
    options = options.model_dump()
    name = options.pop("name")
    return crossover_types[name](problem=problem, publisher=publisher, seed=seed, verbosity=verbosity, **dict(options))

Generator Operators

JSON Schema for generator options.

ArchiveGeneratorOptions

Bases: BaseModel

Options for Archive generator.

Source code in desdeo/emo/options/generator.py
class ArchiveGeneratorOptions(BaseModel):
    """Options for Archive generator."""

    model_config = {"arbitrary_types_allowed": True, "use_attribute_docstrings": True}

    name: Literal["ArchiveGenerator"] = "ArchiveGenerator"
    """The name of the generator."""
    solutions: pl.DataFrame
    """The initial solutions to populate the archive with."""
    outputs: pl.DataFrame
    """The corresponding outputs of the initial solutions."""

name class-attribute instance-attribute

name: Literal['ArchiveGenerator'] = 'ArchiveGenerator'

The name of the generator.

outputs instance-attribute

outputs: DataFrame

The corresponding outputs of the initial solutions.

solutions instance-attribute

solutions: DataFrame

The initial solutions to populate the archive with.

BaseGeneratorOptions

Bases: BaseModel

Options for all generators.

Source code in desdeo/emo/options/generator.py
class BaseGeneratorOptions(BaseModel):
    """Options for all generators."""

    n_points: int = Field(gt=0, description="The number of points to generate for the initial population.")
    """The number of points to generate for the initial population."""

n_points class-attribute instance-attribute

n_points: int = Field(
    gt=0,
    description="The number of points to generate for the initial population.",
)

The number of points to generate for the initial population.

LHSGeneratorOptions

Bases: BaseGeneratorOptions

Options for Latin Hypercube Sampling (LHS) generator.

Source code in desdeo/emo/options/generator.py
class LHSGeneratorOptions(BaseGeneratorOptions):
    """Options for Latin Hypercube Sampling (LHS) generator."""

    name: Literal["LHSGenerator"] = Field(default="LHSGenerator", frozen=True, description="The name of the generator.")
    """The name of the generator."""

name class-attribute instance-attribute

name: Literal["LHSGenerator"] = Field(
    default="LHSGenerator",
    frozen=True,
    description="The name of the generator.",
)

The name of the generator.

RandomBinaryGeneratorOptions

Bases: BaseGeneratorOptions

Options for Random Binary generator.

Source code in desdeo/emo/options/generator.py
class RandomBinaryGeneratorOptions(BaseGeneratorOptions):
    """Options for Random Binary generator."""

    name: Literal["RandomBinaryGenerator"] = Field(
        default="RandomBinaryGenerator", frozen=True, description="The name of the generator."
    )
    """The name of the generator."""

name class-attribute instance-attribute

name: Literal["RandomBinaryGenerator"] = Field(
    default="RandomBinaryGenerator",
    frozen=True,
    description="The name of the generator.",
)

The name of the generator.

RandomGeneratorOptions

Bases: BaseGeneratorOptions

Options for Random generator.

Source code in desdeo/emo/options/generator.py
class RandomGeneratorOptions(BaseGeneratorOptions):
    """Options for Random generator."""

    name: Literal["RandomGenerator"] = Field(
        default="RandomGenerator", frozen=True, description="The name of the generator."
    )
    """The name of the generator."""

name class-attribute instance-attribute

name: Literal["RandomGenerator"] = Field(
    default="RandomGenerator",
    frozen=True,
    description="The name of the generator.",
)

The name of the generator.

RandomIntegerGeneratorOptions

Bases: BaseGeneratorOptions

Options for Random Integer generator.

Source code in desdeo/emo/options/generator.py
class RandomIntegerGeneratorOptions(BaseGeneratorOptions):
    """Options for Random Integer generator."""

    name: Literal["RandomIntegerGenerator"] = Field(
        default="RandomIntegerGenerator", frozen=True, description="The name of the generator."
    )
    """The name of the generator."""

name class-attribute instance-attribute

name: Literal["RandomIntegerGenerator"] = Field(
    default="RandomIntegerGenerator",
    frozen=True,
    description="The name of the generator.",
)

The name of the generator.

RandomMixedIntegerGeneratorOptions

Bases: BaseGeneratorOptions

Options for Random Mixed Integer generator.

Source code in desdeo/emo/options/generator.py
class RandomMixedIntegerGeneratorOptions(BaseGeneratorOptions):
    """Options for Random Mixed Integer generator."""

    name: Literal["RandomMixedIntegerGenerator"] = Field(
        default="RandomMixedIntegerGenerator", frozen=True, description="The name of the generator."
    )
    """The name of the generator."""

name class-attribute instance-attribute

name: Literal["RandomMixedIntegerGenerator"] = Field(
    default="RandomMixedIntegerGenerator",
    frozen=True,
    description="The name of the generator.",
)

The name of the generator.

SeededHybridGeneratorOptions

Bases: BaseGeneratorOptions

Options for the seeded hybrid generator.

Source code in desdeo/emo/options/generator.py
class SeededHybridGeneratorOptions(BaseGeneratorOptions):
    """Options for the seeded hybrid generator."""

    name: Literal["SeededHybridGenerator"] = Field(default="SeededHybridGenerator", frozen=True)
    model_config = {"arbitrary_types_allowed": True, "use_attribute_docstrings": True}

    seed_solution: pl.DataFrame
    """A dataframe with a single row representing the solution seed. The columns
    must math the symbols of the variables in the problem being solved.
    """
    perturb_fraction: float = Field(default=0.2, ge=0.0, le=1.0)
    """The desired fraction of perturbed vs random solutions in the generated population."""

    sigma: float = Field(default=0.02, ge=0.0)
    """The relative perturbation scale with respect to variable ranges."""

    flip_prob: float = Field(default=0.1, ge=0.0, le=1.0)
    """The flipping probability when perturbing binary variables."""

flip_prob class-attribute instance-attribute

flip_prob: float = Field(default=0.1, ge=0.0, le=1.0)

The flipping probability when perturbing binary variables.

perturb_fraction class-attribute instance-attribute

perturb_fraction: float = Field(default=0.2, ge=0.0, le=1.0)

The desired fraction of perturbed vs random solutions in the generated population.

seed_solution instance-attribute

seed_solution: DataFrame

A dataframe with a single row representing the solution seed. The columns must math the symbols of the variables in the problem being solved.

sigma class-attribute instance-attribute

sigma: float = Field(default=0.02, ge=0.0)

The relative perturbation scale with respect to variable ranges.

generator_constructor

generator_constructor(
    problem: Problem,
    options: GeneratorOptions,
    publisher: Publisher,
    verbosity: int,
    seed: int,
    evaluator: EMOEvaluator,
) -> BaseGenerator

Construct a generator based on the provided options.

Parameters:

Name Type Description Default
problem Problem

The optimization problem to solve.

required
options GeneratorOptions

The options for the generator.

required
publisher Publisher

The publisher for the generator.

required
verbosity int

The verbosity level for the generator.

required
seed int

The random seed for the generator.

required
evaluator EMOEvaluator

The evaluator to use for evaluating solutions.

required

Returns:

Name Type Description
BaseGenerator BaseGenerator

The constructed generator.

Source code in desdeo/emo/options/generator.py
def generator_constructor(
    problem: Problem,
    options: GeneratorOptions,
    publisher: Publisher,
    verbosity: int,
    seed: int,
    evaluator: EMOEvaluator,
) -> BaseGenerator:
    """Construct a generator based on the provided options.

    Args:
        problem (Problem): The optimization problem to solve.
        options (GeneratorOptions): The options for the generator.
        publisher (Publisher): The publisher for the generator.
        verbosity (int): The verbosity level for the generator.
        seed (int): The random seed for the generator.
        evaluator (EMOEvaluator): The evaluator to use for evaluating solutions.

    Returns:
        BaseGenerator: The constructed generator.
    """
    generator_types = {
        "LHSGenerator": LHSGenerator,
        "RandomBinaryGenerator": RandomBinaryGenerator,
        "RandomGenerator": RandomGenerator,
        "RandomIntegerGenerator": RandomIntegerGenerator,
        "RandomMixedIntegerGenerator": RandomMixedIntegerGenerator,
        "ArchiveGenerator": ArchiveGenerator,
        "SeededHybridGenerator": SeededHybridGenerator,
    }
    options: dict = options.model_dump()
    name = options.pop("name")
    return generator_types[name](
        problem, **options, publisher=publisher, verbosity=verbosity, seed=seed, evaluator=evaluator
    )

Mutation Operators

JSON Schema for mutation operator options.

MutationOptions module-attribute

MutationOptions = (
    BoundedPolynomialMutationOptions
    | BinaryFlipMutationOptions
    | IntegerRandomMutationOptions
    | MixedIntegerRandomMutationOptions
    | MPTMutationOptions
    | NonUniformMutationOptions
    | SelfAdaptiveGaussianMutationOptions
    | PowerMutationOptions
)

All possible mutation operator options.

BinaryFlipMutationOptions

Bases: BaseModel

Options for Binary Flip Mutation.

Source code in desdeo/emo/options/mutation.py
class BinaryFlipMutationOptions(BaseModel):
    """Options for Binary Flip Mutation."""

    name: Literal["BinaryFlipMutation"] = Field(
        default="BinaryFlipMutation", frozen=True, description="The name of the mutation operator."
    )
    """The name of the mutation operator."""
    mutation_probability: float | None = Field(
        default=None,
        ge=0.0,
        le=1.0,
        description=(
            "The probability of mutation. Defaults to None, which sets the "
            "mutation probability to 1/<number of decision variables>."
        ),
    )
    """
    The probability of mutation. Defaults to None, which sets the mutation probability to
    1/<number of decision variables>.
    """

mutation_probability class-attribute instance-attribute

mutation_probability: float | None = Field(
    default=None,
    ge=0.0,
    le=1.0,
    description="The probability of mutation. Defaults to None, which sets the mutation probability to 1/<number of decision variables>.",
)

The probability of mutation. Defaults to None, which sets the mutation probability to 1/.

name class-attribute instance-attribute

name: Literal["BinaryFlipMutation"] = Field(
    default="BinaryFlipMutation",
    frozen=True,
    description="The name of the mutation operator.",
)

The name of the mutation operator.

BoundedPolynomialMutationOptions

Bases: BaseModel

Options for Bounded Polynomial Mutation.

Source code in desdeo/emo/options/mutation.py
class BoundedPolynomialMutationOptions(BaseModel):
    """Options for Bounded Polynomial Mutation."""

    model_config = {"use_attribute_docstrings": True}

    name: Literal["BoundedPolynomialMutation"] = Field(
        default="BoundedPolynomialMutation",
        frozen=True,
    )
    """The name of the mutation operator."""
    mutation_probability: float | None = Field(default=None, ge=0.0, le=1.0)
    """
    The probability of mutation. Defaults to None, which sets the mutation probability to
    1/<number of decision variables>.
    """
    distribution_index: float = Field(default=20.0, gt=0.0)
    """The distribution index."""

distribution_index class-attribute instance-attribute

distribution_index: float = Field(default=20.0, gt=0.0)

The distribution index.

mutation_probability class-attribute instance-attribute

mutation_probability: float | None = Field(
    default=None, ge=0.0, le=1.0
)

The probability of mutation. Defaults to None, which sets the mutation probability to 1/.

name class-attribute instance-attribute

name: Literal["BoundedPolynomialMutation"] = Field(
    default="BoundedPolynomialMutation", frozen=True
)

The name of the mutation operator.

IntegerRandomMutationOptions

Bases: BaseModel

Options for Integer Random Mutation.

Source code in desdeo/emo/options/mutation.py
class IntegerRandomMutationOptions(BaseModel):
    """Options for Integer Random Mutation."""

    name: Literal["IntegerRandomMutation"] = Field(
        default="IntegerRandomMutation", frozen=True, description="The name of the mutation operator."
    )
    """The name of the mutation operator."""
    mutation_probability: float | None = Field(
        default=None,
        ge=0.0,
        le=1.0,
        description=(
            "The probability of mutation. Defaults to None, which sets the "
            "mutation probability to 1/<number of decision variables>."
        ),
    )
    """
    The probability of mutation. Defaults to None, which sets the mutation probability to
    1/<number of decision variables>.
    """

mutation_probability class-attribute instance-attribute

mutation_probability: float | None = Field(
    default=None,
    ge=0.0,
    le=1.0,
    description="The probability of mutation. Defaults to None, which sets the mutation probability to 1/<number of decision variables>.",
)

The probability of mutation. Defaults to None, which sets the mutation probability to 1/.

name class-attribute instance-attribute

name: Literal["IntegerRandomMutation"] = Field(
    default="IntegerRandomMutation",
    frozen=True,
    description="The name of the mutation operator.",
)

The name of the mutation operator.

MPTMutationOptions

Bases: BaseModel

Options for MPT Mutation.

Source code in desdeo/emo/options/mutation.py
class MPTMutationOptions(BaseModel):
    """Options for MPT Mutation."""

    name: Literal["MPTMutation"] = Field(
        default="MPTMutation", frozen=True, description="The name of the mutation operator."
    )
    """The name of the mutation operator."""
    mutation_probability: float | None = Field(
        default=None,
        ge=0.0,
        le=1.0,
        description=(
            "The probability of mutation. Defaults to None, which sets the "
            "mutation probability to 1/<number of decision variables>."
        ),
    )
    """
    The probability of mutation. Defaults to None, which sets the mutation probability to
    1/<number of decision variables>.
    """
    mutation_exponent: float = Field(
        default=2.0, ge=0.0, description="Controls strength of small mutation (larger means smaller mutations)."
    )
    """Controls strength of small mutation (larger means smaller mutations)."""

mutation_exponent class-attribute instance-attribute

mutation_exponent: float = Field(
    default=2.0,
    ge=0.0,
    description="Controls strength of small mutation (larger means smaller mutations).",
)

Controls strength of small mutation (larger means smaller mutations).

mutation_probability class-attribute instance-attribute

mutation_probability: float | None = Field(
    default=None,
    ge=0.0,
    le=1.0,
    description="The probability of mutation. Defaults to None, which sets the mutation probability to 1/<number of decision variables>.",
)

The probability of mutation. Defaults to None, which sets the mutation probability to 1/.

name class-attribute instance-attribute

name: Literal["MPTMutation"] = Field(
    default="MPTMutation",
    frozen=True,
    description="The name of the mutation operator.",
)

The name of the mutation operator.

MixedIntegerRandomMutationOptions

Bases: BaseModel

Options for Mixed Integer Random Mutation.

Source code in desdeo/emo/options/mutation.py
class MixedIntegerRandomMutationOptions(BaseModel):
    """Options for Mixed Integer Random Mutation."""

    name: Literal["MixedIntegerRandomMutation"] = Field(
        default="MixedIntegerRandomMutation", frozen=True, description="The name of the mutation operator."
    )
    """The name of the mutation operator."""
    mutation_probability: float | None = Field(
        default=None,
        ge=0.0,
        le=1.0,
        description=(
            "The probability of mutation. Defaults to None, which sets the "
            "mutation probability to 1/<number of decision variables>."
        ),
    )
    """
    The probability of mutation. Defaults to None, which sets the mutation probability to
    1/<number of decision variables>.
    """

mutation_probability class-attribute instance-attribute

mutation_probability: float | None = Field(
    default=None,
    ge=0.0,
    le=1.0,
    description="The probability of mutation. Defaults to None, which sets the mutation probability to 1/<number of decision variables>.",
)

The probability of mutation. Defaults to None, which sets the mutation probability to 1/.

name class-attribute instance-attribute

name: Literal["MixedIntegerRandomMutation"] = Field(
    default="MixedIntegerRandomMutation",
    frozen=True,
    description="The name of the mutation operator.",
)

The name of the mutation operator.

NonUniformMutationOptions

Bases: BaseModel

Options for Non-Uniform Mutation.

Source code in desdeo/emo/options/mutation.py
class NonUniformMutationOptions(BaseModel):
    """Options for Non-Uniform Mutation."""

    name: Literal["NonUniformMutation"] = Field(
        default="NonUniformMutation", frozen=True, description="The name of the mutation operator."
    )
    """The name of the mutation operator."""
    mutation_probability: float | None = Field(
        default=None,
        ge=0.0,
        le=1.0,
        description=(
            "The probability of mutation. Defaults to None, which sets the "
            "mutation probability to 1/<number of decision variables>."
        ),
    )
    """
    The probability of mutation. Defaults to None, which sets the mutation probability to
    1/<number of decision variables>.
    """
    max_generations: int = Field(
        gt=0, description="Maximum number of generations in the evolutionary run. Used to scale mutation decay."
    )
    b: float = Field(
        default=5.0,
        ge=0.0,
        description=(
            "Non-uniform mutation decay parameter. Higher values cause"
            "faster reduction in mutation strength over generations."
        ),
    )
    """Non-uniform mutation decay parameter. Higher values cause
    faster reduction in mutation strength over generations."""

b class-attribute instance-attribute

b: float = Field(
    default=5.0,
    ge=0.0,
    description="Non-uniform mutation decay parameter. Higher values causefaster reduction in mutation strength over generations.",
)

Non-uniform mutation decay parameter. Higher values cause faster reduction in mutation strength over generations.

mutation_probability class-attribute instance-attribute

mutation_probability: float | None = Field(
    default=None,
    ge=0.0,
    le=1.0,
    description="The probability of mutation. Defaults to None, which sets the mutation probability to 1/<number of decision variables>.",
)

The probability of mutation. Defaults to None, which sets the mutation probability to 1/.

name class-attribute instance-attribute

name: Literal["NonUniformMutation"] = Field(
    default="NonUniformMutation",
    frozen=True,
    description="The name of the mutation operator.",
)

The name of the mutation operator.

PowerMutationOptions

Bases: BaseModel

Options for Power Mutation.

Source code in desdeo/emo/options/mutation.py
class PowerMutationOptions(BaseModel):
    """Options for Power Mutation."""

    name: Literal["PowerMutation"] = Field(
        default="PowerMutation", frozen=True, description="The name of the mutation operator."
    )
    """The name of the mutation operator."""
    mutation_probability: float | None = Field(
        default=None,
        ge=0.0,
        le=1.0,
        description=(
            "The probability of mutation. Defaults to None, which sets the "
            "mutation probability to 1/<number of decision variables>."
        ),
    )
    """
    The probability of mutation. Defaults to None, which sets the mutation probability to
    1/<number of decision variables>.
    """
    p: float = Field(
        default=1.5, ge=0.0, description="Power distribution parameter. Controls the perturbation magnitude."
    )
    """Power distribution parameter. Controls the perturbation magnitude."""

mutation_probability class-attribute instance-attribute

mutation_probability: float | None = Field(
    default=None,
    ge=0.0,
    le=1.0,
    description="The probability of mutation. Defaults to None, which sets the mutation probability to 1/<number of decision variables>.",
)

The probability of mutation. Defaults to None, which sets the mutation probability to 1/.

name class-attribute instance-attribute

name: Literal["PowerMutation"] = Field(
    default="PowerMutation",
    frozen=True,
    description="The name of the mutation operator.",
)

The name of the mutation operator.

p class-attribute instance-attribute

p: float = Field(
    default=1.5,
    ge=0.0,
    description="Power distribution parameter. Controls the perturbation magnitude.",
)

Power distribution parameter. Controls the perturbation magnitude.

SelfAdaptiveGaussianMutationOptions

Bases: BaseModel

Options for Self-Adaptive Gaussian Mutation.

Source code in desdeo/emo/options/mutation.py
class SelfAdaptiveGaussianMutationOptions(BaseModel):
    """Options for Self-Adaptive Gaussian Mutation."""

    name: Literal["SelfAdaptiveGaussianMutation"] = Field(
        default="SelfAdaptiveGaussianMutation", frozen=True, description="The name of the mutation operator."
    )
    """The name of the mutation operator."""
    mutation_probability: float | None = Field(
        default=None,
        ge=0.0,
        le=1.0,
        description=(
            "The probability of mutation. Defaults to None, which sets the "
            "mutation probability to 1/<number of decision variables>."
        ),
    )
    """
    The probability of mutation. Defaults to None, which sets the mutation probability to
    1/<number of decision variables>.
    """

mutation_probability class-attribute instance-attribute

mutation_probability: float | None = Field(
    default=None,
    ge=0.0,
    le=1.0,
    description="The probability of mutation. Defaults to None, which sets the mutation probability to 1/<number of decision variables>.",
)

The probability of mutation. Defaults to None, which sets the mutation probability to 1/.

name class-attribute instance-attribute

name: Literal["SelfAdaptiveGaussianMutation"] = Field(
    default="SelfAdaptiveGaussianMutation",
    frozen=True,
    description="The name of the mutation operator.",
)

The name of the mutation operator.

mutation_constructor

mutation_constructor(
    problem: Problem,
    publisher: Publisher,
    seed: int,
    verbosity: int,
    options: MutationOptions,
) -> BaseMutation

Construct a mutation operator.

Parameters:

Name Type Description Default
problem Problem

The optimization problem to solve.

required
publisher Publisher

The publisher for communication.

required
seed int

The random seed for reproducibility.

required
verbosity int

The verbosity level of the output.

required
options MutationOptions

The options for the mutation operator.

required

Returns:

Name Type Description
BaseCrossover BaseMutation

The constructed crossover operator.

Source code in desdeo/emo/options/mutation.py
def mutation_constructor(
    problem: Problem, publisher: Publisher, seed: int, verbosity: int, options: MutationOptions
) -> BaseMutation:
    """Construct a mutation operator.

    Args:
        problem (Problem): The optimization problem to solve.
        publisher (Publisher): The publisher for communication.
        seed (int): The random seed for reproducibility.
        verbosity (int): The verbosity level of the output.
        options (MutationOptions): The options for the mutation operator.

    Returns:
        BaseCrossover: The constructed crossover operator.
    """
    mutation_types = {
        "BoundedPolynomialMutation": BoundedPolynomialMutation,
        "BinaryFlipMutation": BinaryFlipMutation,
        "IntegerRandomMutation": IntegerRandomMutation,
        "MixedIntegerRandomMutation": MixedIntegerRandomMutation,
        "MPTMutation": MPTMutation,
        "NonUniformMutation": NonUniformMutation,
        "SelfAdaptiveGaussianMutation": SelfAdaptiveGaussianMutation,
        "PowerMutation": PowerMutation,
    }
    options: dict = options.model_dump()
    name = options.pop("name")
    return mutation_types[name](problem=problem, publisher=publisher, seed=seed, verbosity=verbosity, **options)

Repair Functions

JSON Schema for repair operator options.

ClipRepairOptions

Bases: BaseModel

Options for Clip Repair.

Source code in desdeo/emo/options/repair.py
class ClipRepairOptions(BaseModel):
    """Options for Clip Repair."""

    model_config = ConfigDict(use_attribute_docstrings=True)

    name: Literal["ClipRepair"] = Field(default="ClipRepair")
    """Clip the solutions to be within the variable bounds."""

    lower_bounds: dict[str, float] | None = None
    """Lower bounds for the decision variables. If none, the lower bounds from the problem will be used."""
    upper_bounds: dict[str, float] | None = None
    """Upper bounds for the decision variables. If none, the upper bounds from the problem will be used."""

lower_bounds class-attribute instance-attribute

lower_bounds: dict[str, float] | None = None

Lower bounds for the decision variables. If none, the lower bounds from the problem will be used.

name class-attribute instance-attribute

name: Literal['ClipRepair'] = Field(default='ClipRepair')

Clip the solutions to be within the variable bounds.

upper_bounds class-attribute instance-attribute

upper_bounds: dict[str, float] | None = None

Upper bounds for the decision variables. If none, the upper bounds from the problem will be used.

NoRepairOptions

Bases: BaseModel

Options for No Repair.

Source code in desdeo/emo/options/repair.py
class NoRepairOptions(BaseModel):
    """Options for No Repair."""

    model_config = ConfigDict(use_attribute_docstrings=True)

    name: Literal["NoRepair"] = Field(default="NoRepair")
    """Do not apply any repair to the solutions."""

name class-attribute instance-attribute

name: Literal['NoRepair'] = Field(default='NoRepair')

Do not apply any repair to the solutions.

repair_constructor

repair_constructor(
    options: RepairOptions, problem: Problem
) -> Callable[[pl.DataFrame], pl.DataFrame]

Get the repair operator based on the provided options.

Parameters:

Name Type Description Default
options RepairOptions

The repair options.

required
problem Problem

The optimization problem to solve.

required

Returns:

Name Type Description
callable Callable[[DataFrame], DataFrame]

The repair operator function.

Source code in desdeo/emo/options/repair.py
def repair_constructor(options: RepairOptions, problem: Problem) -> Callable[[pl.DataFrame], pl.DataFrame]:
    """Get the repair operator based on the provided options.

    Args:
        options (RepairOptions): The repair options.
        problem (Problem): The optimization problem to solve.

    Returns:
        callable: The repair operator function.
    """
    if options.name == "NoRepair":
        return lambda x: x  # No repair, return input as is
    if options.name == "ClipRepair":
        if options.lower_bounds is None:
            lower_bounds = {var.symbol: var.lowerbound for var in problem.get_flattened_variables()}
        else:
            lower_bounds = options.lower_bounds
        if options.upper_bounds is None:
            upper_bounds = {var.symbol: var.upperbound for var in problem.get_flattened_variables()}
        else:
            upper_bounds = options.upper_bounds
        return repair(lower_bounds=lower_bounds, upper_bounds=upper_bounds)
    raise ValueError(f"Unknown repair operator: {options.name}")

Scalar Selection Operators

JSON Schema for scalar selector operator options.

RouletteWheelSelectionOptions

Bases: TournamentSelectionOptions

Options for roulette wheel selection operator.

Source code in desdeo/emo/options/scalar_selection.py
class RouletteWheelSelectionOptions(TournamentSelectionOptions):
    """Options for roulette wheel selection operator."""

    name: Literal["RouletteWheelSelection"] = Field(
        default="RouletteWheelSelection", frozen=True, description="The name of the scalar selection operator."
    )
    """The name of the scalar selection operator."""

name class-attribute instance-attribute

name: Literal["RouletteWheelSelection"] = Field(
    default="RouletteWheelSelection",
    frozen=True,
    description="The name of the scalar selection operator.",
)

The name of the scalar selection operator.

TournamentSelectionOptions

Bases: BaseModel

Options for tournament selection operator.

Source code in desdeo/emo/options/scalar_selection.py
class TournamentSelectionOptions(BaseModel):
    """Options for tournament selection operator."""

    name: Literal["TournamentSelection"] = Field(
        default="TournamentSelection", frozen=True, description="The name of the scalar selection operator."
    )
    """The name of the scalar selection operator."""
    tournament_size: int = Field(
        default=2,
        description="The number of individuals participating in the tournament.",
    )
    """The number of individuals participating in the tournament."""
    winner_size: int = Field(
        gt=1,
        description="The number of winners to select (equivalent to population size).",
    )
    """The number of winners to select (equivalent to population size)."""

name class-attribute instance-attribute

name: Literal["TournamentSelection"] = Field(
    default="TournamentSelection",
    frozen=True,
    description="The name of the scalar selection operator.",
)

The name of the scalar selection operator.

tournament_size class-attribute instance-attribute

tournament_size: int = Field(
    default=2,
    description="The number of individuals participating in the tournament.",
)

The number of individuals participating in the tournament.

winner_size class-attribute instance-attribute

winner_size: int = Field(
    gt=1,
    description="The number of winners to select (equivalent to population size).",
)

The number of winners to select (equivalent to population size).

scalar_selector_constructor

scalar_selector_constructor(
    options: ScalarSelectionOptions,
    seed: int,
    publisher: Publisher,
    verbosity: int,
) -> BaseScalarSelector

Construct a scalar selector operator based on the provided options.

Source code in desdeo/emo/options/scalar_selection.py
def scalar_selector_constructor(
    options: ScalarSelectionOptions, seed: int, publisher: Publisher, verbosity: int
) -> BaseScalarSelector:
    """Construct a scalar selector operator based on the provided options."""
    if options.name == "TournamentSelection":
        return TournamentSelection(
            tournament_size=options.tournament_size,
            winner_size=options.winner_size,
            publisher=publisher,
            verbosity=verbosity,
        )
    if options.name == "RouletteWheelSelection":
        return TournamentSelection(  # It implements both (and more)
            winner_size=options.winner_size,
            seed=seed,  # By providing seed tournament selection behaves like roulette wheel
            publisher=publisher,
            verbosity=verbosity,
            tournament_size=options.tournament_size,
        )
    else:
        raise ValueError(f"Unknown scalar selection operator: {options.name}")

Selection Operators

JSON Schema for selection operator options.

IBEASelectorOptions

Bases: BaseModel

Options for IBEA Selection.

Source code in desdeo/emo/options/selection.py
class IBEASelectorOptions(BaseModel):
    """Options for IBEA Selection."""

    name: Literal["IBEASelector"] = Field(
        default="IBEASelector", frozen=True, description="The name of the selection operator."
    )
    """The name of the selection operator."""
    population_size: int = Field(gt=0, description="The population size.")
    """The population size."""
    kappa: float = Field(default=0.05, description="The kappa parameter for IBEA.")
    """The kappa parameter for IBEA."""
    binary_indicator: Literal["eps", "hv"] = Field(default="eps", description="The binary indicator for IBEA.")
    """The binary indicator for IBEA."""

binary_indicator class-attribute instance-attribute

binary_indicator: Literal["eps", "hv"] = Field(
    default="eps",
    description="The binary indicator for IBEA.",
)

The binary indicator for IBEA.

kappa class-attribute instance-attribute

kappa: float = Field(
    default=0.05,
    description="The kappa parameter for IBEA.",
)

The kappa parameter for IBEA.

name class-attribute instance-attribute

name: Literal["IBEASelector"] = Field(
    default="IBEASelector",
    frozen=True,
    description="The name of the selection operator.",
)

The name of the selection operator.

population_size class-attribute instance-attribute

population_size: int = Field(
    gt=0, description="The population size."
)

The population size.

NSGA2SelectorOptions

Bases: BaseModel

Options for NSGA-II Selection.

Source code in desdeo/emo/options/selection.py
class NSGA2SelectorOptions(BaseModel):
    """Options for NSGA-II Selection."""

    name: Literal["NSGA2Selector"] = Field(
        default="NSGA2Selector", frozen=True, description="The name of the selection operator."
    )
    """The name of the selection operator."""
    population_size: int = Field(gt=0, description="The population size.")
    """The population size."""

name class-attribute instance-attribute

name: Literal["NSGA2Selector"] = Field(
    default="NSGA2Selector",
    frozen=True,
    description="The name of the selection operator.",
)

The name of the selection operator.

population_size class-attribute instance-attribute

population_size: int = Field(
    gt=0, description="The population size."
)

The population size.

NSGA3SelectorOptions

Bases: BaseModel

Options for NSGA-III Selection.

Source code in desdeo/emo/options/selection.py
class NSGA3SelectorOptions(BaseModel):
    """Options for NSGA-III Selection."""

    name: Literal["NSGA3Selector"] = Field(
        default="NSGA3Selector", frozen=True, description="The name of the selection operator."
    )
    """The name of the selection operator."""
    reference_vector_options: ReferenceVectorOptions = Field(
        default=ReferenceVectorOptions(), description="Options for the reference vectors."
    )
    """Options for the reference vectors."""
    invert_reference_vectors: bool = Field(
        default=False, description="Whether to invert the reference vectors (inverted triangle)."
    )
    """Whether to invert the reference vectors (inverted triangle)."""

invert_reference_vectors class-attribute instance-attribute

invert_reference_vectors: bool = Field(
    default=False,
    description="Whether to invert the reference vectors (inverted triangle).",
)

Whether to invert the reference vectors (inverted triangle).

name class-attribute instance-attribute

name: Literal["NSGA3Selector"] = Field(
    default="NSGA3Selector",
    frozen=True,
    description="The name of the selection operator.",
)

The name of the selection operator.

reference_vector_options class-attribute instance-attribute

reference_vector_options: ReferenceVectorOptions = Field(
    default=ReferenceVectorOptions(),
    description="Options for the reference vectors.",
)

Options for the reference vectors.

RVEASelectorOptions

Bases: BaseModel

Options for RVEA Selection.

Source code in desdeo/emo/options/selection.py
class RVEASelectorOptions(BaseModel):
    """Options for RVEA Selection."""

    model_config = ConfigDict(use_enum_values=True)

    name: Literal["RVEASelector"] = Field(
        default="RVEASelector", frozen=True, description="The name of the selection operator."
    )
    """The name of the selection operator."""
    reference_vector_options: ReferenceVectorOptions = Field(
        default=ReferenceVectorOptions(), description="Options for the reference vectors."
    )
    """Options for the reference vectors."""
    parameter_adaptation_strategy: ParameterAdaptationStrategy = Field(
        default=ParameterAdaptationStrategy.GENERATION_BASED, description="The parameter adaptation strategy to use."
    )
    """Whether the angle penalized distance is adapted per generation or per function evaluation."""
    alpha: float = Field(default=2.0, gt=0.0, description="The alpha parameter in the angle penalized distance.")
    """The alpha parameter in the angle penalized distance."""

alpha class-attribute instance-attribute

alpha: float = Field(
    default=2.0,
    gt=0.0,
    description="The alpha parameter in the angle penalized distance.",
)

The alpha parameter in the angle penalized distance.

name class-attribute instance-attribute

name: Literal["RVEASelector"] = Field(
    default="RVEASelector",
    frozen=True,
    description="The name of the selection operator.",
)

The name of the selection operator.

parameter_adaptation_strategy class-attribute instance-attribute

parameter_adaptation_strategy: ParameterAdaptationStrategy = Field(
    default=GENERATION_BASED,
    description="The parameter adaptation strategy to use.",
)

Whether the angle penalized distance is adapted per generation or per function evaluation.

reference_vector_options class-attribute instance-attribute

reference_vector_options: ReferenceVectorOptions = Field(
    default=ReferenceVectorOptions(),
    description="Options for the reference vectors.",
)

Options for the reference vectors.

selection_constructor

selection_constructor(
    problem: Problem,
    options: SelectorOptions,
    publisher: Publisher,
    verbosity: int,
    seed: int,
) -> BaseSelector

Construct a selection operator from given options.

Parameters:

Name Type Description Default
problem Problem

The optimization problem.

required
options SelectorOptions

The options for the selection operator.

required
publisher Publisher

The publisher to use for the operator.

required
verbosity int

The verbosity level.

required
seed int

The random seed.

required

Returns:

Name Type Description
BaseSelector BaseSelector

The constructed selection operator.

Raises:

Type Description
ValueError

If an unknown selection operator name is provided.

Source code in desdeo/emo/options/selection.py
def selection_constructor(
    problem: Problem, options: SelectorOptions, publisher: Publisher, verbosity: int, seed: int
) -> BaseSelector:
    """Construct a selection operator from given options.

    Args:
        problem (Problem): The optimization problem.
        options (SelectorOptions): The options for the selection operator.
        publisher (Publisher): The publisher to use for the operator.
        verbosity (int): The verbosity level.
        seed (int): The random seed.

    Returns:
        BaseSelector: The constructed selection operator.

    Raises:
        ValueError: If an unknown selection operator name is provided.
    """
    selection_types = {
        "RVEASelector": RVEASelector,
        "NSGA2Selector": NSGA2Selector,
        "NSGA3Selector": NSGA3Selector,
        "IBEASelector": IBEASelector,
    }
    options: dict = options.model_dump()
    name = options.pop("name")
    if name == "IBEASelector":
        indi = options.pop("binary_indicator")
        match indi:
            case "eps":
                options["binary_indicator"] = self_epsilon
            case "hv":
                options["binary_indicator"] = self_hv
            case _:
                raise ValueError(f"Unknown binary indicator: {indi}")
    return selection_types[name](problem=problem, publisher=publisher, seed=seed, verbosity=verbosity, **options)

Termination Criteria

JSON Schema for termination operator options.

CompositeTerminatorOptions

Bases: BaseModel

Options for composite terminator operator.

Source code in desdeo/emo/options/termination.py
class CompositeTerminatorOptions(BaseModel):
    """Options for composite terminator operator."""

    name: Literal["CompositeTerminator"] = Field(
        default="CompositeTerminator", frozen=True, description="The name of the termination operator."
    )
    """The name of the termination operator."""
    terminators: list[
        MaxEvaluationsTerminatorOptions
        | MaxGenerationsTerminatorOptions
        | MaxTimeTerminatorOptions
        | ExternalCheckTerminatorOptions
    ] = Field(default_factory=lambda: [MaxGenerationsTerminatorOptions()], description="List of terminators.")
    """List of terminators."""
    mode: Literal["all", "any"] = Field(default="any", description="Whether to use logical AND or OR.")
    """Whether to use logical AND or OR."""

    @model_validator(mode="after")
    def check_unique_terminator_types(self):
        """Ensure that all terminator types in the composite are unique."""
        types_seen = set()
        for term in self.terminators:
            t = type(term)
            if t in types_seen:
                raise ValueError(f"Duplicate terminator type: {t.__name__}")
            types_seen.add(t)
        return self

mode class-attribute instance-attribute

mode: Literal["all", "any"] = Field(
    default="any",
    description="Whether to use logical AND or OR.",
)

Whether to use logical AND or OR.

name class-attribute instance-attribute

name: Literal["CompositeTerminator"] = Field(
    default="CompositeTerminator",
    frozen=True,
    description="The name of the termination operator.",
)

The name of the termination operator.

terminators class-attribute instance-attribute

terminators: list[
    MaxEvaluationsTerminatorOptions
    | MaxGenerationsTerminatorOptions
    | MaxTimeTerminatorOptions
    | ExternalCheckTerminatorOptions
] = Field(
    default_factory=lambda: [
        MaxGenerationsTerminatorOptions()
    ],
    description="List of terminators.",
)

List of terminators.

check_unique_terminator_types

check_unique_terminator_types()

Ensure that all terminator types in the composite are unique.

Source code in desdeo/emo/options/termination.py
@model_validator(mode="after")
def check_unique_terminator_types(self):
    """Ensure that all terminator types in the composite are unique."""
    types_seen = set()
    for term in self.terminators:
        t = type(term)
        if t in types_seen:
            raise ValueError(f"Duplicate terminator type: {t.__name__}")
        types_seen.add(t)
    return self

ExternalCheckTerminatorOptions

Bases: BaseModel

Options for external check terminator operator. Note that the check function must be provided separately.

Source code in desdeo/emo/options/termination.py
class ExternalCheckTerminatorOptions(BaseModel):
    """Options for external check terminator operator. Note that the check function must be provided separately."""

    name: Literal["ExternalCheckTerminator"] = Field(
        default="ExternalCheckTerminator", frozen=True, description="The name of the termination operator."
    )
    """The name of the termination operator."""

name class-attribute instance-attribute

name: Literal["ExternalCheckTerminator"] = Field(
    default="ExternalCheckTerminator",
    frozen=True,
    description="The name of the termination operator.",
)

The name of the termination operator.

MaxEvaluationsTerminatorOptions

Bases: BaseModel

Options for max evaluations terminator operator.

Source code in desdeo/emo/options/termination.py
class MaxEvaluationsTerminatorOptions(BaseModel):
    """Options for max evaluations terminator operator."""

    name: Literal["MaxEvaluationsTerminator"] = Field(
        default="MaxEvaluationsTerminator", frozen=True, description="The name of the termination operator."
    )
    """The name of the termination operator."""
    max_evaluations: int = Field(default=10000, gt=0, description="The maximum number of evaluations allowed.")
    """The maximum number of evaluations allowed."""

max_evaluations class-attribute instance-attribute

max_evaluations: int = Field(
    default=10000,
    gt=0,
    description="The maximum number of evaluations allowed.",
)

The maximum number of evaluations allowed.

name class-attribute instance-attribute

name: Literal["MaxEvaluationsTerminator"] = Field(
    default="MaxEvaluationsTerminator",
    frozen=True,
    description="The name of the termination operator.",
)

The name of the termination operator.

MaxGenerationsTerminatorOptions

Bases: BaseModel

Options for max generations terminator operator.

Source code in desdeo/emo/options/termination.py
class MaxGenerationsTerminatorOptions(BaseModel):
    """Options for max generations terminator operator."""

    name: Literal["MaxGenerationsTerminator"] = Field(
        default="MaxGenerationsTerminator", frozen=True, description="The name of the termination operator."
    )
    """The name of the termination operator."""
    max_generations: int = Field(default=100, gt=0, description="The maximum number of generations allowed.")
    """The maximum number of generations allowed."""

max_generations class-attribute instance-attribute

max_generations: int = Field(
    default=100,
    gt=0,
    description="The maximum number of generations allowed.",
)

The maximum number of generations allowed.

name class-attribute instance-attribute

name: Literal["MaxGenerationsTerminator"] = Field(
    default="MaxGenerationsTerminator",
    frozen=True,
    description="The name of the termination operator.",
)

The name of the termination operator.

MaxTimeTerminatorOptions

Bases: BaseModel

Options for max time terminator operator.

Source code in desdeo/emo/options/termination.py
class MaxTimeTerminatorOptions(BaseModel):
    """Options for max time terminator operator."""

    name: Literal["MaxTimeTerminator"] = Field(
        default="MaxTimeTerminator", frozen=True, description="The name of the termination operator."
    )
    """The name of the termination operator."""
    max_time: float = Field(default=30.0, gt=0, description="The maximum time allowed (in seconds).")
    """The maximum time allowed (in seconds)."""

max_time class-attribute instance-attribute

max_time: float = Field(
    default=30.0,
    gt=0,
    description="The maximum time allowed (in seconds).",
)

The maximum time allowed (in seconds).

name class-attribute instance-attribute

name: Literal["MaxTimeTerminator"] = Field(
    default="MaxTimeTerminator",
    frozen=True,
    description="The name of the termination operator.",
)

The name of the termination operator.

terminator_constructor

terminator_constructor(
    options: TerminatorOptions,
    publisher: Publisher,
    external_check: Callable | None = None,
) -> BaseTerminator

Construct a termination operator.

Parameters:

Name Type Description Default
options TerminatorOptions

Options for the termination operator.

required
publisher Publisher

Publisher instance for the termination operator.

required
external_check Callable | None

External check function for the termination operator. Defaults to None. Only required if using ExternalCheckTerminator.

None

Raises:

Type Description
ValueError

If the options are invalid.

ValueError

If the external check function is required but not provided.

Returns:

Name Type Description
BaseTerminator BaseTerminator

Instance of the termination operator.

Source code in desdeo/emo/options/termination.py
def terminator_constructor(
    options: TerminatorOptions, publisher: Publisher, external_check: Callable | None = None
) -> BaseTerminator:
    """Construct a termination operator.

    Args:
        options (TerminatorOptions): Options for the termination operator.
        publisher (Publisher): Publisher instance for the termination operator.
        external_check (Callable | None, optional): External check function for the termination operator.
            Defaults to None. Only required if using ExternalCheckTerminator.

    Raises:
        ValueError: If the options are invalid.
        ValueError: If the external check function is required but not provided.

    Returns:
        BaseTerminator: Instance of the termination operator.
    """
    terminators = {
        "MaxGenerationsTerminator": MaxGenerationsTerminator,
        "MaxEvaluationsTerminator": MaxEvaluationsTerminator,
        "MaxTimeTerminator": MaxTimeTerminator,
        "ExternalCheckTerminator": ExternalCheckTerminator,
        "CompositeTerminator": CompositeTerminator,
    }
    options: dict = options.model_dump()
    name = options.pop("name")
    if name not in ("ExternalCheckTerminator", "CompositeTerminator"):
        return terminators[name](publisher=publisher, **options)
    if name == "ExternalCheckTerminator":
        if external_check is None:
            raise ValueError("External check function must be provided for ExternalCheckTerminator.")
        return terminators[name](external_check=external_check, **options)
    if name == "CompositeTerminator":
        sub_terminators = []
        for term_options in options.pop("terminators"):
            sub_terminators.append(terminator_constructor(term_options, publisher, external_check))
            # sub_name = term_options.pop("name")
            # sub_terminators.append(terminators[sub_name](publisher=publisher, **term_options))
        return CompositeTerminator(terminators=sub_terminators, publisher=publisher, mode=options["mode"])
    raise ValueError(f"Unknown terminator name: {name}")