Skip to content

odys.domain.objective

Objective configuration for energy system optimization.

An Objective holds its terms: a required ProfitTerm and an optional CVaRTerm, at most one of each. The model maximizes the sum of their weighted expressions; without a CVaRTerm, that is the expected profit alone. The terms are written out on the Objective formulation page, and configuring them on the Risk (CVaR) User Guide page.

See also optimization.objective_terms for the implementation-side construction.

Objective function configuration for energy system optimization.

Provides composable objective terms that users combine into an Objective. The final objective is: maximize Σ weight_i * term_i(model).

CVaRTerm

Bases: ObjectiveTerm

Represents a Conditional Value at Risk (CVaR) penalty term.

CVaR is used to reduce exposure to low-probability, high-impact losses. The confidence level determines the portion of the distribution used when evaluating risk.

Attributes:

Name Type Description
confidence_level float

Confidence level used for the CVaR calculation. Must be greater than 0 and less than 1.

Source code in src/odys/domain/objective.py
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
class CVaRTerm(ObjectiveTerm):
    """Represents a Conditional Value at Risk (CVaR) penalty term.

    CVaR is used to reduce exposure to low-probability, high-impact losses.
    The confidence level determines the portion of the distribution used
    when evaluating risk.

    Attributes:
        confidence_level: Confidence level used for the CVaR calculation.
            Must be greater than 0 and less than 1.
    """

    confidence_level: float = Field(
        gt=0,
        lt=1,
        description="Confidence level used for the CVaR calculation. Must be greater than 0 and less than 1.",
    )

Objective

Bases: BaseModel

Configuration for the optimization objective.

Combines objective terms into a single objective function to maximize: Σ weight_i * term_i. A ProfitTerm is required; a CVaRTerm is optional and balances expected profit against risk. Each term type appears at most once. The default maximizes expected profit.

Example

Objective(terms=(ProfitTerm(weight=1.0), CVaRTerm(weight=0.5, confidence_level=0.95)))

Attributes:

Name Type Description
terms tuple[ProfitTerm | CVaRTerm, ...]

The objective terms, at most one of each type.

Source code in src/odys/domain/objective.py
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
class Objective(BaseModel):
    """Configuration for the optimization objective.

    Combines objective terms into a single objective function to maximize:
    Σ weight_i * term_i. A `ProfitTerm` is required; a `CVaRTerm` is optional
    and balances expected profit against risk. Each term type appears at
    most once. The default maximizes expected profit.

    Example:
        >>> Objective(terms=(ProfitTerm(weight=1.0), CVaRTerm(weight=0.5, confidence_level=0.95)))

    Attributes:
        terms: The objective terms, at most one of each type.
    """

    model_config = ConfigDict(frozen=True, extra="forbid")

    terms: tuple[ProfitTerm | CVaRTerm, ...] = Field(
        default=(ProfitTerm(weight=1.0),),
        description="The objective terms, at most one of each type. A ProfitTerm is required.",
    )

    @model_validator(mode="after")
    def _validate_one_term_per_type(self) -> Self:
        duplicates = [kind.__name__ for kind in (ProfitTerm, CVaRTerm) if len(self._terms_of(kind)) > 1]
        if duplicates:
            msg = f"Objective has more than one term of type: {duplicates}."
            raise OdysValidationError(msg)
        return self

    @model_validator(mode="after")
    def _validate_profit_term_present(self) -> Self:
        if self.term_of(ProfitTerm) is None:
            msg = "Objective must include a ProfitTerm."
            raise OdysValidationError(msg)
        return self

    def _terms_of(self, kind: type[TermT]) -> tuple[TermT, ...]:
        return tuple(term for term in self.terms if isinstance(term, kind))

    def term_of(self, kind: type[TermT]) -> TermT | None:
        """Return the term of the given type, if the objective has one.

        Args:
            kind: The term type to look up, such as `CVaRTerm`.

        Returns:
            The term, or None if the objective has no term of that type.

        """
        return next(iter(self._terms_of(kind)), None)

term_of(kind)

Return the term of the given type, if the objective has one.

Parameters:

Name Type Description Default
kind type[TermT]

The term type to look up, such as CVaRTerm.

required

Returns:

Type Description
TermT | None

The term, or None if the objective has no term of that type.

Source code in src/odys/domain/objective.py
106
107
108
109
110
111
112
113
114
115
116
def term_of(self, kind: type[TermT]) -> TermT | None:
    """Return the term of the given type, if the objective has one.

    Args:
        kind: The term type to look up, such as `CVaRTerm`.

    Returns:
        The term, or None if the objective has no term of that type.

    """
    return next(iter(self._terms_of(kind)), None)

ObjectiveTerm

Bases: BaseModel

Base class for all objective terms used in the optimization objective.

Each objective term contributes to the final objective function through its associated weight. Subclasses define the specific metric or penalty that should be optimized.

Attributes:

Name Type Description
weight float

Relative importance of this objective term in the overall objective function. Must be non-negative; a weight of 0 keeps the term in the config while excluding it from the objective.

Source code in src/odys/domain/objective.py
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class ObjectiveTerm(BaseModel):
    """Base class for all objective terms used in the optimization objective.

    Each objective term contributes to the final objective function through
    its associated weight. Subclasses define the specific metric or penalty
    that should be optimized.

    Attributes:
        weight: Relative importance of this objective term in the overall
            objective function. Must be non-negative; a weight of 0 keeps the
            term in the config while excluding it from the objective.
    """

    model_config = ConfigDict(frozen=True, extra="forbid")

    weight: float = Field(
        ge=0,
        description="Relative importance of this objective term in the overall objective function.",
    )

ProfitTerm

Bases: ObjectiveTerm

Represents the expected profit objective across all scenarios.

This objective term maximizes the expected profit of the optimization model. No additional configuration is required beyond the inherited weight attribute.

Source code in src/odys/domain/objective.py
35
36
37
38
39
40
41
class ProfitTerm(ObjectiveTerm):
    """Represents the expected profit objective across all scenarios.

    This objective term maximizes the expected profit of the optimization
    model. No additional configuration is required beyond the inherited
    weight attribute.
    """