Optimization Plans
ropt.plan
Code for executing optimization plans.
The Plan
class orchestrates optimization workflows by
managing steps and event handlers.
A plan consists of PlanStep
objects, which
define individual actions, and
EventHandler
objects, which process and
store data generated during execution. Both steps and event handlers are
implemented using a plugin mechanism, making it easy to
extend the range of supported actions and data processing. The ropt
library
provides default implementations through the default plan
handler and default plan
step plugins. These provide
basic steps and event handlers to support a wide range of optimization
workflows.
Setting up and executing a Plan
object for simple optimization cases can be
complex. The BasicOptimizer
class simplifies this
process by providing a convenient way to build and execute straightforward plans
involving a single optimization.
ropt.plan.Plan
Plan class for executing optimization workflows.
The Plan
object is the core component for executing optimization workflows.
It orchestrates the execution of individual steps, manages evaluators for
function computations, and processes data and results through event handlers.
Building a Plan:
A Plan
is constructed by adding three main types of components, typically
instantiated via the PluginManager
:
- Steps (
PlanStep
): These define individual actions or operations within the optimization workflow. Steps are added using theadd_step
method. - Event Handlers (
EventHandler
): These components process data, track results, or react to events emitted during plan execution. Event handlers are added using theadd_event_handler
method. - Evaluators (
Evaluator
): These are responsible for performing function evaluations (e.g., objective functions, constraints). Evaluators are added using theadd_evaluator
method and can be passed to steps that need them.
Tags:
Steps, event handlers, and evaluators can be assigned one or more tags.
These tags can be used to identify the components instead of their unique
IDs. Unlike ID's, tags do not need to be unique. This is useful when the
components are created dynamically or if multiple components are to be
identified as a group. For example, when specifying the source of events
that a handler should process, its sources
argument may contain both
component objects, which identifies by their ID, or tags, which could refer
to multiple components that have that tag.
Executing a Plan:
Once a plan is assembled, the run
method can be invoked for each step individually. This approach allows for
the integration of complex logic and custom functions, leveraging the full
capabilities of Python.
PluginManager:
A PluginManager
object can be provided that
is used by the plan object to find and instantiate step, event handler, and
evaluator objects. This manager can also be used by these components to
implement further plugin-based functionality.
Events:
Steps can communicate events by retrieving a list of handlers using the
get_event_handlers
method. Event
handlers can respond to these events, enabling actions such as processing
optimization results. Event handlers are added to the plan using the
add_event_handler
method. To connect
the event handlers to steps, they generally accept a set of steps via the
sources
argument. The steps must be part of the same plan, or a child plan
(if existent).
Evaluators:
Evaluators (Evaluator
) are key
components responsible for performing function evaluations, such as
computing objective functions or constraint values. They are added to the
plan using the add_evaluator
method. They
connect to the steps in the plan, or in child plans, via the clients
argument.
Nested Plans:
Multiple plans can be defined. A step within one plan can trigger the
execution of another plan, enabling nested workflows. In nested plans, the
set_parent
method establishes a parent-child
relationship. This allows events to propagate up the hierarchy to the parent
plan.
Aborting a Plan:
A plan's execution can be terminated, either programmatically from within a
step or event handler, or externally by directly calling the
abort
method. The
aborted
property can be used to check if a plan
has been aborted.
Handler Data:
Individual event handlers may store values that they accumulate or calculate
from the events that they handle. Code outside of the event handlers, such
as the optimization workflow code that runs the steps, can set and retrieve
these values using the []
operator.
aborted
property
Check if the plan was aborted.
Determines whether the plan's execution has been aborted.
Returns:
Name | Type | Description |
---|---|---|
bool |
bool
|
|
plugin_manager
property
Return the plugin manager.
Retrieves the PluginManager
object
associated with this plan.
Returns:
Type | Description |
---|---|
PluginManager
|
The plugin manager stored by the plan. |
__init__
Initialize a plan object.
Constructs a new plan, associating it with an evaluator, and optionally with a plugin manager and/or a parent plan.
The plugin_manager
is used by the plan, and possibly by steps and
event handlers to add plugin functionality.
If a parent
plan is specified, this plan becomes a child, enabling
communication up the plan hierarchy.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
plugin_manager
|
PluginManager
|
A plugin manager. |
required |
parent
|
Plan | None
|
An optional parent plan. |
None
|
add_event_handler
add_event_handler(
name: str,
tags: set[str] | None = None,
sources: set[PlanComponent | str] | None = None,
**kwargs: Any,
) -> EventHandler
Add an event handler to the plan.
Constructs and registers an event handler with the plan. The handler's
type is determined by the provided name
, which the plugin system uses
to locate the corresponding handler class. Any additional keyword
arguments are passed to the handler's constructor.
The sources
parameter acts as a filter, determining which plan steps
this event handler should listen to. It should be a set containing the
PlanStep
instances whose event you want to receive. When an event is
received, this event handler checks if the step that emitted the event
(event.source
) is present in the sources
set. If sources
is
None
, events from all sources will be processed.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
name
|
str
|
The name of the event handler to add. |
required |
tags
|
set[str] | None
|
Optional tags |
None
|
sources
|
set[PlanComponent | str] | None
|
The steps whose events should be processed. |
None
|
kwargs
|
Any
|
Additional arguments for the handler's constructor. |
{}
|
Returns:
Type | Description |
---|---|
EventHandler
|
The newly added event handler. |
add_step
Add a step to the plan.
Registers a step with the plan. The step's type is determined by the
provided name
, which the plugin system uses to locate the
corresponding step class. Any additional keyword arguments are passed to
the step's constructor.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
name
|
str
|
The name of the step to add. |
required |
tags
|
set[str] | None
|
Optional tags |
None
|
kwargs
|
Any
|
Additional arguments for the step's constructor. |
{}
|
Returns:
Type | Description |
---|---|
PlanStep
|
The newly added step. |
add_evaluator
add_evaluator(
name: str,
tags: set[str] | None = None,
clients: set[PlanComponent | str] | None = None,
**kwargs: Any,
) -> Evaluator
Add an evaluator object to the plan.
Creates an evaluator of a type that is determined by the provided name
,
which the plugin system uses to locate the corresponding evaluator class.
Any additional keyword arguments are passed to the evaluators's constructor.
The clients
parameter acts as a filter, determining which plan steps
this evaluator should serve. It should be a set containing the
PlanStep
instances that should be handled. When an evaluation is
requested, this evaluator checks if the step is present in the client
set.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
name
|
str
|
The name of the evaluator to add. |
required |
tags
|
set[str] | None
|
Optional tags |
None
|
clients
|
set[PlanComponent | str] | None
|
The clients that should be served by this evaluator. |
None
|
kwargs
|
Any
|
Additional arguments for the evaluators's constructor. |
{}
|
Returns:
Type | Description |
---|---|
Evaluator
|
The new evaluator object. |
run_step
Run a step in the plan.
Executes a specific step within the plan. The step's run
method is
called with the provided keyword arguments. If the plan has been
aborted, a PlanAborted
exception is
raised before the step is executed.
The step is executed only once. The value returned by the step's run
method is returned by this method.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
step
|
PlanStep
|
The step to run. |
required |
kwargs
|
Any
|
Additional arguments to pass to the step's |
{}
|
Returns:
Name | Type | Description |
---|---|---|
Any |
Any
|
The value returned by the step's |
Raises:
Type | Description |
---|---|
AttributeError
|
If the provided |
PlanAborted
|
If the plan has been aborted. |
get_event_handlers
get_event_handlers(
source: PlanComponent, event_types: set[EventType]
) -> dict[EventType, list[Callable[[Event], None]]]
Get the event handlers for a given source and event types.
When this method is called, all event handlers associated with the plan
are searched for those that handle the source
. Then, if the plan has a
parent, the parent plan's get_event_handlers
method is also called,
find handlers further up the hierarchy.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
source
|
PlanComponent
|
The source of the event. |
required |
event_types
|
set[EventType]
|
The event types that should be handled. |
required |
Returns:
Type | Description |
---|---|
dict[EventType, list[Callable[[Event], None]]]
|
A mapping of event types to a list of suitable handlers. |
get_evaluator
Retrieve the appropriate evaluator for a given client step.
This method searches for an Evaluator
that is configured to serve the specified client
(PlanStep
). The search starts in the
current plan and, if no suitable evaluator is found and a parent plan
exists, continues recursively up the plan hierarchy.
An evaluator is considered suitable the id
or tags
of the client
step is present in the clients
set of the evaluator.
The method expects to find exactly one suitable evaluator.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
client
|
PlanComponent
|
The step for which an evaluator is being requested. |
required |
Returns:
Type | Description |
---|---|
Evaluator
|
The single evaluator instance configured to serve the client. |
Raises:
Type | Description |
---|---|
AttributeError
|
If no suitable evaluator is found, or if multiple suitable evaluators are found. |
abort
Abort the plan.
Prevents further steps in the plan from being executed. This method does not interrupt a currently running step but ensures that no subsequent steps will be initiated. It can be used to halt the plan's execution due to a step failure or external intervention.
The aborted
property can be used to check if
the plan has been aborted.
set_parent
Set the parent of the plan.
Establishes a parent-child relationship between this plan and another
plan. This enables event propagation up the plan hierarchy. It also
allows the get_evaluation
method to inquire the parent for an
evaluator object, if necessary.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
parent
|
Plan
|
The parent plan. |
required |
ropt.plan.Event
dataclass
Stores data related to an optimization event.
During the execution of an optimization plan, events are triggered to signal
specific occurrences. Callbacks can be registered to react to these events
and will receive an Event
object containing relevant information.
The specific data within the Event
object varies depending on the event
type. See the EventType
documentation for details.
Attributes:
Name | Type | Description |
---|---|---|
event_type |
EventType
|
The type of event that occurred. |
data |
dict[str, Any]
|
A dictionary containing additional event-specific data. |