Topology Optimizer#
toop_engine_topology_optimizer.interfaces.messages.commands
#
Defines the interaction between the optimizer and a backend.
The backend will send commands in the form of messages to the optimizer, which will trigger a certain behaviour. The Optimizer will respond with results, for this see results.py
StartOptimizationCommand
#
Bases: BaseModel
Command with parameters for starting an optimization run.
message_type
class-attribute
instance-attribute
#
The command type for deserialization, don't change this
dc_params
class-attribute
instance-attribute
#
dc_params = DCOptimizerParameters()
The parameters for the DC optimizer
ac_params
class-attribute
instance-attribute
#
ac_params = ACOptimizerParameters()
The parameters for the AC optimizer
grid_files
instance-attribute
#
The grid files to load, where each gridfile represents one timestep. The grid files also include coupling information for the timesteps.
optimization_id
instance-attribute
#
The id of the optimization run, used to identify the optimization run in the results. Should stay the same for the whole optimization run and should be equal to the kafka event key
ShutdownCommand
#
Command
#
Bases: BaseModel
Base class for all commands to the optimizer.
command
class-attribute
instance-attribute
#
The actual command
uuid
class-attribute
instance-attribute
#
uuid = Field(default_factory=lambda: str(uuid.uuid4()))
A unique identifier for the command message, used to avoid duplicate processing on optimizer side
timestamp
class-attribute
instance-attribute
#
When the command was sent
validate_first_gridfile_uncoupled
#
Check that the first gridfile is uncoupled
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/interfaces/messages/commands.py
toop_engine_topology_optimizer.interfaces.messages.dc_params
#
The DC optimizer is the GPU stage where massive amounts of topologies are being checked.
This holds the parameters to start the optimization. Some parameters can not be changed (mainly the names of the kafka streams) and are included in the command line start parameters instead.
BatchedMEParameters
#
Bases: BaseModel
Parameters for starting the batched genetic algorithm (In this case Map-Elites)
iterations_per_epoch
class-attribute
instance-attribute
#
The number of iterations per epoch
random_seed
class-attribute
instance-attribute
#
The random seed to use for reproducibility
enable_nodal_inj_optim
class-attribute
instance-attribute
#
Whether to enable the nodal injection optimization stage. This can optimize PSTs (currently) and soon HVDC and potentially even redispatch clusters. Using this will increase runtime.
enable_parallel_pst_group_optim
class-attribute
instance-attribute
#
Whether grouped PST optimization should enforce shared tap updates for configured parallel PST groups.
n_worst_contingencies
class-attribute
instance-attribute
#
The number of worst contingencies to consider in the scoring function. This is used to determine the worst cases for overloads.
enable_bb_outage
class-attribute
instance-attribute
#
Whether the optimizer should include busbar outage effects in scoring. If the preprocessed grid file does not contain busbar outage data, this flag is ignored.
bb_outage_as_nminus1
class-attribute
instance-attribute
#
Whether busbar outages are handled as additional N-1 cases. If this is True, they are just part of the N-1 matrix and will contribute to normal overload energy, max load, etc. If this is False, a separate busbar outage penalty is computed and added to the scores. If no busbar outage data is provided in the grid model, this parameter will be ignored.
clip_bb_outage_penalty
class-attribute
instance-attribute
#
Whether busbar outage penalties are clipped at 0. This is only relevant in case of bb_outage_as_nminus1=False, where busbar outage penalties are added to the scores as a separate term. If this is True, the busbar outage penalty will be clipped at 0, meaning that topologies that improve the busbar outage penalty will not be rewarded for it. If this is False, topologies that improve the busbar outage penalty will receive a negative penalty, which can lead to higher scores and thus be rewarded by the optimizer. If no busbar outage data is provided in the grid model or if bb_outage_as_nminus1 is True, this parameter will be ignored.
bb_outage_more_islands_penalty
class-attribute
instance-attribute
#
Islanding penalty used for busbar outage baseline comparisons. This is only relevant in case of bb_outage_as_nminus1=False, where busbar outage penalties are added to the scores as a separate term. If a busbar outage computation fails due to grid splits/islanding, this penalty will be applied to the score proportional to the number of islands. If no busbar outage data is provided in the grid model or if bb_outage_as_nminus1 is True, this parameter will be ignored.
mutation_repetition
class-attribute
instance-attribute
#
More chance to get unique mutations by mutating multiple copies of the repertoire
random_topo_prob
class-attribute
instance-attribute
#
The probability to create a random topology instead of mutating the existing one. This can help to escape local minima.
n_subs_mutated_lambda
class-attribute
instance-attribute
#
The number of substations to mutate in a single iteration is drawn from a poisson with this lambda
add_split_prob
class-attribute
instance-attribute
#
The probability to add an additional split to a substation, applied after the number of substations to mutate is drawn
change_split_prob
class-attribute
instance-attribute
#
The probability to change an existing split in a substation
remove_split_prob
class-attribute
instance-attribute
#
The probability to remove a split from a substation
add_disconnection_prob
class-attribute
instance-attribute
#
The probability to add a disconnection, applied after the number of disconnections to mutate is drawn
change_disconnection_prob
class-attribute
instance-attribute
#
The probability to change an existing disconnection
remove_disconnection_prob
class-attribute
instance-attribute
#
The probability to remove an existing disconnection
pst_mutation_sigma
class-attribute
instance-attribute
#
The sigma to use for the normal distribution that mutates the PST taps. The mutation is applied by adding a random value drawn from this distribution to the current tap position. A value of 0.0 means no PST mutation.
pst_mutation_probability
class-attribute
instance-attribute
#
The probability for an individual PST to be selected for mutation. A value of 0.0 means no PST mutation. A value of 1.0 means all PSTs will be mutated.
pst_reset_probability
class-attribute
instance-attribute
#
The probability for an individual PST to be reverted to its initial set point. A value of 0.0 means no reset. A value of 1.0 means all PSTs will be reset. This only has an effect if the PST mutation is enabled, because the taps start at their initial set point and the mutation is the only thing that moves them away from it.
proportion_crossover
class-attribute
instance-attribute
#
The proportion of the first topology to take in the crossover
crossover_mutation_ratio
class-attribute
instance-attribute
#
The ratio of crossovers to mutations
target_metrics
class-attribute
instance-attribute
#
The list of metrics to optimize for with their weights
observed_metrics
class-attribute
instance-attribute
#
observed_metrics = (
"max_flow_n_0",
"overload_energy_n_0",
"overload_energy_limited_n_0",
"max_flow_n_1",
"overload_energy_n_1",
"overload_energy_limited_n_1",
"split_subs",
"switching_distance",
)
The observed metrics, i.e. which metrics are to be computed for logging purposes. The target_metrics and me_descriptors must be included in the observed metrics and will be added automatically by the validator if they are missing
me_descriptors
class-attribute
instance-attribute
#
me_descriptors = (
DescriptorDef(metric="split_subs", num_cells=5),
DescriptorDef(
metric="switching_distance", num_cells=45
),
)
The descriptors to use for MAP-Elites. This includes a metric that determines the cell index and a number of cells. If the metric exceeds the number of cells, it will be clipped to the largest cell index. Currently, this must be integer metrics
cell_depth
class-attribute
instance-attribute
#
When applicable, each cell contains cell_depth unique topologies. Use 1 to retain the original map-elites behaviour
infer_missing_observed_metrics
#
Add potentially missing target and descriptor metrics to the observed metrics.
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/interfaces/messages/dc_params.py
probabilities_less_than_one
#
Check that the mutation probabilities are not larger than 1.
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/interfaces/messages/dc_params.py
pst_mutation_enabled_consistently
#
Check that the PST mutation is either fully enabled or fully disabled.
Both a sigma of 0 and a mutation probability of 0 disable the PST mutation completely. The taps are initialized at their starting values and the mutation is the only thing that moves them away from it, so a reset probability has no effect on its own either. We therefore require all three parameters to be 0 as soon as one of the two disables the mutation, instead of silently ignoring the remaining ones.
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/interfaces/messages/dc_params.py
grouped_pst_optimization_requires_nodal_optimization
#
Ensure grouped PST optimization is only enabled together with nodal injection optimization.
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/interfaces/messages/dc_params.py
me_descriptors_cannot_be_empty
#
Check that MeDescriptors tuple is not empty.
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/interfaces/messages/dc_params.py
LoadflowSolverParameters
#
Bases: BaseModel
Parameters for the loadflow solver.
max_num_splits
class-attribute
instance-attribute
#
The maximum number of splits per topology
max_num_disconnections
class-attribute
instance-attribute
#
The maximum number of disconnections to apply per topology
batch_size
class-attribute
instance-attribute
#
The batch size for the genetic algorithm
distributed
class-attribute
instance-attribute
#
Whether to run the genetic algorithm distributed over multiple devices
cross_coupler_flow
class-attribute
instance-attribute
#
Whether to compute cross-coupler flows
DCOptimizerParameters
#
Bases: BaseModel
The set of parameters that are used in the DC optimizer only
ga_config
class-attribute
instance-attribute
#
ga_config = BatchedMEParameters()
The configuration options for the genetic algorithm
loadflow_solver_config
class-attribute
instance-attribute
#
loadflow_solver_config = LoadflowSolverParameters()
The configuration options for the loadflow solver
double_limits
class-attribute
instance-attribute
#
The double limits for the optimization, if they should be updated
summary_frequency
class-attribute
instance-attribute
#
The frequency to push back results, based on number of iterations. Default is after every 10 iterations.
check_command_frequency
class-attribute
instance-attribute
#
The frequency to check for new commands, based on number of iterations. Should be a multiple of summary_frequency
max_num_splits_unequal_zero_if_descriptor_exists
#
Check that max_num_splits is larger than the MeDescriptor size-1 of split_subs.
If the map elites descriptor contains split_subs, max_num_splits must be larger
than 0. Otherwise, the computation of the BSDF will fail.
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/interfaces/messages/dc_params.py
toop_engine_topology_optimizer.interfaces.messages.ac_params
#
The parameters for the AC optimizer.
On AC, some subtelties are different to the DC optimization such as that the optimization is not batched, and the parameters are slightly different.
ACGAParameters
#
Bases: BaseModel
Parameters for the AC genetic algorithm
runtime_seconds
class-attribute
instance-attribute
#
The maximum runtime of the AC optimization in seconds
n_worst_contingencies
class-attribute
instance-attribute
#
How many worst contingencies to consider for the initial metrics, i.e. the top k contingencies that are used to compute the initial metrics. This is used to compute the top_k_overloads_n_1
include_non_converging_loadflows_in_worst_k
class-attribute
instance-attribute
#
Whether non-converging contingencies should always be appended to the worst-k contingency cases. These will be added on top of the worst-k contingencies that are selected based on the overload energy. So if k=20 and there are 3 non-converging contingencies, the worst-k will contain 23 contingencies in total. If this is set to False, the non-converging contingencies will be ignored and the worst-k will only contain the contingencies with the highest overload energy.
runner_processes
class-attribute
instance-attribute
#
How many processes to spawn for computing the N-1 cases in each timestep in parallel. Note that this multiplies with contingency_processes and you might run out of memory if you set both too high
contingency_processes
class-attribute
instance-attribute
#
How many processes to spawn for computing the contingencies of each strategy in parallel. Note that this multiplies with runner_processes and you might run out of memory if you set both too high
worst_k_runner_processes
class-attribute
instance-attribute
#
How many processes to spawn per topology during the worst-k stage.
worst_k_contingency_processes
class-attribute
instance-attribute
#
How many processes to spawn for computing the contingencies of each strategy in parallel during the worst-k stage.
remaining_loadflow_wait_seconds
class-attribute
instance-attribute
#
Maximum time to keep collecting non-rejected strategies before starting the remaining contingency evaluation, even if the survivor threshold has not been reached.
filter_strategy
class-attribute
instance-attribute
#
The filter strategy to use for the optimization, used to filter out strategies based on the discriminator, median or dominator filter.
enable_ac_rejection
class-attribute
instance-attribute
#
Whether to enable the AC rejection, i.e. no messages will be sent to the results topic in case of non-acceptance.
reject_convergence_threshold
class-attribute
instance-attribute
#
The rejection threshold for the convergence rate, i.e. the split case must have at most the same amount of non converging loadflows as the unsplit case or it will be rejected.
reject_overload_threshold
class-attribute
instance-attribute
#
The rejection threshold for the overload energy improvement, i.e. the split case must have at least 5% lower overload energy than the unsplit case or it will be rejected.
reject_critical_branch_threshold
class-attribute
instance-attribute
#
The rejection threshold for the critical branches increase, i.e. the split case must have less than 10% more critical branches than the unsplit case or it will be rejected.
reject_voltage_jump_threshold
class-attribute
instance-attribute
#
The rejection threshold for the voltage jump count increase, i.e. the split case must have less than 10% more critical voltage jumps than the unsplit case or it will be rejected.
reject_critical_va_diff_threshold
class-attribute
instance-attribute
#
The rejection threshold for the critical voltage-angle-difference count increase, i.e. the split case must have less than 10% more critical voltage-angle differences than the unsplit case or it will be rejected.
enable_critical_voltage_rejection
class-attribute
instance-attribute
#
Whether to use critical voltage jumps and voltage-angle-difference counts as an acceptance/rejection criterion.
The associated metrics are still computed and reported when this flag is disabled.
critical_voltage_jump_percent
class-attribute
instance-attribute
#
Voltage jumps larger than this percentage are counted as critical in the AC metrics.
critical_va_diff_degree
class-attribute
instance-attribute
#
Voltage angle differences larger than this value in degrees are counted as critical in the AC metrics.
early_stop_validation
class-attribute
instance-attribute
#
Whether to enable early stopping during the optimization process.
early_stopping_non_convergence_percentage_threshold
class-attribute
instance-attribute
#
The threshold for the early stopping criterion, i.e. if the percentage of non-converging cases is greater than this value, the ac validation will be stopped early.
max_initial_wait_seconds
class-attribute
instance-attribute
#
The maximum amount of seconds to wait for the initial DC results. If no results have arrived within this time, we assume the DC optimizer had some problem and abort the optimization run.
ACOptimizerParameters
#
Bases: BaseModel
The set of parameters that are used in the AC optimizer only
initial_loadflow
class-attribute
instance-attribute
#
If an initial AC loadflow was computed before the start of the optimization run, this can be passed and will be used e.g. to compute double limits. It will be sent back through the initial topology push.
ga_config
class-attribute
instance-attribute
#
ga_config = ACGAParameters()
The genetic algorithm configuration
toop_engine_topology_optimizer.interfaces.messages.results
#
Defines the schema for the messages sent to the results topic.
The optimizer will push results to a results topic.
RejectionCriterion
module-attribute
#
RejectionCriterion = Literal[
"convergence",
"voltage-magnitude",
"voltage-angle",
"overload-energy",
"critical-branch-count",
"error",
"other",
]
OptimizationStoppedReason
module-attribute
#
OptimizationStoppedReason = Literal[
"error",
"stopped",
"converged",
"ac-not-converged",
"dc-not-started",
"command-too-old",
"unknown",
]
ResultUnion
module-attribute
#
ResultUnion = Union[
TopologyPushResult,
TopologyRejectionResult,
OptimizationStoppedResult,
OptimizationStartedResult,
]
Metrics
#
Bases: BaseModel
Result message containing the metrics of the optimization.
Topology
#
Bases: BaseModel
A results class encapsulating a single topology for a single timestep in action index format.
actions
instance-attribute
#
The branch/injection reconfiguration actions as indices into the action set. This can only be parsed when combined with the action set. This includes only actions that are actually used, i.e. no int_max entries. Actions will be automatically sorted in ascending order, as the order does not matter and we want to avoid duplicates.
disconnections
instance-attribute
#
The applied disconnections in this topology as an index into the disconnectable branches set in the action set. This includes only disconnections that are actually used, i.e. no int_max entries. Disconnections will be automatically sorted in ascending order, as the order does not matter and we want to avoid duplicates.
pst_setpoints
instance-attribute
#
The setpoints for the PSTs if they have been computed.
These are the taps as they are stored in the original grid model, i.e. if a PST has a tap range from -20 to 20 then this can take all these values. Note that inside the dc optimizer, taps are always starting with 0 and have to be converted by adding grid_model_low_tap.
The list has the length of the number of controllable PSTs in the grid model and the nth entry corresponds to the nth controllable PST in the network data.
If the PST taps were not optimized, then this is None. Empty list is only allowed if there are no controllable PSTs in the grid model.
metrics
instance-attribute
#
The metrics of this topology and timestep. While the optimizer might optimize for all timesteps, these metrics should be broken down on a per-timestep basis if possible as they will be summed up before processing.
loadflow_results
class-attribute
instance-attribute
#
The loadflow results of this topology in this timestep, if they were computed. Mostly for AC results, as for DC we don't need to send full loadflow results every time. This is a reference to the loadflow results stored on disk as sending them every time would be too large.
sort_actions
classmethod
#
Sort the actions in ascending order. This is important for the hashing.
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/interfaces/messages/results.py
sort_disconnections
classmethod
#
Sort the disconnections in ascending order. This is important for the hashing.
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/interfaces/messages/results.py
Strategy
#
Bases: BaseModel
A series of topologies over multiple timesteps. This is basically a list of topologies,
one for every timestep.
TopologyRejectionReason
#
Bases: BaseModel
The reason for rejecting a topology including a criterion that was violated and further data.
description
class-attribute
instance-attribute
#
A more detailed description of the rejection, e.g. which lines were overloaded, etc.
value_after
instance-attribute
#
The value of the metric that caused the rejection after applying the strategy.
Depending on the criterion, this has different meanings:
- For convergence this is the number of non-converging loadflows.
- For voltage magnitude this is the maximum voltage violation in p.u.
- For voltage angle this is the maximum voltage angle violation in degrees.
- For overload energy this is the overload in MW.
- For critical branch count this is the number of critical branches, i.e. branches above their operational limit.
value_before
instance-attribute
#
The value of the metric that caused the rejection before applying the strategy.
Meaning of the value is similar to value_after dependent on the criterion.
threshold
class-attribute
instance-attribute
#
The threshold for rejection that was set in the AC configuration, if applicable.
early_stopping
class-attribute
instance-attribute
#
Whether this rejection was part of an early stopping run, i.e. only a subset of the cases were computed to determine the rejection. In that case, the value_before and value_after are only based on the subset of cases that were computed.
TopologyRejectionResult
#
Bases: BaseModel
A rejection of a topology in a later stage.
For example if the DC optimizer found a topology as sensible but the AC optimizer rejects it, this will result in a rejection result. For the moment, this is only used in the backend to gather statistics on rejections, however a future version could implement some sort of learning algorithm that uses these rejections to try and extrapolate the reasons.
message_type
class-attribute
instance-attribute
#
The result type, don't change this
strategy
instance-attribute
#
The strategy that is rejected. Note that only a single strategy is rejected at a time, if multiple were rejected then send multiple messages.
epoch
class-attribute
instance-attribute
#
The epoch of the optimization run. Enables plotting the results over time on backend side.
reason
instance-attribute
#
The reason for the rejection along with additional data
This is separated into a different class to make it easier to pass along inside the code, as it turns out often it is not required to read the strategy itself.
TopologyPushResult
#
Bases: BaseModel
A message that pushes new topology results. These must include the topo-vects
and disconnections and may include loadflow results.
OptimizationStoppedResult
#
Bases: BaseModel
A message that is sent if the optimization was successfully stopped.
message_type
class-attribute
instance-attribute
#
The result type, don't change this
reason
class-attribute
instance-attribute
#
The reason why the optimization was stopped
Possible values: - Error means an unexpected exception was raised/the optimizer crashed - Stopped means it was stopped through a command - Converged means it stopped after hitting the convergence criterium - ac-not-converged means the AC convergence in the base grid was too poor to run an AC optimization, this will only be sent by the AC optimizer. - dc-not-started means the DC optimization results did not arrive, potentially due to a suspected failure on dc side and the optimization was abandoned. This will only be sent by the AC optimizer. - command-too-old means the command was too old and was skipped.
message
class-attribute
instance-attribute
#
A message that can be sent with the stop message, i.e. an error message
epoch
class-attribute
instance-attribute
#
The epoch of the optimization run when it was stopped.
OptimizationStartedResult
#
Bases: BaseModel
Result message for when an optimization run has just started.
message_type
class-attribute
instance-attribute
#
The result type, don't change this
initial_topology
instance-attribute
#
The initial topology including the starting metrics of the optimization. This is the topology without any splits or disconnections
initial_stats
class-attribute
instance-attribute
#
The initial statistics of the optimization run, i.e. the number of disconnections, etc. This is only filled by the DC optimizer and will hold one entry for each timestep in the initial topology.
Result
#
Bases: BaseModel
A generic result message sent back from the optimizer to the results topic.
Results can be read by either the backend or another optimizer in the waterfall.
result
class-attribute
instance-attribute
#
The actual result message
instance_id
class-attribute
instance-attribute
#
The instance id of the optimizer that created this result
uuid
class-attribute
instance-attribute
#
uuid = Field(default_factory=lambda: str(uuid.uuid4()))
A unique identifier for this result message, used to avoid duplicates during processing
timestamp
class-attribute
instance-attribute
#
When the result was sent
get_topology_rejection_message
#
Condense a TopologyRejectionReason into a human-readable message for logging purposes.
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/interfaces/messages/results.py
toop_engine_topology_optimizer.interfaces.messages.heartbeats
#
Contains the heartbeat messages that are sent by the worker.
HeartbeatUnion
module-attribute
#
HeartbeatUnion = Union[
IdleHeartbeat,
LogMessage,
OptimizationStatsHeartbeat,
OptimizationStartedHeartbeat,
StartupHeartbeat,
]
OptimizationStartedHeartbeat
#
OptimizationStatsHeartbeat
#
Bases: BaseModel
Optimization statistics to track the progress of the optimization.
IdleHeartbeat
#
Bases: BaseModel
A heartbeat that is sent by the optimizer every now and then.
message_type
class-attribute
instance-attribute
#
The message type, don't change this
StartupHeartbeat
#
Bases: BaseModel
A heartbeat that is sent by the optimizer when it starts up but not yet ready to accept optimizations
message_type
class-attribute
instance-attribute
#
The message type, don't change this
LogMessage
#
AC Validation#
toop_engine_topology_optimizer.ac.evolution_functions
#
Implements an adjusted AC evolution
Instead of the original GA evolution which only knows mutate and crossover, we introduce the following operations: - The pull operator will take a promising topology from the DC repertoire and re-evaluate it on AC. The notion of promising is defined through a interest-scoring function which tries to balance the explore/exploit trade-off.
select_repertoire
#
Select the topologies that are suitable for mutation and crossover
In this case, all topologies that satisfy the filter criteria are suitable, however a check after the mutate is necessary to ensure that the topology is not already in the database.
The unsplit strategy is never selected for mutation or crossover.
| PARAMETER | DESCRIPTION |
|---|---|
optimization_id
|
The optimization ID to filter for
TYPE:
|
optimizer_type
|
The optimizer types to filter for (whitelist)
TYPE:
|
without_children_on
|
If the topology already spawned a child on any of these optimizer types, it will be filtered out.
TYPE:
|
session
|
The database session to use
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[ACOptimTopology]
|
The topologies that are suitable for mutation and crossover |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/evolution_functions.py
get_unsplit_ac_topology
#
Get the unsplit AC topology for the given optimization ID
| PARAMETER | DESCRIPTION |
|---|---|
optimization_id
|
The optimization ID to filter for
TYPE:
|
session
|
The database session to use
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
ACOptimTopology
|
The unsplit AC topology for the given optimization ID, or None if not found |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/evolution_functions.py
default_scorer
#
Return raw fitness values for the default lower-is-better AC selection.
| PARAMETER | DESCRIPTION |
|---|---|
metrics
|
The metrics DataFrame to score
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Series
|
The topology fitness values. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/evolution_functions.py
get_contingency_indices_from_ids
#
Map contingency ids to their indices in the N-1 definition.
This is a helper method used in update_initial_metrics_with_worst_k_contingencies method.
| PARAMETER | DESCRIPTION |
|---|---|
case_ids
|
A list of contingency ids for a specific topology.
TYPE:
|
n_minus1_definition
|
The N-1 definition containing the contingencies.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[int]
|
A list of indices of the contingencies in the N-1 definition. If a contingency id is not found, it will be skipped. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/evolution_functions.py
pull
#
Pull a promising topology from the DC repertoire to AC
This only copies the topology without any changes other than setting the optimizer type to AC. This function takes a list of selected DC topologies and creates corresponding AC topologies by copying relevant attributes, setting the optimizer type to AC, and merging contingency case indices from both the DC and unsplit AC topologies.
| PARAMETER | DESCRIPTION |
|---|---|
selected_strategy
|
The selected strategy to pull
TYPE:
|
session
|
The database session to use, by default None. The session object is used to fetch the unsplit AC topology which is then used to add the critical contingency cases to the pulled strategy. These critical cases can then be used for early stopping of AC N-1 contingency analysis.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
ACStrategy
|
The a copy of the input topologies with the optimizer type set to AC |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/evolution_functions.py
evolution
#
Perform the AC evolution.
| PARAMETER | DESCRIPTION |
|---|---|
rng
|
The random number generator to use
TYPE:
|
session
|
The database session to use, will write the new topologies to the database
TYPE:
|
optimization_id
|
The optimization ID to filter for
TYPE:
|
max_retries
|
The maximum number of retries to perform if a strategy is already in the database
TYPE:
|
batch_size
|
Number of unevaluated topologies to sample and convert to AC in one try.
TYPE:
|
filter_strategy
|
The filter strategy to use for the optimization, used to filter out strategies that are too far away from the original topology.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
ACStrategy
|
The strategy that was created during the evolution or an empty list if something went wrong at all retries |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/evolution_functions.py
evolution_try
#
Perform a single try of the AC evolution.
| PARAMETER | DESCRIPTION |
|---|---|
rng
|
The random number generator to use
TYPE:
|
session
|
The database session to use, will write the new topologies to the database
TYPE:
|
optimization_id
|
The optimization ID to filter for
TYPE:
|
batch_size
|
Number of unevaluated topologies to sample and convert to AC.
TYPE:
|
filter_strategy
|
The filter strategy to use for the optimization, used to filter out strategies that are too far away from the original topology.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[ACOptimTopology]
|
The list of topologies that were created during the evolution or an empty list if something went wrong during the try |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/evolution_functions.py
toop_engine_topology_optimizer.ac.listener
#
A listener that listens for new topologies on a kafka result stream and saves them to db
This is intended for usage both in the AC optimizer and the backend, as they both listen for topologies on the result kafka stream. The backend has some further logic as it watches all optimizations and might change the state of the optimization to "running" if it receives a start optimization result and "stopped" if a stop optimization result is received.
One of the requirements is that the AC listener will only want to listen to a single optimization_id and not to messages by itself. Hence a filtering mechanic is added.
finish_optimization
#
Mark an optimization as finished in the database.
If it was a DC optimization, this function just saves an entry to DB. If it was an AC optimization, this function also deletes all topologies from the database that belong to this optimization, as they are no longer relevant and we don't want to keep them around.
| PARAMETER | DESCRIPTION |
|---|---|
db
|
The database session to use for saving the finished optimization
TYPE:
|
optimization_id
|
The optimization ID of the finished optimization as sent via kafka
TYPE:
|
optimizer_type
|
Which optimizer type has finished
TYPE:
|
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/listener.py
poll_results_topic
#
Poll the results topic for new topologies to store in the DB
We store topologies from all optimization jobs, as it could be that we will later optimize the same job in this worker.
| PARAMETER | DESCRIPTION |
|---|---|
db
|
The database session to use for saving the topologies
TYPE:
|
consumer
|
The kafka consumer to poll messages from. It should already be subscribed to the result topic.
TYPE:
|
first_poll
|
If True, we assume the optimizatin has just started and we can afford to wait for the first DC results for a longer time (30 seconds). If False, we assume the optimization is already running and we don't want to block the consumer for too long (100 ms), by default True
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
dict[str, int]
|
A dictionary with the number of topologies added to the database for each optimization ID |
list[str]
|
A list of optimization IDs for which a stop optimization result was received. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/listener.py
toop_engine_topology_optimizer.ac.optimizer
#
Implements initialize and run_epoch functions for the AC optimizer
AcNotConvergedError
#
Bases: Exception
An exception that is raised when the AC optimization did not converge in the base grid
update_initial_metrics_with_worst_k_contingencies
#
update_initial_metrics_with_worst_k_contingencies(
initial_loadflow,
initial_metrics,
worst_k,
include_non_converging_loadflows=True,
)
Update the initial metrics with the worst k contingencies.
This function computes the worst k contingencies for each timestep in the initial loadflow results and updates the initial metrics with the case ids and the top k overloads. This way, a baseline for the worst k contingencies to compare to is established, i.e. in the initial loadflow results these are the reference, disregarding the worst k for the specific strategy.
| PARAMETER | DESCRIPTION |
|---|---|
initial_loadflow
|
The initial loadflow results containing the branch results.
TYPE:
|
initial_metrics
|
The initial metrics for each timestep.
TYPE:
|
worst_k
|
The number of worst contingencies to consider for the initial metrics.
TYPE:
|
include_non_converging_loadflows
|
Whether non-converging contingencies should be appended to the worst-k contingency list, by default True.
TYPE:
|
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/optimizer.py
make_runner
#
make_runner(
action_set,
nminus1_definition,
grid_file,
n_processes,
batch_size,
processed_gridfile_fs,
lf_params=None,
)
Initialize a runner for a gridfile, action set and n-1 def
| PARAMETER | DESCRIPTION |
|---|---|
action_set
|
The action set to use
TYPE:
|
nminus1_definition
|
The N-1 definition to use
TYPE:
|
grid_file
|
The grid file to use
TYPE:
|
n_processes
|
The number of processes to use, from the ACGAParameters
TYPE:
|
batch_size
|
The batch size to use, if any, from the ACGAParameters
TYPE:
|
processed_gridfile_fs
|
The target filesystem for the preprocessing worker. This contains all processed grid files. During the import job, a new folder import_results.data_folder was created which will be completed with the preprocess call to this function. Internally, only the data folder is passed around as a dirfs. Note that the unprocessed_gridfile_fs is not needed here anymore, as all preprocessing steps that need the unprocessed gridfiles were already done.
TYPE:
|
lf_params
|
The loadflow parameters to use for the runner, if any. This is passed in the preprocessing results and can be used to run the loadflows with the same parameters as the initial loadflow in the preprocessing step. If None, the runner will use default parameters.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
AbstractLoadflowRunner
|
The initialized loadflow runner, either Pandapower or Powsybl |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/optimizer.py
initialize_optimization
#
initialize_optimization(
params,
session,
optimization_id,
grid_file,
loadflow_result_fs,
processed_gridfile_fs,
)
Initialize an optimization run for the AC optimizer
| PARAMETER | DESCRIPTION |
|---|---|
params
|
The parameters for the AC optimizer
TYPE:
|
session
|
The database session to use for storing topologies
TYPE:
|
optimization_id
|
The ID of the optimization run
TYPE:
|
grid_file
|
The grid file to optimize on
TYPE:
|
loadflow_result_fs
|
A filesystem where the loadflow results are stored. Loadflows will be stored here using the uuid generation process and passed as a StoredLoadflowReference which contains the subfolder in this filesystem.
TYPE:
|
processed_gridfile_fs
|
The target filesystem for the preprocessing worker. This contains all processed grid files. During the import job, a new folder import_results.data_folder was created which will be completed with the preprocess call to this function. Internally, only the data folder is passed around as a dirfs. Note that the unprocessed_gridfile_fs is not needed here anymore, as all preprocessing steps that need the unprocessed gridfiles were already done.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
OptimizerData
|
The initial optimizer data |
Strategy
|
The initial strategy |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/optimizer.py
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 | |
get_or_create_initial_strategy
#
Store the initial strategy in the database, reusing an existing row on duplicates.
| PARAMETER | DESCRIPTION |
|---|---|
session
|
The database session to use for storing the topology. The caller is expected to own the surrounding transaction.
TYPE:
|
optimization_id
|
The ID of the optimization run, used to identify the topology in the database.
TYPE:
|
unsplit_topology
|
The initial topology to store, which should already have its strategy hash computed and assigned.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
ACOptimTopology
|
The persisted topology row. If the insert hits a duplicate, the existing database row is returned. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/optimizer.py
wait_for_first_dc_results
#
wait_for_first_dc_results(
results_consumer,
session,
max_wait_time,
optimization_id,
heartbeat_fn,
)
Wait an initial period for DC results to arrive before proceeding with the optimization.
Call this after initialize optimization and before run epoch to ensure that the DC optimizer has started, and avoid the AC optimizer idling while waiting for the first DC results to arrive.
| PARAMETER | DESCRIPTION |
|---|---|
results_consumer
|
The consumer where to listen for DC results
TYPE:
|
session
|
The database session to use for storing topologies
TYPE:
|
max_wait_time
|
The maximum time to wait for DC results, in seconds
TYPE:
|
optimization_id
|
The ID of the optimization run, used to filter the incoming topologies and only proceed when DC results from the correct optimization run arrive. Note that other DC runs could be active.
TYPE:
|
heartbeat_fn
|
A function to send heartbeats while waiting for DC results, as this wait time can be relatively long.
TYPE:
|
| RAISES | DESCRIPTION |
|---|---|
TimeoutError
|
If no DC results arrive within the maximum wait time |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/optimizer.py
persist_topology
#
Persist a topology and return the payload needed for later emission.
This function stores the topology in the database, including the loadflow results if available, and returns the final message payload and scoring result. Emission is handled separately so callers can persist without necessarily sending a result immediately.
| PARAMETER | DESCRIPTION |
|---|---|
topology
|
The topology to persist and send
TYPE:
|
scoring_result
|
The scoring result for the topology, containing the metrics, loadflow results and rejection reason if any
TYPE:
|
optimizer_data
|
The optimizer data containing the session and the loadflow storage function
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
tuple[Topology, TopologyScoringResult]
|
The message payload to emit and the final scoring result after persistence handling. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/optimizer.py
send_topology_result
#
send_topology_result(
topology_message,
scoring_result,
epoch,
enable_ac_rejection,
send_result_fn,
)
Send the persisted topology result to the result topic.
This function sends either a TopologyPushResult or a TopologyRejectionResult depending on the scoring result and the AC rejection settings.
| PARAMETER | DESCRIPTION |
|---|---|
topology_message
|
The topology message to send, containing the actions, metrics and loadflow result reference
TYPE:
|
scoring_result
|
The scoring result for the topology, containing the metrics, loadflow results and rejection reason if any. The rejection reason will be used to determine whether to send a push result or a rejection result
TYPE:
|
epoch
|
The current epoch number.
TYPE:
|
enable_ac_rejection
|
Whether to enable AC rejection. If True, topologies with a rejection reason in the scoring result will be sent as rejections. If False, all topologies will be sent as push results regardless of the scoring result.
TYPE:
|
send_result_fn
|
The function to send results to the result topic, used for sending either the push result or the rejection result depending on the scoring result and AC rejection settings.
TYPE:
|
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/optimizer.py
run_fast_failing_epoch
#
Run one epoch of fast-failing AC evaluation only.
This imports new DC topologies, pulls up to topology_batch_size strategies from the
evolution function, evaluates them with the worst-k fast-failing scorer, and returns the
evaluated strategies together with their early-stage scoring results.
| PARAMETER | DESCRIPTION |
|---|---|
optimizer_data
|
The optimizer data containing the evolution and fast-failing scoring functions.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[ACOptimTopology]
|
The strategies that were pulled and evaluated in the fast-failing stage. |
list[EarlyStoppingStageResult]
|
The corresponding fast-failing scoring results. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/optimizer.py
process_fast_failing_results
#
process_fast_failing_results(
optimizer_data,
topologies,
fast_failing_results,
epoch,
send_result_fn,
)
Process the fast-failing stage, emitting only rejected strategies.
Rejected strategies are persisted immediately and emitted as rejections. Surviving strategies are returned so they can be fully evaluated on the remaining contingencies before any accepted push result is sent.
| PARAMETER | DESCRIPTION |
|---|---|
optimizer_data
|
The optimizer data containing the session and the loadflow storage function.
TYPE:
|
topologies
|
The topologies that were evaluated in the fast-failing stage.
TYPE:
|
fast_failing_results
|
The corresponding fast-failing scoring results, containing the rejection reason if any.
TYPE:
|
epoch
|
The current epoch number, used for logging and for sending in the result messages.
TYPE:
|
send_result_fn
|
The function to send results to the result topic.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[ACOptimTopology]
|
The topologies that passed the fast-failing stage and can proceed to the remaining-contingency evaluation. |
list[EarlyStoppingStageResult]
|
The corresponding fast-failing scoring results for the surviving topologies. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/optimizer.py
run_remaining_epoch
#
Run one epoch of remaining-contingency AC evaluation only.
This evaluates the full remaining-loadflow stage for strategies that already passed the fast-failing worst-k evaluation and returns the same strategies together with their final scoring results.
| PARAMETER | DESCRIPTION |
|---|---|
optimizer_data
|
The optimizer data containing the remaining-stage scoring function.
TYPE:
|
topologies
|
The survivor topologies to evaluate in the remaining stage.
TYPE:
|
early_stage_results
|
The corresponding fast-failing stage results for each topology.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[ACOptimTopology]
|
The topologies that were evaluated in the remaining stage. |
list[TopologyScoringResult]
|
The corresponding final scoring results. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/optimizer.py
process_remaining_results
#
Process the results of the remaining-contingency stage and send the strategies to the result topic.
| PARAMETER | DESCRIPTION |
|---|---|
optimizer_data
|
The optimizer data containing the session and the loadflow storage function.
TYPE:
|
topologies
|
The topologies that were evaluated in the remaining stage.
TYPE:
|
full_results
|
The corresponding full scoring results, containing the final metrics, loadflow results and rejection reason if any.
TYPE:
|
epoch
|
The current epoch number, used for logging and for sending in the result messages.
TYPE:
|
send_result_fn
|
The function to send results to the result topic.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[ACOptimTopology]
|
The topologies that were evaluated in the remaining stage, with their metrics and fitness updated based on the full scoring results. |
list[TopologyScoringResult]
|
The corresponding full scoring results for each topology, which can be used for further processing in the next epoch, e.g. for the evolution function. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/optimizer.py
evaluate_remaining_contingencies
#
evaluate_remaining_contingencies(
send_result_fn,
optimizer_data,
epoch,
survivor_topologies,
survivor_early_results,
)
Evaluate the remaining contingencies for the strategies that passed the fast-failing stage.
| PARAMETER | DESCRIPTION |
|---|---|
survivor_topologies
|
The topologies that passed the fast-failing stage and need to be evaluated on the remaining contingencies.
TYPE:
|
survivor_early_results
|
The early results from the fast-failing stage for the topologies that passed.
TYPE:
|
send_result_fn
|
The function to send results to the result topic, used for sending the final results after evaluating the remaining contingencies.
TYPE:
|
optimizer_data
|
The optimizer data containing the scoring function for the remaining contingencies and other necessary data for the evaluation.
TYPE:
|
epoch
|
The current epoch number, used for logging and for sending in the result messages.
TYPE:
|
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/optimizer.py
toop_engine_topology_optimizer.ac.scoring_functions
#
Scoring functions for the AC optimizer - in this case this runs an N-1 and computes metrics for it
ACScoringParameters
dataclass
#
ACScoringParameters(
reject_convergence_threshold,
reject_overload_threshold,
reject_critical_branch_threshold,
reject_voltage_jump_threshold,
reject_critical_va_diff_threshold,
enable_critical_voltage_rejection,
critical_voltage_jump_percent,
critical_va_diff_degree,
base_case_id,
early_stop_validation,
)
Parameters for ac scoring
This is a subset of all ac parameters and grouped to shorten the signature of the scoring and acceptance functions.
reject_convergence_threshold
instance-attribute
#
The rejection threshold for the convergence rate, i.e. the split case must have at most the same amount of non converging loadflows as the unsplit case or it will be rejected.
reject_overload_threshold
instance-attribute
#
The rejection threshold for the overload energy improvement, i.e. the split case must have at least 5% lower overload energy than the unsplit case or it will be rejected.
reject_critical_branch_threshold
instance-attribute
#
The rejection threshold for the critical branches increase, i.e. the split case must have less than 10% more critical branches than the unsplit case or it will be rejected.
reject_voltage_jump_threshold
instance-attribute
#
The rejection threshold for the voltage jump count increase.
reject_critical_va_diff_threshold
instance-attribute
#
The rejection threshold for the critical voltage-angle-difference count increase.
enable_critical_voltage_rejection
instance-attribute
#
Whether to reject based on the critical voltage jump or voltage-angle-difference count increase.
critical_voltage_jump_percent
instance-attribute
#
Voltage jumps larger than this percentage are counted as critical in the AC metrics.
critical_va_diff_degree
instance-attribute
#
Voltage angle differences larger than this value in degrees are counted as critical in the AC metrics.
base_case_id
instance-attribute
#
The base case id for the loadflow runner (used to separately compute the N-0 flows).
early_stop_validation
instance-attribute
#
Whether to enable early stopping during the optimization process.
get_early_stopping_contingency_ids
#
Extract the contingency ids for early stopping from a list of ACOptimTopology strategies.
This function extracts the worst k contingency case ids from each topology's worst_k_contingency_cases attribute for each timestep. These ids are used to determine which contingencies to include in the N-1 analysis for early stopping.
| PARAMETER | DESCRIPTION |
|---|---|
topology
|
An ACOptimTopology object containing a worst_k_contingency_cases attribute with contingency case ids.
TYPE:
|
base_case_id
|
An optional base case id to include in the early stopping subset. If provided, this will be added to the list of contingency case ids for each timestep.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Optional[list[str]]
|
A list of contingency case IDs, or None if any required metric is missing. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/scoring_functions.py
update_runner_nminus1
#
Update the N-1 definitions in the runners to only include the worst k contingencies.
This modifies the N-1 definitions in the runners to only include the contingencies at the given indices.
| PARAMETER | DESCRIPTION |
|---|---|
runner
|
The loadflow runner to update.
TYPE:
|
nminus1_def
|
The original N-1 definition to use as a template.
TYPE:
|
case_ids_all_t
|
A list of contingency ids for each runner, indicating which contingencies to keep in the N-1 definition. Each element should be an index to the contingencies in the original N-1 definition.
TYPE:
|
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/scoring_functions.py
compute_loadflow_and_metrics
#
compute_loadflow_and_metrics(
runner,
topology,
base_case_id,
critical_voltage_jump_percent,
critical_va_diff_degree,
cases_subset=None,
)
Compute loadflow results and associated metrics for a given set of strategies.
This function runs loadflow simulations for each provided strategy using the specified runners, then computes additional metrics based on the simulation results.
| PARAMETER | DESCRIPTION |
|---|---|
runner
|
The loadflow runner to use for simulations.
TYPE:
|
topology
|
The topology to evaluate.
TYPE:
|
base_case_id
|
The base case identifier for the topology. Can be None.
TYPE:
|
critical_voltage_jump_percent
|
Voltage jumps larger than this percentage are counted as critical in the AC metrics.
TYPE:
|
critical_va_diff_degree
|
Voltage angle differences larger than this value in degrees are counted as critical in the AC metrics.
TYPE:
|
cases_subset
|
Subset of contingency cases to use for loadflow computation. If None, all available contingencies are used.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
lfs
|
The results of the loadflow simulations.
TYPE:
|
additional_info
|
Additional information for the actions taken in the topology.
TYPE:
|
metrics
|
Computed metrics for the topology.
TYPE:
|
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/scoring_functions.py
extract_switching_distance
#
Extract the switching distance from the additional action info
| PARAMETER | DESCRIPTION |
|---|---|
additional_info
|
The additional action info containing the switching distance
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
int
|
The switching distance, or 0 if not available |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/scoring_functions.py
compute_metrics_single_timestep
#
compute_metrics_single_timestep(
actions,
disconnections,
loadflow,
additional_info,
critical_voltage_jump_percent,
critical_va_diff_degree,
base_case_id=None,
)
Compute the metrics for a single timestep
| PARAMETER | DESCRIPTION |
|---|---|
actions
|
The reconfiguration assignment for the timestep
TYPE:
|
disconnections
|
The disconnections for the timestep
TYPE:
|
loadflow
|
The loadflow results for the timestep, use select_timestep to get the results for a specific timestep
TYPE:
|
additional_info
|
Additional information about the actions taken, such as switching distance or other metrics.
TYPE:
|
critical_voltage_jump_percent
|
Voltage jumps larger than this percentage are counted as critical in the AC metrics.
TYPE:
|
critical_va_diff_degree
|
Voltage angle differences larger than this value in degrees are counted as critical in the AC metrics.
TYPE:
|
base_case_id
|
The base case id from the nminus1 definition, to separate N-0 flows from N-1
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Metrics
|
The metrics for the timestep |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/scoring_functions.py
compute_loadflow
#
Compute the loadflow for a given strategy
| PARAMETER | DESCRIPTION |
|---|---|
actions
|
The reconfiguration actions for the timestep
TYPE:
|
disconnections
|
The disconnections for the timestep
TYPE:
|
pst_setpoints
|
The PST setpoints for the topology, or None if PST taps are not part of the topology.
TYPE:
|
runner
|
The loadflow runner to use
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
LoadflowResultsPolars
|
The loadflow results for all timesteps in the strategy |
list[Optional[AdditionalActionInfo]]
|
Additional information about the actions taken, such as switching distance or other metrics. The length of the list is n_timesteps. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/scoring_functions.py
evaluate_acceptance
#
evaluate_acceptance(
metrics_split,
metrics_unsplit,
reject_convergence_threshold=1.0,
reject_overload_threshold=0.95,
reject_critical_branch_threshold=1.1,
reject_voltage_jump_threshold=1.1,
reject_critical_va_diff_threshold=1.1,
enable_critical_voltage_rejection=False,
early_stopping=False,
)
Evaluate if the split loadflow results are acceptable compared to the unsplit results.
Compares the unsplit metrics * the thresholds to the split metrics. If all split metrics are better than the unsplit metrics * thresholds, the split results are accepted.
Checked metrics are: non_converging_loadflows: the number of non-converging loadflows should be less than or equal to reject_convergence_threshold * unsplit.extra_scores.get("non_converging_loadflows", 0) overload_energy_n_1: the overload energy should be less than or equal to reject_overload_threshold * unsplit.extra_scores.get("overload_energy_n_1", 0) critical_branch_count_n_1: the number of critical branches should be less than or equal to reject_critical_branch_threshold * unsplit.extra_scores.get("critical_branch_count_n_1", 0) voltage_jump_count_n_1: the number of critical voltage jumps should be less than or equal to reject_voltage_jump_threshold * unsplit.extra_scores.get("voltage_jump_count_n_1", 0) critical_va_diff_count_n_1: the number of critical voltage-angle differences should be less than or equal to reject_critical_va_diff_threshold * unsplit.extra_scores.get("critical_va_diff_count_n_1", 0)
| PARAMETER | DESCRIPTION |
|---|---|
metrics_split
|
The metrics for the split case.
TYPE:
|
metrics_unsplit
|
The metrics for the unsplit case.
TYPE:
|
reject_convergence_threshold
|
The threshold for the convergence rate, by default 1. (i.e. the split case must have at most the same amount of nonconverging loadflows as the unsplit case.)
TYPE:
|
reject_overload_threshold
|
The threshold for the overload energy improvement, by default 0.95 (i.e. the split case must have at least 5% lower overload energy than the unsplit case).
TYPE:
|
reject_critical_branch_threshold
|
The threshold for the critical branches increase, by default 1.1 (i.e. the split case must not have more than 110 % of the critical branches in the unsplit case).
TYPE:
|
reject_voltage_jump_threshold
|
The threshold for the voltage jump count increase, by default 1.1 (i.e. the split case must not have more than 110 % of the critical voltage jumps in the unsplit case).
TYPE:
|
reject_critical_va_diff_threshold
|
The threshold for the critical voltage-angle-difference count increase, by default 1.1 (i.e. the split case must not have more than 110 % of the critical voltage-angle differences in the unsplit case).
TYPE:
|
enable_critical_voltage_rejection
|
Whether to reject based on the critical jump or voltage-angle-difference count increase.
TYPE:
|
early_stopping
|
Whether the acceptance is computed as part of an early stopping criterion, will set the early_stopping field in the TopologyRejectionReason
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Optional[TopologyRejectionReason]
|
A TopologyRejectionReason if the split results are rejected, None if accepted. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/scoring_functions.py
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 | |
compute_remaining_loadflows
#
compute_remaining_loadflows(
runner,
topology,
base_case_id,
loadflows_subset,
cases_subset,
critical_voltage_jump_percent,
critical_va_diff_degree,
)
Compute the loadflows for the remaining contingencies that were not included in the early stopping subset.
This function is called after the early stopping loadflows have been computed and accepted. It computes the loadflows for the remaining contingencies that were not included in the early stopping subset, and then computes the metrics for the full set of loadflows.
| PARAMETER | DESCRIPTION |
|---|---|
runner
|
The loadflow runners to use, length n_timesteps.
TYPE:
|
topology
|
The topology to score, length n_timesteps
TYPE:
|
base_case_id
|
The base case id for the loadflow runners, used to separately compute the N-0 flows.
TYPE:
|
loadflows_subset
|
The loadflow results for the early stopping subset, used to avoid recomputing these loadflows.
TYPE:
|
cases_subset
|
The contingency case ids that were included in the early stopping subset for each timestep. This could be extracted from the loadflows_subset but as it is available it is faster to pass it in.
TYPE:
|
critical_voltage_jump_percent
|
Voltage jumps larger than this percentage are counted as critical in the AC metrics.
TYPE:
|
critical_va_diff_degree
|
Voltage angle differences larger than this value in degrees are counted as critical in the AC metrics.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
LoadflowResultsPolars
|
The loadflow results for all contingencies, including those from the early stopping subset. |
Metrics
|
The metrics for the full set of loadflows. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/scoring_functions.py
score_strategy_worst_k
#
score_strategy_worst_k(
topology,
runner,
loadflow_results_unsplit,
metrics_unsplit,
scoring_params,
)
Evaluate only the worst-k stage for a single strategy.
| PARAMETER | DESCRIPTION |
|---|---|
topology
|
The topology to evaluate, length n_timesteps
TYPE:
|
runner
|
The loadflow runner to use for the evaluation of the strategy
TYPE:
|
loadflow_results_unsplit
|
The loadflow results for the unsplit case, used for comparison in the acceptance evaluation.
TYPE:
|
metrics_unsplit
|
The metrics for the unsplit case, used for comparison in the acceptance evaluation.
TYPE:
|
scoring_params
|
The parameters for scoring, including thresholds for acceptance and early stopping settings.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
EarlyStoppingStageResult
|
The result of the worst-k stage evaluation, including loadflow results, metrics and rejection reason if rejected. If early stopping is enabled and the strategy is rejected based on the worst-k contingencies, the early_stopping flag will be set. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/scoring_functions.py
585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 | |
score_strategy_worst_k_batch
#
score_strategy_worst_k_batch(
topologies,
worst_k_runner_groups,
loadflow_results_unsplit,
metrics_unsplit,
scoring_params,
)
Evaluate the worst-k stage for a batch of strategies.
| PARAMETER | DESCRIPTION |
|---|---|
topologies
|
The topologies to evaluate, length n_strategies.
TYPE:
|
worst_k_runner_groups
|
The loadflow runner groups to use for the evaluation of the strategies, length n_strategies.
TYPE:
|
loadflow_results_unsplit
|
The loadflow results for the unsplit case, used for comparison in the acceptance evaluation.
TYPE:
|
metrics_unsplit
|
The metrics for the unsplit case, used for comparison in the acceptance evaluation.
TYPE:
|
scoring_params
|
The parameters for scoring, including thresholds for acceptance and early stopping settings.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[EarlyStoppingStageResult]
|
The results of the worst-k stage evaluation for each strategy, including loadflow results, metrics and rejection reason if rejected. If early stopping is enabled and a strategy is rejected based on the worst-k contingencies, the early_stopping flag will be set in the rejection reason. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/scoring_functions.py
score_topology_remaining
#
Evaluate the remaining contingencies for a surviving strategy.
This function is called for strategies that survived the worst-k stage (i.e. were not rejected based on the worst-k contingencies). It computes the loadflows for the remaining contingencies that were not included in the worst-k stage, and then computes the metrics for the full set of loadflows. Finally, it evaluates the acceptance of the full set of loadflows compared to the unsplit case.
| PARAMETER | DESCRIPTION |
|---|---|
topology
|
The topology to evaluate, length n_timesteps
TYPE:
|
runner
|
The loadflow runner to use for the evaluation of the strategy
TYPE:
|
metrics_unsplit
|
The metrics for the unsplit case, used for comparison in the acceptance evaluation.
TYPE:
|
scoring_params
|
The parameters for scoring, including thresholds for acceptance and early stopping settings.
TYPE:
|
early_stage_result
|
The result from the worst-k stage evaluation, including loadflow results, metrics and cases subset used for early stopping. This is used to compute the remaining loadflows and metrics without recomputing the early stopping subset.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
TopologyScoringResult
|
The result of the full evaluation, including loadflow results, metrics and rejection reason if rejected. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/scoring_functions.py
score_strategy_full
#
Evaluate a strategy on the full set of contingencies in one pass.
| PARAMETER | DESCRIPTION |
|---|---|
topology
|
The topology to evaluate, length n_timesteps
TYPE:
|
runner
|
The loadflow runner to use for the evaluation of the strategy
TYPE:
|
metrics_unsplit
|
The metrics for the unsplit case, used for comparison in the acceptance evaluation.
TYPE:
|
scoring_params
|
The parameters for scoring, including thresholds for acceptance and early stopping settings.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
TopologyScoringResult
|
The result of the full evaluation, including loadflow results, metrics and rejection reason if rejected. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/scoring_functions.py
score_strategy_full_batch
#
Evaluate a batch of topologies on the full set of contingencies.
| PARAMETER | DESCRIPTION |
|---|---|
topologies
|
The topologies to evaluate, length n_strategies.
TYPE:
|
runner_groups
|
The loadflow runner groups to use for the evaluation of the strategies, length n_strategies.
TYPE:
|
metrics_unsplit
|
The metrics for the unsplit case, used for comparison in the acceptance evaluation.
TYPE:
|
scoring_params
|
The parameters for scoring, including thresholds for acceptance and early stopping settings.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[TopologyScoringResult]
|
The results of the full evaluation for each strategy, including loadflow results, metrics and rejection reason if rejected. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/scoring_functions.py
score_remaining_contingency_batch
#
score_remaining_contingency_batch(
topologies,
early_stage_results,
runner_group,
metrics_unsplit,
scoring_params,
)
Evaluate the remaining contingencies for a batch of surviving topologies.
This function is called for strategies that survived the worst-k stage (i.e. were not rejected based on the worst-k contingencies). It computes the loadflows for the remaining contingencies that were not included in the worst-k stage, and then computes the metrics for the full set of loadflows.
| PARAMETER | DESCRIPTION |
|---|---|
topologies
|
The topologies to evaluate, length n_strategies.
TYPE:
|
early_stage_results
|
The results from the worst-k stage evaluation for each topology, including loadflow results, metrics and cases subset used for early stopping. This is used to compute the remaining loadflows and metrics without recomputing the early stopping subset.
TYPE:
|
runner_group
|
The loadflow runner group to use for the evaluation of the strategies, length n_strategies.
TYPE:
|
metrics_unsplit
|
The metrics for the unsplit case, used for comparison in the acceptance evaluation.
TYPE:
|
scoring_params
|
The parameters for scoring, including thresholds for acceptance and early stopping settings.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[TopologyScoringResult]
|
The results of the full evaluation for each strategy, including loadflow results, metrics and rejection reason if rejected. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/scoring_functions.py
927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 | |
score_topology_batch
#
score_topology_batch(
topologies,
runner_group,
metrics_unsplit,
scoring_params,
early_stage_results=None,
)
Score a batch of topologies in two stages.
| PARAMETER | DESCRIPTION |
|---|---|
topologies
|
The topologies to be scored.
TYPE:
|
runner_group
|
The group of runners to use for scoring.
TYPE:
|
metrics_unsplit
|
The metrics to be used for scoring.
TYPE:
|
scoring_params
|
The parameters for scoring, including thresholds for acceptance and early stopping settings.
TYPE:
|
early_stage_results
|
The results from the early stage, by default None.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[TopologyScoringResult]
|
The results of the full evaluation for each strategy, including loadflow results, metrics and rejection reason if rejected. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/scoring_functions.py
toop_engine_topology_optimizer.ac.select_strategy
#
Selection strategy for AC optimization topologies.
select_strategy
#
select_strategy(
rng,
repertoire,
candidates,
interest_scorer,
batch_size=1,
lower_scores_are_better=False,
filter_strategy=None,
)
Select promising unevaluated topologies from the candidate pool.
Make sure the repertoire only contains topologies with the right optimizer type and optimization id as select_strategy will not filter for this.
| PARAMETER | DESCRIPTION |
|---|---|
rng
|
The random number generator to use
TYPE:
|
repertoire
|
The filtered repertoire with all individuals of the optimization in all optimizer types
TYPE:
|
candidates
|
Candidates which have not yet been evaluated. For a pull operation this will only include DC candidates without an AC parent.
TYPE:
|
interest_scorer
|
The function to score the topologies in the candidate pool. The higher the score, the more interesting the topology is. Eventually, the topology will be selected with a probability proportional to its score.
TYPE:
|
batch_size
|
Number of topologies to sample without replacement. If more topologies are requested than available candidates, all available candidates are returned.
TYPE:
|
lower_scores_are_better
|
Whether lower values returned by
TYPE:
|
filter_strategy
|
Whether to filter the candidates based on discriminator, median or dominator filter.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[BaseDBTopology]
|
The selected topologies sampled from the candidate pool. If no topology could be selected because the candidate pool is empty, return an empty list |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/select_strategy.py
filter_metrics_df
#
Get a mask for the metrics DataFrame that filters out rows based on discriminator and median masks.
This function applies a discriminator, median and dominator mask.
| PARAMETER | DESCRIPTION |
|---|---|
metrics_df
|
The DataFrame containing the metrics to filter. This is typically the DC repertoire from which new results shall be pulled.
TYPE:
|
discriminator_df
|
The DataFrame containing the discriminator metrics. These are topologies that have previously been AC validated
TYPE:
|
filter_strategy
|
The filter strategy to use for the optimization, used to filter out strategies based on the discriminator, median or dominator filter.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
DataFrame
|
The filtered metrics DataFrame with similar topologies removed. If all topologies are filtered out, the original metrics DataFrame is returned. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/select_strategy.py
get_repertoire_filter_mask
#
Get a mask for the metrics DataFrame that filters out rows based on discriminator and median masks.
This function applies a discriminator, median and dominator mask.
| PARAMETER | DESCRIPTION |
|---|---|
metrics_df
|
The DataFrame containing the metrics to filter.
TYPE:
|
discriminator_df
|
The DataFrame containing the discriminator metrics.
TYPE:
|
filter_strategy
|
The filter strategy to use for the optimization, used to filter out strategies based on the discriminator, median or dominator filter.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Bool[ndarray, ' metrics_df.shape[0]']
|
A boolean mask where True indicates the row is not filtered out. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/select_strategy.py
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 | |
get_median_mask
#
Get a mask for fitness values below the median for each discrete value of the target metrics.
Note: expects the target metrics to be discrete values, not continuous.
| PARAMETER | DESCRIPTION |
|---|---|
metrics_df
|
The DataFrame containing the metrics to filter.
TYPE:
|
target_metrics
|
A list of metrics with discrete values to consider for filtering. example: ["split_subs"].
TYPE:
|
fitness_col
|
The column name that contains the fitness values. Defaults to "fitness".
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
filter_mask
|
A boolean mask where True indicates the row is not below the median for any of the target metrics.
TYPE:
|
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/select_strategy.py
get_dominator_mask
#
Get a mask for rows from a DataFrame that are dominated by other rows based on specified metrics.
A metric entry if there is any other metric entry with a better fitness, in respect to the distance to the original topology. The distance in measured by the metric, assuming that lower values are better.
The target metric is used to fix the discrete value for which the dominance is checked. The fitness column is used to determine the fitness of the rows. Each observed metric is checked against the minimum fitness of all discrete target values.
Intended use is target_metrics = ["switching_distance", "split_subs"] and observed_metrics = Any additional metric to the target metrics, e.g. "disconnections"
| PARAMETER | DESCRIPTION |
|---|---|
metrics_df
|
The DataFrame to filter.
TYPE:
|
target_metrics
|
A list of metrics to consider for dominance. A target metric is expected to have discrete values (e.g. not fitness, overload_energy, or max_flow) If None, defaults to ["switching_distance", "split_subs"].
TYPE:
|
observed_metrics
|
A list of metrics to observe for dominance. If None, defaults to ["switching_distance", "split_subs"].
TYPE:
|
fitness_col
|
The column name that contains the fitness values. Defaults to "fitness". Note: the values are expected to be negative, best fitness converges to zero.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
filter_mask
|
A boolean mask where True indicates the row is not dominated by another row.
TYPE:
|
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/select_strategy.py
get_discriminator_mask
#
Get a mask for rows in metrics_df that are within a certain distance from the discriminator_df.
The distance is defined by the metric_distances dictionary, which contains the metrics and their respective distances.
Use the use_split_sub_multiplier flag to apply a multiplier in respect to the split_subs_col.
e.g. use_split_sub_multiplier=False, the metric_distances is applied directly to the metrics_df.
If use_split_sub_multiplier=True, the metric_distances are multiplied by the split_subs, leading to a
larger distance for larger split_subs values.
| PARAMETER | DESCRIPTION |
|---|---|
metrics_df
|
The DataFrame containing the metrics to filter.
TYPE:
|
discriminator_df
|
The DataFrame containing the discriminator metrics.
TYPE:
|
metric_distances
|
A dictionary defining the metric distances for filtering. The keys are metric names and the values are sets of distances. example: metric_distances = { "split_subs": {0}, "switching_distance": {-0.9, 0.9}, "fitness": {-0.1, 0.1}, } Note: the fitness is treated as a percentage.
TYPE:
|
metric_multiplier
|
A dictionary defining multiplier for the metric distances.
The keys are metric names and the values are multipliers.
If None, defaults to an empty dictionary.
Multiple values are added by:
distance_multiplier = (
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
filter_mask
|
A boolean mask where True indicates the row is not within the distance defined by the discriminator_df and metric_distances.
TYPE:
|
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
If not all metric distances are present in the discriminator DataFrame columns. If the metric_distances is None, it will use default values based on the use_split_sub_multiplier flag. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/select_strategy.py
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 | |
get_discriminator_df
#
Get a discriminator DataFrame from the metrics DataFrame.
The discriminator DataFrame is a subset of the metrics DataFrame that contains only the target metrics. It is used to filter out similar topologies from the metrics DataFrame.
| PARAMETER | DESCRIPTION |
|---|---|
metrics_df
|
The DataFrame containing the metrics to filter. Note: expects the metrics_df to contain only AC topologies that have as a metric the "fitness_dc" column.
TYPE:
|
target_metrics
|
A list of metrics to consider for filtering.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
DataFrame
|
A DataFrame containing only the target metrics. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/select_strategy.py
toop_engine_topology_optimizer.ac.storage
#
The database models to store topologies in the AC optimizer
ACOptimTopology
#
Bases: BaseDBTopology
Inherits from the base topology to make a database table for AC optimizer topologies
This can include both AC and DC topologies, with the specific needs of the AC optimizer
parent_id
class-attribute
instance-attribute
#
The mutation parent id, i.e. the topology that this topology was mutated from. This is mostly for debugging purposes to see where a topology came from and understand the mutation process.
acceptance
class-attribute
instance-attribute
#
Whether the strategy was accepted or not.
id
class-attribute
instance-attribute
#
The table primary key
actions
class-attribute
instance-attribute
#
The branch/injection reconfiguration actions as indices into the action set.
disconnections
class-attribute
instance-attribute
#
A list of disconnections, indexing into the disconnectable branches set in the action set.
pst_setpoints
class-attribute
instance-attribute
#
The setpoints for the PSTs if they have been computed. This is an index into the range of pst taps, i.e. the smallest tap is 0 and the neutral tap somewhere in the middle of the range. The tap range is defined in the action set. The list always has the same length, i.e. the number of controllable PSTs in the system, and each entry corresponds to the PST at the same position in the action set.
unsplit
instance-attribute
#
Whether all topologies in the strategy including this one have no branch assignments, disconnections or injections.
strategy_hash
instance-attribute
#
The hash of the strategy - this hashes actions, disconnections and pst_setpoints for all timesteps in the strategy, making it possible to form a unique constraint on the strategy. This value will be set to the same for all topologies in the same strategy, furthermore making it possible to group timesteps.
metrics
class-attribute
instance-attribute
#
The metrics of this topology
worst_k_contingency_cases
class-attribute
instance-attribute
#
The worst k contingency case IDs for the topology.
created_at
class-attribute
instance-attribute
#
The time the topology was recorded in the database
stored_loadflow_reference
class-attribute
instance-attribute
#
The file reference for the loadflow results of this topology/strategy, if they were computed. Multiple topologies belonging to the same strategy will have the same serialized loadflow results object as there is a timestep notion in the loadflow results. To obtain the correct loadflow results, use the timestep attribute. This is stored as a json serialized StoredLoadflowReference object
__table_args__
class-attribute
instance-attribute
#
__table_args__ = (
UniqueConstraint(
"optimization_id",
"optimizer_type",
"strategy_hash",
"timestep",
name="topo_unique",
),
)
get_loadflow_reference
#
Get the loadflow reference as a StoredLoadflowReference object
| RETURNS | DESCRIPTION |
|---|---|
Optional[StoredLoadflowReference]
|
The loadflow reference, or None if it is not set |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/interfaces/models/base_storage.py
set_loadflow_reference
#
Set the loadflow reference from a StoredLoadflowReference object
| PARAMETER | DESCRIPTION |
|---|---|
loadflow_reference
|
The loadflow reference to set, or None to unset it
TYPE:
|
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/interfaces/models/base_storage.py
FinishedOptimizations
#
Bases: SQLModel
A table to store finished optimizations, to prevent picking up old topologies from previous optimizations
optimization_id
class-attribute
instance-attribute
#
The optimization ID of the finished optimization as sent via kafka
optimizer_type
class-attribute
instance-attribute
#
Which optimizer type has finished
finished_at
class-attribute
instance-attribute
#
When the optimization was marked as finished in the database
convert_single_topology
#
convert_single_topology(
topology,
optimization_id,
optimizer_type,
timestep,
strategy_hash,
unsplit,
)
Convert a single Topology to a ACOptimTopology
| PARAMETER | DESCRIPTION |
|---|---|
topology
|
The topology to convert
TYPE:
|
optimization_id
|
The optimization ID to assign to the db topology
TYPE:
|
optimizer_type
|
The optimizer type to assign to the db topology
TYPE:
|
timestep
|
The timestep of the topology
TYPE:
|
strategy_hash
|
The hash of the strategy computed through hash_strategy
TYPE:
|
unsplit
|
Whether the strategy is unsplit
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
ACOptimTopology
|
The converted topology |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/storage.py
convert_message_topo_to_db_topo
#
Convert a TopologyPushResult to a list of ACOptimTopology
| PARAMETER | DESCRIPTION |
|---|---|
message_strategy
|
The strategy to convert, usually from a TopologyPushResult or OptimizationStartedResult. Strategy timesteps are flattened into the list of topologies that are being returned.
TYPE:
|
optimization_id
|
The optimization ID to assign to the topologies. This was sent through with the parent result message and is not part of TopologyPushResult
TYPE:
|
optimizer_type
|
The optimizer type to assign. This was sent through with the parent result message and is not part of TopologyPushResult
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[ACOptimTopology]
|
A list of converted topologies where for each timestep a new ACOptimTopology instance is created. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/storage.py
create_session
#
Create a thread-safe shared in-memory SQLite session for the AC worker.
Using StaticPool plus check_same_thread=False keeps the
worker on a single shared in-memory database connection.
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/storage.py
scrub_db
#
Scrub the database of the worker to prevent memory issues.
The AC worker has to store topologies from all runs, not only the current one, as it might have to pick up an optimization later. Meaning, the AC worker busily collects all topologies into memory. To prevent memory leak issues, we scrub the database of topologies that are older than a day as we do not expect to ever have to go back to those.
| PARAMETER | DESCRIPTION |
|---|---|
session
|
The database session. The session object will be modified in-place
TYPE:
|
max_age_seconds
|
The maximum age of topologies to keep in the database, in seconds. Topologies older than this will be removed.
TYPE:
|
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/storage.py
toop_engine_topology_optimizer.ac.summary
#
Helper functions to write a summary after an optimization.
changing_switches_to_orao_dict
#
Write the changing switches into an orao compatible dictionary format
The format looks like this:
| PARAMETER | DESCRIPTION |
|---|---|
switch_updates
|
The list of switch updates to export.
TYPE:
|
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/summary.py
db_topology_to_changing_switches
#
Get the list of changing switches from a topology in the database
| PARAMETER | DESCRIPTION |
|---|---|
db_topology
|
The topology to be converted to the ORAO format
TYPE:
|
action_set
|
The action set that was applied to the topology, to read up the asset topology for the switched station
TYPE:
|
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/summary.py
export_topology
#
Write a summary of an optimization run for a single timestep
This will export to - Openrao compatible json format - .dgs format for visualization in PowerFactory (TODO, not implemented yet)
| PARAMETER | DESCRIPTION |
|---|---|
db_topology
|
The topology that was explored during the optimization run for the given grid file.
TYPE:
|
action_set
|
The action set that was applied during the optimization run for the given grid file, to be included in the summary.
TYPE:
|
processed_gridfile_fs
|
The file system where the summary should be written to. This is typically the same file system where the processed gridfiles are stored.
TYPE:
|
root_folder
|
The root folder where the summary should be written to. This is typically the root folder of the processed grid file
TYPE:
|
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/summary.py
write_summary
#
Write a summary of the optimization run to the file system.
| PARAMETER | DESCRIPTION |
|---|---|
grid_file
|
The grid file that was optimized during the optimization run.
TYPE:
|
db
|
The in-memory database that holds topologies including the ones from the current optimization. It will be queried to perform a topology summary
TYPE:
|
optimization_id
|
The optimization id of the optimization run for which the summary should be written. Topologies will be filtered for this optimization id
TYPE:
|
processed_gridfile_fs
|
The file system where the summary should be written to. This is typically the same file system where the processed gridfiles are stored.
TYPE:
|
action_set
|
The action set that was applied during the optimization run, to be included in the summary.
TYPE:
|
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/summary.py
toop_engine_topology_optimizer.ac.worker
#
The AC worker that listens to the kafka topics, organizes optimization runs, etc.
Args
#
Bases: Args
Command line arguments for the AC worker.
Mostly the same as the DC worker except for an additional loadflow results folder
kafka_broker
class-attribute
instance-attribute
#
The Kafka broker to connect to.
optimizer_command_topic
class-attribute
instance-attribute
#
The Kafka topic to listen for commands on.
optimizer_results_topic
class-attribute
instance-attribute
#
The topic to push results to.
optimizer_heartbeat_topic
class-attribute
instance-attribute
#
The topic to push heartbeats to.
heartbeat_interval_ms
class-attribute
instance-attribute
#
The interval in milliseconds to send heartbeats.
max_command_age_hours
class-attribute
instance-attribute
#
The maximum age of a command in hours. If a command is received that is older than this, the command will be ignored.
WorkerData
dataclass
#
Data that is stored across optimization runs
command_consumer
instance-attribute
#
A kafka consumer listening in for optimization commands
result_consumer
instance-attribute
#
A kafka consumer listening on the results topic, constantly writing results to the database. This is polled both during the optimization and idle loop to keep the database up to date.
initialize_optimization_run
#
initialize_optimization_run(
ac_params,
grid_file,
worker_data,
send_result_fn,
send_heartbeat_fn,
optimization_id,
loadflow_result_fs,
processed_gridfile_fs,
)
Initialize the AC optimization and wait for the first DC results.
Parameters are identical to optimization_loop plus the bound logger.
| RETURNS | DESCRIPTION |
|---|---|
tuple[OptimizerData, Strategy]
|
The initialized optimizer data and the initial topology message. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/worker.py
run_optimization_epochs
#
run_optimization_epochs(
ac_params,
optimizer_data,
worker_data,
send_result_fn,
send_heartbeat_fn,
optimization_id,
)
Run the iterative AC optimization phase.
| PARAMETER | DESCRIPTION |
|---|---|
ac_params
|
The parameters for the AC optimizer
TYPE:
|
optimizer_data
|
The initialized optimizer data containing the curried functions and database session
TYPE:
|
worker_data
|
The dataclass with the results consumer and database
TYPE:
|
send_result_fn
|
The function to send results
TYPE:
|
send_heartbeat_fn
|
The function to send heartbeats
TYPE:
|
optimization_id
|
The ID of the optimization run
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
None
|
|
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/worker.py
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 | |
summarize_optimization_run
#
summarize_optimization_run(
optimization_id,
grid_file,
worker_data,
optimizer_data,
processed_gridfile_fs,
)
Write the optimization summary artifacts.
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/worker.py
optimization_loop
#
optimization_loop(
ac_params,
grid_file,
worker_data,
send_result_fn,
send_heartbeat_fn,
optimization_id,
loadflow_result_fs,
processed_gridfile_fs,
)
Run the main loop for the AC optimizer.
This function will run the AC optimizer on the given grid files with the given parameters.
| PARAMETER | DESCRIPTION |
|---|---|
ac_params
|
The parameters for the AC optimizer
TYPE:
|
grid_file
|
The grid file to optimize on
TYPE:
|
worker_data
|
The dataclass with the results consumer and database
TYPE:
|
send_result_fn
|
The function to send results
TYPE:
|
send_heartbeat_fn
|
The function to send heartbeats
TYPE:
|
optimization_id
|
The ID of the optimization run
TYPE:
|
loadflow_result_fs
|
A filesystem where the loadflow results are stored. Loadflows will be stored here using the uuid generation process and passed as a StoredLoadflowReference which contains the subfolder in this filesystem.
TYPE:
|
processed_gridfile_fs
|
The target filesystem for the preprocessing worker. This contains all processed grid files. During the import job, a new folder import_results.data_folder was created which will be completed with the preprocess call to this function. Internally, only the data folder is passed around as a dirfs. Note that the unprocessed_gridfile_fs is not needed here anymore, as all preprocessing steps that need the unprocessed gridfiles were already done.
TYPE:
|
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/worker.py
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 | |
idle_loop
#
idle_loop(
worker_data,
send_heartbeat_fn,
send_result_fn,
heartbeat_interval_ms,
max_command_age_hours,
)
Run idle loop of the AC optimizer worker.
This will be running when the worker is currently not optimizing This will wait until a StartOptimizationCommand is received and return it. In case a ShutdownCommand is received, the worker will exit with the exit code provided in the command.
| PARAMETER | DESCRIPTION |
|---|---|
worker_data
|
The dataclass with the command consumer, results consumer and database
TYPE:
|
send_heartbeat_fn
|
A function to call when there were no messages received for a while.
TYPE:
|
send_result_fn
|
A function to call to send results back to the results topic, used to send a message in case a command is too old.
TYPE:
|
heartbeat_interval_ms
|
The time to wait for a new command in milliseconds. If no command has been received, a heartbeat will be sent and then the receiver will wait for commands again.
TYPE:
|
max_command_age_hours
|
The maximum age of a command in hours. If a command is received that is older than this, the command will be ignored and a message will be sent to the results topic.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
StartOptimizationCommand
|
The start optimization command to start the optimization run with |
| RAISES | DESCRIPTION |
|---|---|
SystemExit
|
If a ShutdownCommand is received |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/worker.py
384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 | |
warmup_result_storage
#
Go through the results topic and stores all published topology results in the database
This way, when an optimization run starts, the local in-memory results storage is already populated with results, so no time is wasted in spooling through the results topic.
| PARAMETER | DESCRIPTION |
|---|---|
worker_data
|
The dataclass with the results consumer and database
TYPE:
|
heartbeat_fn
|
A function to call to send heartbeats during the warmup loop, as it can take a while if there are many results to spool through.
TYPE:
|
heartbeat_interval_ms
|
The time interval in milliseconds to send heartbeats during the warmup loop, by default 5000 ms
TYPE:
|
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/worker.py
main
#
main(
args,
loadflow_result_fs,
processed_gridfile_fs,
producer,
command_consumer,
result_consumer,
)
Run the main AC worker loop.
| PARAMETER | DESCRIPTION |
|---|---|
args
|
The command line arguments
TYPE:
|
loadflow_result_fs
|
A filesystem where the loadflow results are stored. Loadflows will be stored here using the uuid generation process and passed as a StoredLoadflowReference which contains the subfolder in this filesystem.
TYPE:
|
processed_gridfile_fs
|
The target filesystem for the preprocessing worker. This contains all processed grid files. During the import job, a new folder import_results.data_folder was created which will be completed with the preprocess call to this function. Internally, only the data folder is passed around as a dirfs. Note that the unprocessed_gridfile_fs is not needed here anymore, as all preprocessing steps that need the unprocessed gridfiles were already done.
TYPE:
|
producer
|
A kafka producer to send heartbeats and results
TYPE:
|
command_consumer
|
A kafka consumer listening in for optimization commands
TYPE:
|
result_consumer
|
A kafka consumer listening in for results
TYPE:
|
| RAISES | DESCRIPTION |
|---|---|
SystemExit
|
If the worker receives a ShutdownCommand |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/ac/worker.py
518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 | |
Benchmarks#
toop_engine_topology_optimizer.benchmark.benchmark
#
Run benchmark.
This module provides functionality to run benchmark tasks based on a provided configuration.
It supports grid search for sweeping through the values of number of CUDA devices or a single parameter
not defined inside lf_config and ga_config. Multiple parameter sweeps are not supported yet.
| FUNCTION | DESCRIPTION |
|---|---|
main |
|
main
#
Run benchmark tasks based on the provided configuration.
| PARAMETER | DESCRIPTION |
|---|---|
cfg
|
Configuration object containing benchmark tasks and output settings.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
None
|
|
Notes
The function performs the following steps: 1. Iterates over the benchmark tasks specified in the configuration. 2. Checks for grid search configurations and generates new configurations for each value in the grid. 3. Sets environment variables for each benchmark task. 4. Runs each benchmark task in a separate process to avoid side-effects. 5. Collects the results and logs them into a JSON file specified in the configuration.
Grid search currently supports sweeping through the values of number of CUDA devices or
a single parameter not defined inside lf_config and ga_config. Multiple parameter sweeps are not supported yet.
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/benchmark/benchmark.py
DC Optimizer#
toop_engine_topology_optimizer.dc.ga_helpers
#
Helper functions for genetic algorithms.
MixingEmitterState
#
Bases: EmitterState
The state of a MixingEmitter.
It extends the EmitterState with additional fields to track the number of branch and injection combinations and splits.
TrackingMixingEmitter
#
Bases: MixingEmitter
A MixingEmitter that tracks the number of branch and injection combinations and splits.
init
#
Overwrite the Emitter.init function to seed an EmitterState.
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/ga_helpers.py
state_update
#
Overwrite the state update to store information for the running means.
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/ga_helpers.py
RunningMeans
dataclass
#
RunningMeans(
start_time,
last_time,
time_step,
total_branch_combis,
total_inj_combis,
br_per_sec,
inj_per_sec,
split_per_iter,
last_emitter_state,
n_outages,
n_devices,
)
A dataclass to hold the running means estimations for the TQDM progress bar.
init_running_means
#
Initialize an empty RunningMeans object.
| PARAMETER | DESCRIPTION |
|---|---|
n_outages
|
The number of outages
TYPE:
|
n_devices
|
The number of devices
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
RunningMeans
|
The initialized running means |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/ga_helpers.py
update_running_means
#
Aggregate the emitter state statistics into the running means.
| PARAMETER | DESCRIPTION |
|---|---|
running_means
|
The running means to be updated
TYPE:
|
emitter_state
|
The emitter state of the current iteration
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
RunningMeans
|
The updated running means |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/ga_helpers.py
toop_engine_topology_optimizer.dc.main
#
Launcher for the Map-Elites optimizer.
example args:
--fixed_files /workspaces/AICoE_HPC_RL_Optimizer/data/static_information.hdf5 --stats_dir /workspaces/AICoE_HPC_RL_Optimizer/stats/ --tensorboard_dir /workspaces/AICoE_HPC_RL_Optimizer/stats/tensorboard/ --ga_config.target_metrics overload_energy_n_1 1.0 # The metrics to optimize with their weight --ga_config.me_descriptors.0.metric split_subs --ga_config.me_descriptors.0.num_cells 5 --ga_config.me_descriptors.1.metric switching_distance --ga_config.me_descriptors.1.num_cells 45 # The metrics to use as descriptors along with their maximum value --ga_config.observed_metrics overload_energy_n_1 split_subs switching_distance # All the relevant metrics, including target, descriptors and extra metrics you want to see in the report --ga_config.substation_unsplit_prob 0.5 # Instinctively better suited for mapelites --ga_config.substation_split_prob 0.5 # Instinctively better suited for mapelites --ga_config.plot # Enable plot generation and saving in stats_dir/plots/ --ga_config.iterations_per_epoch 50 # Basically how often you wanna get a report. Suggested range : 50 - 1000 --ga_config.runtime_seconds 300 # How many seconds to run the optimization for The first descriptor metric is the vertical axis, the second the horizontal axis.
CLIArgs
#
Bases: BaseModel
The arguments for a CLI invocation, mostly equal to OptimizationStartCommand.
ga_config
class-attribute
instance-attribute
#
ga_config = Field(default_factory=BatchedMEParameters)
The configuration for the genetic algorithm
lf_config
class-attribute
instance-attribute
#
lf_config = Field(default_factory=LoadflowSolverParameters)
The configuration for the loadflow solver
fixed_files
class-attribute
instance-attribute
#
The file containing the static information. You can pass multiple files here
tensorboard_dir
class-attribute
instance-attribute
#
The directory to store the tensorboard logs
stats_dir
class-attribute
instance-attribute
#
The directory to store the json summaries
summary_frequency
class-attribute
instance-attribute
#
How often to write tensorboard summaries
checkpoint_frequency
class-attribute
instance-attribute
#
How often to write json summaries
double_limits
class-attribute
instance-attribute
#
The double limits to use in the form (lower_limit, upper_limit). lower_limit: float The relative lower limit to set, for branches whose n-1 flows are below the lower limit upper_limit: float The relative upper_limit determining at what relative load a branch is considered overloaded. Branches in the band between lower and upper limit are considered overloaded if more load is added.
log_tensorboard
#
Log fitness and metrics to tensorboard.
| PARAMETER | DESCRIPTION |
|---|---|
fitness
|
The fitness value
TYPE:
|
metrics
|
The metrics to log
TYPE:
|
iteration
|
The current iteration number
TYPE:
|
writer
|
The tensorboard writer
TYPE:
|
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/main.py
write_summary
#
write_summary(
optimizer_data,
repertoire,
emitter_state,
iteration,
folder,
cli_args,
processed_gridfile_fs,
final_results=False,
)
Write a summary to a json file.
Watch out : here, the optimizer data is out of sync with the jax_data
| PARAMETER | DESCRIPTION |
|---|---|
optimizer_data
|
The optimizer data of the optimization. This includes a jax_data, however as the jax_data is updated per-iteration and the optimizer_data only per-epoch, we need to pass the jax_data separately
TYPE:
|
repertoire
|
The current repertoire for this iteration, will be used instead of the one in the optimizer_data |
emitter_state
|
The emitter state for this iteration, will be used instead of the one in the optimizer_data
TYPE:
|
iteration
|
The iteration number
TYPE:
|
folder
|
The folder to write the summary to, relative to the processed_gridfile_fs
TYPE:
|
cli_args
|
The arguments used for invocation, will be added to the summary for documentation purposes
TYPE:
|
processed_gridfile_fs
|
The target filesystem for the preprocessing worker. This contains all processed grid files. During the import job, a new folder import_results.data_folder was created which will be completed with the preprocess call to this function. Internally, only the data folder is passed around as a dirfs. Note that the unprocessed_gridfile_fs is not needed here anymore, as all preprocessing steps that need the unprocessed gridfiles were already done.
TYPE:
|
final_results
|
Whether this is the final results summary "res.json" or an intermediate one "res_{iteration}.json"
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
dict
|
The summary that was written |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/main.py
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 | |
main
#
Run main optimization function for CLI execution.
| PARAMETER | DESCRIPTION |
|---|---|
args
|
The arguments for the optimization
TYPE:
|
processed_gridfile_fs
|
The target filesystem for the preprocessing worker. This contains all processed grid files. During the import job, a new folder import_results.data_folder was created which will be completed with the preprocess call to this function. Internally, only the data folder is passed around as a dirfs. Note that the unprocessed_gridfile_fs is not needed here anymore, as all preprocessing steps that need the unprocessed gridfiles were already done.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
dict
|
The final results of the optimization |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/main.py
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 | |
Genetic Algorithm Functions#
toop_engine_topology_optimizer.dc.genetic_functions.genotype
#
Dataclass for the genotype used in the genetic algorithm.
Genotype
#
Bases: Module
A single genome in the repertoire representing a topology.
disconnections
instance-attribute
#
The disconnections to apply, padded with int_max for disconnection slots that are unused. These are indices into the disconnectable branches set.
nodal_injections_optimized
instance-attribute
#
The results of the nodal injection optimization, if any was performed.
deduplicate_genotypes
#
Deduplicate the genotypes in the repertoire.
This version is jittable because we set the size
| PARAMETER | DESCRIPTION |
|---|---|
genotypes
|
The genotypes to deduplicate. These should be sorted by action id already.
TYPE:
|
desired_size
|
How many unique values you are expecting. If not given, this is not jittable
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Genotype
|
The deduplicated genotypes |
Int[Array, ' n_unique']
|
The indices of the unique genotypes |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/genotype.py
fix_dtypes
#
Fix the dtypes of the genotypes to their native type.
For some reason, qdax aggressively converts everything to float
| PARAMETER | DESCRIPTION |
|---|---|
genotypes
|
The genotypes to fix
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Genotype
|
The genotypes with fixed dtypes |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/genotype.py
empty_repertoire
#
empty_repertoire(
batch_size,
max_num_splits,
max_num_disconnections,
n_timesteps,
starting_taps=None,
)
Create an initial genotype repertoire with all zeros for all entries and int_max for all subs.
| PARAMETER | DESCRIPTION |
|---|---|
batch_size
|
The batch size
TYPE:
|
max_num_splits
|
The maximum number of splits per topology
TYPE:
|
max_num_disconnections
|
The maximum number of disconnections as topological measures per topology
TYPE:
|
n_timesteps
|
The number of timesteps in the optimization horizon, used for the nodal injection optimization results
TYPE:
|
starting_taps
|
The starting taps for the psts. If None, no nodal inj optimization will be enabled and nodal_injections_optimized will be set to None. If provided, nodal_injections_optimized will be initialized with these starting taps.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Genotype
|
The initial genotype |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/genotype.py
toop_engine_topology_optimizer.dc.genetic_functions.initialization
#
Initialization of the genetic algorithm for branch and injection choice optimization.
JaxOptimizerData
#
Bases: Module
The part of the optimizer data that lives on GPU.
If distributed is enabled, every item will have a leading device dimension.
update_max_mw_flows_according_to_double_limits
#
update_max_mw_flows_according_to_double_limits(
dynamic_informations,
solver_configs,
lower_limit,
upper_limit,
)
Update all dynamic informations max mw loads.
Runs an initial n-1 analysis to determine limits in mw.
| PARAMETER | DESCRIPTION |
|---|---|
dynamic_informations
|
List of static informations to calculate with max_mw_flow limits set at 1.0
TYPE:
|
solver_configs
|
List of solver configurations to use for the loadflow
TYPE:
|
lower_limit
|
The relative lower limit to set, for branches whose n-1 flows are below the lower limit
TYPE:
|
upper_limit
|
The relative upper_limit determining at what relative load a branch is considered overloaded. Branches in the band between lower and upper limit are considered overloaded if more load is added.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
tuple[DynamicInformation, ...]
|
The updated dynamic informations with new limits set. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/initialization.py
initialize_genetic_algorithm
#
initialize_genetic_algorithm(
batch_size,
max_num_splits,
max_num_disconnections,
static_informations,
target_metrics,
mutation_config,
action_set,
proportion_crossover,
crossover_mutation_ratio,
random_seed,
observed_metrics,
me_descriptors,
distributed,
devices=None,
cell_depth=1,
n_worst_contingencies=10,
)
Initialize the mapelites algorithm.
| PARAMETER | DESCRIPTION |
|---|---|
batch_size
|
The batch size to use
TYPE:
|
max_num_splits
|
The maximum number of substations that can be split
TYPE:
|
max_num_disconnections
|
The maximum number of disconnections that can be made
TYPE:
|
static_informations
|
The static information to use for the optimization run
TYPE:
|
target_metrics
|
The target metrics to use for the optimization run
TYPE:
|
mutation_config
|
The mutation configuration to use for the optimization run
TYPE:
|
action_set
|
The action set to use for mutations
TYPE:
|
proportion_crossover
|
The proportion of crossover to mutation
TYPE:
|
crossover_mutation_ratio
|
The ratio of crossover to mutation
TYPE:
|
random_seed
|
The random seed to use for reproducibility
TYPE:
|
observed_metrics
|
The observed metrics, i.e. which metrics are to be computed for logging purposes.
TYPE:
|
me_descriptors
|
The descriptors to use for map elites
TYPE:
|
distributed
|
Whether to run the optimization on multiple devices
TYPE:
|
devices
|
The devices to run the optimization on, if distributed
TYPE:
|
cell_depth
|
The cell depth to use if applicable
TYPE:
|
n_worst_contingencies
|
The number of worst contingencies to consider in the scoring function for calculating top_k_overloads_n_1.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
DiscreteMapElites
|
The genetic algorithm object including scoring, mutate and crossover functions |
JaxOptimizerData
|
The initialized jax dataclass |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/initialization.py
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 | |
get_repertoire_metrics
#
Get the metrics of the best individual in the Mapelites repertoire.
| PARAMETER | DESCRIPTION |
|---|---|
repertoire
|
The repertoire |
observed_metrics
|
The metrics to observe (max_flow_n_0, median_flow_n_0 ...)
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
float
|
The fitness |
dict[MetricType, float]
|
The metrics as defined in METRICS |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/initialization.py
algo_setup
#
Set up the genetic algorithm run.
| PARAMETER | DESCRIPTION |
|---|---|
ga_args
|
The genetic algorithm parameters
TYPE:
|
lf_args
|
The loadflow solver parameters
TYPE:
|
double_limits
|
The lower and upper limit for the relative max mw flow if double limits are used
TYPE:
|
static_information_files
|
A list of files with static information to load
TYPE:
|
processed_gridfile_fs
|
The target filesystem for the preprocessing worker. This contains all processed grid files. During the import job, a new folder import_results.data_folder was created which will be completed with the preprocess call to this function. Internally, only the data folder is passed around as a dirfs. Note that the unprocessed_gridfile_fs is not needed here anymore, as all preprocessing steps that need the unprocessed gridfiles were already done.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
DiscreteMapElites
|
The initialized genetic algorithm object, can be used to update the optimization run |
JaxOptimizerData
|
The jax dataclass of all GPU data including dynamic information and the GA data |
tuple[SolverConfig, ...]
|
The solver configurations for every timestep (the dynamic information is part of the jax dataclass) |
float
|
The initial fitness, for logging purposes |
dict
|
The initial metrics, for logging purposes |
list[StaticInformationDescription]
|
Some statistics on the static information dataclasses that were loaded |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/initialization.py
373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 | |
toop_engine_topology_optimizer.dc.genetic_functions.scoring_functions
#
Create scoring functions for the genetic algorithm.
METRICS
module-attribute
#
METRICS = {
"max_flow_n_0": jnp.maximum,
"median_flow_n_0": jnp.maximum,
"overload_energy_n_0": jnp.add,
"overload_energy_limited_n_0": jnp.add,
"underload_energy_n_0": jnp.add,
"transport_n_0": jnp.add,
"exponential_overload_energy_n_0": jnp.add,
"exponential_overload_energy_limited_n_0": jnp.add,
"critical_branch_count_n_0": jnp.maximum,
"critical_branch_count_limited_n_0": jnp.maximum,
"max_flow_n_1": jnp.maximum,
"median_flow_n_1": jnp.maximum,
"overload_energy_n_1": jnp.add,
"overload_energy_limited_n_1": jnp.add,
"underload_energy_n_1": jnp.add,
"transport_n_1": jnp.add,
"exponential_overload_energy_n_1": jnp.add,
"exponential_overload_energy_limited_n_1": jnp.add,
"critical_branch_count_n_1": jnp.maximum,
"critical_branch_count_limited_n_1": jnp.maximum,
"n0_n1_delta": jnp.add,
"cross_coupler_flow": jnp.add,
"switching_distance": jnp.maximum,
"split_subs": jnp.maximum,
"n_2_penalty": jnp.add,
"pst_switching_distance": jnp.maximum,
"pst_switching_distance_squared": jnp.maximum,
"pst_activated": jnp.maximum,
}
get_aggregate_metrics
#
get_aggregate_metrics(
lf_res,
success,
dynamic_information,
observed_metrics,
n_worst_contingencies,
)
Aggregate one scored batch of loadflow results into optimizer metrics.
| PARAMETER | DESCRIPTION |
|---|---|
lf_res
|
Batched loadflow results returned by the symmetric solver path.
TYPE:
|
success
|
Per-topology success mask used to invalidate failed candidates.
TYPE:
|
dynamic_information
|
Dynamic grid information required by the aggregation metrics.
TYPE:
|
observed_metrics
|
Metrics that should be preserved for scoring and result emission.
TYPE:
|
n_worst_contingencies
|
Number of worst contingency indices to keep for each topology.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
dict[str, Array]
|
Aggregated metrics for the full batch, including |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/scoring_functions.py
compute_overloads
#
compute_overloads(
topologies,
dynamic_information,
solver_config,
observed_metrics,
n_worst_contingencies=10,
)
Compute the overloads for a single timestep by invoking the solver and aggregating the results.
| PARAMETER | DESCRIPTION |
|---|---|
topologies
|
The topologies to score, where the first max_num_splits entries are the substations, the second max_num_splits entries are the branch topos and the last max_num_splits entries are the injection topos
TYPE:
|
dynamic_information
|
The dynamic information of the grid
TYPE:
|
solver_config
|
The static solver configuration
TYPE:
|
observed_metrics
|
The metrics to observe
TYPE:
|
n_worst_contingencies
|
The number of worst contingencies to return, by default 10
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
dict[str, Float[Array, ' batch_size']]
|
A dictionary with the overload energy, transport, max flow and other metrics, from aggregate_to_metric_batched |
NodalInjOptimResults
|
The results of the nodal injection optimization |
Bool[Array, ' batch_size']
|
Whether the topologies were successfully solved |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/scoring_functions.py
scoring_function
#
scoring_function(
topologies,
random_key,
dynamic_informations,
solver_configs,
target_metrics,
observed_metrics,
descriptor_metrics,
n_worst_contingencies=10,
)
Create scoring function for the genetic algorithm.
| PARAMETER | DESCRIPTION |
|---|---|
topologies
|
The topologies to score
TYPE:
|
random_key
|
The random key to use for the scoring (currently not used)
TYPE:
|
dynamic_informations
|
The dynamic information of the grid for every timestep
TYPE:
|
solver_configs
|
The solver configuration for every timestep
TYPE:
|
target_metrics
|
The list of metrics to optimize for with their weights
TYPE:
|
observed_metrics
|
The observed metrics
TYPE:
|
descriptor_metrics
|
The metrics to use as descriptors
TYPE:
|
n_worst_contingencies
|
The number of worst contingencies to consider for calculating top_k_overloads_n_1
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Float[Array, ' batch_size']
|
The fitness of the topologies, calculated as the weighted sum of the target metrics |
Int[Array, ' batch_size n_dims']
|
The descriptors of the topologies |
dict
|
The metrics of the topologies, including the target metrics and any other observed metrics |
ExtraScores
|
Emitter Information |
PRNGKeyArray
|
The random key that was passed in, unused |
Genotype
|
The genotypes that were passed in, but updated to account for in-the-loop optimizations such as the nodal injection optimization. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/scoring_functions.py
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 | |
translate_topology
#
Translate the topology into the format used by the solver.
| PARAMETER | DESCRIPTION |
|---|---|
topology
|
The topology in genotype form
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
ActionIndexComputations
|
The topology computations |
Int[Array, ' batch_size max_num_disconnections']
|
The branch disconnections to apply |
NodalInjStartOptions | None
|
The nodal injection optimization start options containing pst taps, or None if no PST optimization |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/scoring_functions.py
filter_repo
#
Reduce the repertoire to only valid and deduplicated topologies.
This will not return any topologies that are worse than the initial fitness and deduplicate the topologies. The function is currently not jax jit compatible.
| PARAMETER | DESCRIPTION |
|---|---|
repertoire
|
The repertoire to reduce |
initial_fitness
|
The initial fitness of the grid. This is used to filter out topologies that are worse than this fitness.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
DiscreteMapElitesRepertoire
|
The reduced repertoire with only valid and deduplicated topologies. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/scoring_functions.py
convert_to_topologies
#
Take a repertoire and convert it to a list of kafka-sendable topologies.
| PARAMETER | DESCRIPTION |
|---|---|
repertoire
|
The repertoire to convert. You might want to filter it using filter_repo first. |
contingency_ids
|
The contingency IDs for each topology
TYPE:
|
grid_model_low_tap
|
The lowest tap value in the grid model, used to convert the relative tap values in the genotype to absolute tap values that can be sent to the kafka topics. This will only be read if nodal_injection results are present in the genotype.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[Topology]
|
The list of topologies in the format used by the kafka topics. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/scoring_functions.py
summarize_repo
#
Summarize the repertoire into a list of topologies.
| PARAMETER | DESCRIPTION |
|---|---|
repertoire
|
The repertoire to summarize |
initial_fitness
|
The initial fitness of the grid
TYPE:
|
contingency_ids
|
The contingency IDs for each topology. Here we assume that this list is common for all the topologies in the repertoire. TODO: Fix me to have per topology contingency ids if needed
TYPE:
|
grid_model_low_tap
|
The lowest tap value in the grid model, from nodal_injection_information.grid_model_low_tap.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[Topology]
|
The summarized topologies |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/scoring_functions.py
summarize
#
summarize(
repertoire,
emitter_state,
initial_fitness,
initial_metrics,
contingency_ids,
grid_model_low_tap=None,
)
Summarize the repertoire and emitter state into a serializable dictionary.
| PARAMETER | DESCRIPTION |
|---|---|
repertoire
|
The repertoire to summarize |
emitter_state
|
The emitter state to summarize
TYPE:
|
initial_fitness
|
The initial fitness of the grid
TYPE:
|
initial_metrics
|
The initial metrics of the grid
TYPE:
|
contingency_ids
|
A list of contingency ids. Here we assume that the list of contingency ids is common for all the topologies
TYPE:
|
grid_model_low_tap
|
The lowest tap value in the grid model, from nodal_injection_information.grid_model_low_tap.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
dict
|
The summarized dictionary, json serializable |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/scoring_functions.py
toop_engine_topology_optimizer.dc.genetic_functions.crossover
#
Contains the genetic operations for the topologies.
This module contains the functions to perform the genetic operations of mutation and crossover on the topologies of the grid. The topologies are represented as Genotype dataclasses, which contain the substation ids, the branch topology, the injection topology and the disconnections.
sample_unique_from_array
#
Sample n unique elements from an array (returning indices), counting int_max as always unique.
| PARAMETER | DESCRIPTION |
|---|---|
random_key
|
The random key to use for the sampling
TYPE:
|
sample_pool
|
The array to sample from. Only unique elements are sampled, however int_max entries are not checked for uniqueness
TYPE:
|
sample_probs
|
The probabilities to sample each element
TYPE:
|
n_samples
|
The number of samples to take, should be less than the number of non-int_max entries in array.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Int[Array, ' n_samples']
|
The sampled indices into sample_pool |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/crossover.py
crossover_unbatched
#
Crossover two topologies while making sure that no substation is present twice.
This version is unbatched, i.e. it only works on a single topology. Use crossover for batched inputs.
| PARAMETER | DESCRIPTION |
|---|---|
topologies_a
|
The first topology
TYPE:
|
topologies_b
|
The second topology
TYPE:
|
random_key
|
The random key to use for the crossover
TYPE:
|
action_set
|
The branch action set containing available actions on a per-substation basis. This is needed to resolve the sub_ids for the branch actions
TYPE:
|
prob_take_a
|
The probability to take the value from topology_a, otherwise the value from topology_b is taken
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Genotype
|
The new topology |
PRNGKeyArray
|
The new random key |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/crossover.py
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | |
crossover
#
Crossover two topologies while making sure that no substation is present twice.
| PARAMETER | DESCRIPTION |
|---|---|
topologies_a
|
The first topology
TYPE:
|
topologies_b
|
The second topology
TYPE:
|
random_key
|
The random key to use for the crossover
TYPE:
|
action_set
|
The branch action set containing available actions on a per-substation basis.
TYPE:
|
prob_take_a
|
The probability to take the value from topology_a, otherwise the value from topology_b is taken
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Genotype
|
The new topology |
PRNGKeyArray
|
The new random key |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/crossover.py
Mutation#
toop_engine_topology_optimizer.dc.genetic_functions.mutation.config
#
Mutation configuration classes for the genetic algorithm.
SubstationMutationConfig
#
Bases: Module
Configuration for the substation mutation operation.
The sum of all probabilities should be <= 1.0, the remaining probability will be used for no mutation. If all substations are already split, the add_split_prob will be ignored and the probabilities will be renormalized to sum to 1.
n_subs_mutated_lambda
class-attribute
instance-attribute
#
add_split_prob
class-attribute
instance-attribute
#
The probability to split an additional substation. In case all substations are already split, this probability is ignored.
change_split_prob
class-attribute
instance-attribute
#
The probability to change an already split substation to a different split in the same or another substation.
remove_split_prob
class-attribute
instance-attribute
#
The probability to reset a substation to the unsplit state.
n_rel_subs
class-attribute
instance-attribute
#
The number of substations in the topology, used to determine the valid range of substation ids.
DisconnectionMutationConfig
#
Bases: Module
Configuration for the disconnection mutation operation.
Holds the random parameters used during the mutation of the disconnections, which are applied after the substation mutation.
add_disconnection_prob
class-attribute
instance-attribute
#
The probability to disconnect an additional branch.
change_disconnection_prob
class-attribute
instance-attribute
#
The probability to change a disconnected branch to another one.
remove_disconnection_prob
class-attribute
instance-attribute
#
The probability to remove a reconnect a disconnected branch.
n_disconnectable_branches
class-attribute
instance-attribute
#
The number of disconnectable branches in the topology, used to determine the valid range of branch ids.
NodalInjectionMutationConfig
#
Bases: Module
Configuration for the nodal injection mutation operation.
Holds the random parameters used during the mutation of the nodal injection optimization results, which are applied after the substation mutation.
pst_mutation_sigma
class-attribute
instance-attribute
#
The sigma to use for the normal distribution to sample the PST tap mutation from.
pst_mutation_probability
class-attribute
instance-attribute
#
The probability for an individual PST to be selected for mutation.
pst_reset_probability
class-attribute
instance-attribute
#
The probability for an individual PST to be reverted to its initial set point. A value of 0.0 means no reset. A value of 1.0 means all PSTs will be reset.
pst_n_taps
instance-attribute
#
The number of taps for each PST, used to determine the valid range of tap positions for mutation.
pst_start_tap_idx
instance-attribute
#
The starting tap position as an index into the tap range of each controllable PST
enable_parallel_pst_group_optim
class-attribute
instance-attribute
#
Whether PST mutations should be sampled once per configured parallel group.
parallel_pst_group_mask
class-attribute
instance-attribute
#
Boolean masks that map each controllable PST to exactly one parallel-optimization group.
__post_init__
#
Validate parallel PST grouping metadata only when grouped optimization is enabled.
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/mutation/config.py
MutationConfig
#
Bases: Module
Configuration for the mutation operation.
mutation_repetition
class-attribute
instance-attribute
#
More chance to get unique mutations by mutating mutation_repetition copies of the repertoire. The repertoire is repeated x times before mutation and deduplicated after mutation.
random_topo_prob
class-attribute
instance-attribute
#
The probability to apply a completely random topology, instead of mutating. This is added to increase the exploration capabilities of the mutation operator, but should be used with care as it can easily lead to a decrease in performance if the random topologies are of low quality.
This does not include PSTs for now.
substation_mutation_config
class-attribute
instance-attribute
#
The configuration for the substation mutation operation.
disconnection_mutation_config
class-attribute
instance-attribute
#
The configuration for the disconnection mutation operation.
nodal_injection_mutation_config
instance-attribute
#
The configuration for the nodal injection mutation operation.
toop_engine_topology_optimizer.dc.genetic_functions.mutation.mutate
#
Mutation functions for the genetic algorithm.
mutate_topology
#
mutate_topology(
random_key,
sub_ids,
disconnections_topo,
action,
mutate_config,
action_set,
allow_empty_topology=False,
)
Mutate the topology by changing the substation splits and disconnections according to the mutation configuration.
| PARAMETER | DESCRIPTION |
|---|---|
random_key
|
The random key to use for the mutation
TYPE:
|
sub_ids
|
The substation ids before the mutation
TYPE:
|
disconnections_topo
|
The disconnections before the mutation
TYPE:
|
action
|
The actions before the mutation
TYPE:
|
mutate_config
|
The mutation configuration
TYPE:
|
action_set
|
The set of possible actions
TYPE:
|
allow_empty_topology
|
Whether a topology without splits and without disconnections is a meaningful individual. This is the case if another part of the genome is mutated as well, e.g. the PST taps. See mutate_disconnections for details.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
(Int[Array, ' max_num_splits'],)
|
The splits substation ids after the mutation |
(Int[Array, ' max_num_splits'],)
|
The action ids after the mutation |
(Int[Array, ' max_num_disconnections'],)
|
The disconnections after the mutation |
PRNGKeyArray
|
The mutated substation ids, actions, disconnections, and the updated random key |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/mutation/mutate.py
create_random_topology
#
create_random_topology(
random_key,
sub_ids,
disconnections,
action_set,
n_rel_subs,
n_disconnectable_branches,
)
Create a random topology by sampling random substation splits, branch topologies and disconnections.
| PARAMETER | DESCRIPTION |
|---|---|
random_key
|
The random key to use for the mutation
TYPE:
|
sub_ids
|
The substation ids before the mutation, used to determine the number of splits to sample
TYPE:
|
disconnections
|
The disconnections before the mutation, used to determine the number of disconnections to sample
TYPE:
|
action_set
|
The set of possible actions, used to sample valid actions for the new topology
TYPE:
|
n_rel_subs
|
The number of relevant substations in the grid, used to determine the valid range of substation ids for mutation.
TYPE:
|
n_disconnectable_branches
|
The number of disconnectable branches in the grid, used to determine the valid range of branch ids for mutation.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
(Int[Array, ' max_num_splits'],)
|
The splits substation ids after the random mutation |
(Int[Array, ' max_num_splits'],)
|
The action ids after the random mutation |
(Int[Array, ' max_num_disconnections'],)
|
The disconnections after the random mutation |
PRNGKeyArray
|
The mutated substation ids, actions, disconnections, and the updated random key |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/mutation/mutate.py
mutate
#
Mutate the topologies by splitting substations, disconnecting branches and mutating nodal injections (PSTs).
Makes sure that at all times, a substation is split at most once and that all branch actions are in range of the available actions for the substation. If a substation is not split, this is indicated by the value int_max in the substation, branch.
We mutate mutation_repetition copies of the initial repertoire to increase the chance of getting unique mutations.
| PARAMETER | DESCRIPTION |
|---|---|
topologies
|
The topologies to mutate
TYPE:
|
random_key
|
The random key to use for the mutation
TYPE:
|
mutation_config
|
The mutation configuration containing the probabilities for the different mutation operations and their parameters
TYPE:
|
action_set
|
The action set containing available actions on a per-substation basis.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Genotype
|
The mutated topologies |
PRNGKeyArray
|
The new random key |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/mutation/mutate.py
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 | |
repeat_topologies
#
Repeat the topologies mutation_repetition times to increase the chance of getting unique mutations.
| PARAMETER | DESCRIPTION |
|---|---|
topologies
|
The topologies to repeat
TYPE:
|
batch_size
|
The batch size of the original topologies, used to determine the total size after repetition
TYPE:
|
mutation_repetition
|
The number of times to repeat the topologies
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Genotype
|
The repeated topologies |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/mutation/mutate.py
toop_engine_topology_optimizer.dc.genetic_functions.mutation.mutate_substations
#
Mutation functions for substations in the genetic algorithm.
change_split_substation
#
Change a split to a different one.
Either in the same substation or in a different substation. This assumes, that there is a split already.
| PARAMETER | DESCRIPTION |
|---|---|
random_key
|
The random key to use for the mutation
TYPE:
|
sub_ids
|
The substation ids before mutation
TYPE:
|
n_rel_subs
|
Number of relevant substations that may be selected.
TYPE:
|
int_max_value
|
The value that indicates an unsplit substation, used to determine which substations are currently split and to sample a new substation id from the valid range
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Int[Array, ' max_num_splits']
|
The mutated substation ids, where one split substation is changed to a different one. If there are no split substations, the input sub_ids are returned unchanged |
Int[Array, ' ']
|
The index of the substation that was mutated. If no substation was mutated, this is set to int_max |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/mutation/mutate_substations.py
unsplit_substation
#
Reset a split substation to the unsplit state, with a certain probability.
| PARAMETER | DESCRIPTION |
|---|---|
random_key
|
The random key to use for the reset
TYPE:
|
sub_ids
|
The substation ids before the reset
TYPE:
|
int_max_value
|
The value that indicates an unsplit substation, used to determine which substations are currently split and to sample a new substation id from the valid range
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Int[Array, ' max_num_splits']
|
The substation ids after the reset. If a reset occurred, the substation id at split_idx will be set to int_max |
Int[Array, ' max_num_splits']
|
The topology action after the reset. If a reset occurred, the topology at split_idx will be set to int_max |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/mutation/mutate_substations.py
split_additional_sub
#
Mutate the substation ids of a single topology.
| PARAMETER | DESCRIPTION |
|---|---|
random_key
|
The random key to use for the mutation
TYPE:
|
sub_ids
|
The substation ids before mutation
TYPE:
|
n_rel_subs
|
Number of relevant substations that may be selected.
TYPE:
|
int_max_value
|
The value to use for the mutation, which should be the maximum integer value used to indicate an empty slot in the genotype.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Int[Array, ' max_num_splits']
|
The mutated substation ids |
Int[Array, ' ']
|
The index of the substation that was mutated. If no substation was mutated, this is set to a random substation that was already split, so branch and injection mutations can still happen despite no new split. If no substation was split yet and no split happened, this is set to int_max |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/mutation/mutate_substations.py
mutate_sub_splits
#
Mutate a single substation, changing the sub_ids, branch and inj topos.
The sub-ids are implicit to the branch topo action index, however we pass them explicitely to aid substation mutation. Impossible mutations (e.g. adding a split when there is no room to add one, or removing a split when there are none) are handled by setting the probabilities for these mutations to zero, and normalising the remaining probabilities to sum to 1.
| PARAMETER | DESCRIPTION |
|---|---|
sub_ids
|
The substation ids before mutation
TYPE:
|
action
|
The branch topology before mutation
TYPE:
|
random_key
|
The random key to use for the mutation
TYPE:
|
sub_mutate_config
|
The configuration for the substation mutation, containing the probabilities for the different mutation types and the number of relevant substations in the grid, which is needed to determine the valid range of substation ids for mutation.
TYPE:
|
action_set
|
The actions for every substation. If not provided, will sample from all possible actions per substation
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
sub_ids
|
The substation ids after mutation
TYPE:
|
action
|
The branch topology after mutation
TYPE:
|
random_key
|
The random key used for the mutation
TYPE:
|
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/mutation/mutate_substations.py
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 | |
toop_engine_topology_optimizer.dc.genetic_functions.mutation.mutate_disconnections
#
Mutation functions for the disconnections in the genetic algorithm.
change_disconnected_branch
#
Change a disconnected branch in the topology to a different one.
This assumes, that one branch is already disconnected, otherwise there would be nothing to change.
| PARAMETER | DESCRIPTION |
|---|---|
random_key
|
The random key to use for the mutation
TYPE:
|
disconnections
|
The disconnections before mutation of one individual
TYPE:
|
n_disconnectable_branches
|
The number of disconnectable branches in the action set. It is not necessary to know the contents of the action set here because we only sample an index into the action set.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Int[Array, ' ']
|
The index that is changed |
Int[Array, ' ']
|
The new disconnection that is added. If no disconnection was changed, this is set to int_max |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/mutation/mutate_disconnections.py
reconnect_disconnected_branch
#
Reconnect a disconnected branch in the topology.
| PARAMETER | DESCRIPTION |
|---|---|
random_key
|
The random key to use for the mutation
TYPE:
|
disconnections
|
The disconnections before mutation of one individual
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Int[Array, ' ']
|
The index that is changed |
Int[Array, ' ']
|
The new disconnection that is added. This is always int_max to indicate that the slot is now empty |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/mutation/mutate_disconnections.py
disconnect_additional_branch
#
Add a new disconnection to the topology.
This assumes, that there is still room to add a disconnection, otherwise there would be no valid branch to add.
| PARAMETER | DESCRIPTION |
|---|---|
random_key
|
The random key to use for the mutation
TYPE:
|
disconnections
|
The disconnections before mutation of one individual
TYPE:
|
n_disconnectable_branches
|
The number of disconnectable branches in the action set. It is not necessary to know the contents of the action set here because we only sample an index into the action set.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Int[Array, ' ']
|
The index that is changed |
Int[Array, ' ']
|
The new disconnection that is added. If no disconnection was added, this is set to int_max |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/mutation/mutate_disconnections.py
mutate_disconnections
#
mutate_disconnections(
random_key,
sub_ids,
disconnections,
disconnection_mutation_config,
allow_empty_topology=False,
)
Mutate the disconnections of a single topology.
Impossible mutations (e.g. adding a disconnection when there is no room to add one, or removing a disconnection when there are none) are handled by setting the probabilities for these mutations to zero, and adding them to the remain probability.
| PARAMETER | DESCRIPTION |
|---|---|
random_key
|
The random key to use for the mutation
TYPE:
|
sub_ids
|
The substation ids of the topology, which are needed to determine whether certain disconnection mutations are allowed
TYPE:
|
disconnections
|
The disconnections before mutation of one individual
TYPE:
|
disconnection_mutation_config
|
The configuration for the disconnection mutation, containing the probabilities for the different mutation types and the number of disconnectable branches in the grid, which is needed to determine the valid range of branch ids for mutation. |
allow_empty_topology
|
Whether a topology without splits and without disconnections is a meaningful individual. This is the case if some other part of the genome is mutated as well, e.g. the PST taps. If it is not (the default), we avoid ending up with the unchanged base topology by never reconnecting the last disconnection and by always adding a disconnection to an empty topology. This is a static python bool, it must not be a traced value.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Int[Array, ' max_num_disconnections']
|
The mutated disconnections |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/mutation/mutate_disconnections.py
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 | |
toop_engine_topology_optimizer.dc.genetic_functions.mutation.mutate_nodal_inj
#
Mutation functions for the nodal injections in the genetic algorithm.
mutate_psts
#
mutate_psts(
random_key,
pst_taps,
pst_n_taps,
pst_starting_taps,
pst_mutation_sigma,
pst_mutation_probability=0.2,
pst_reset_probability=0.1,
enable_parallel_pst_group_optim=False,
parallel_pst_group_mask=None,
)
Mutate the PST taps of a single topology.
| PARAMETER | DESCRIPTION |
|---|---|
random_key
|
The random key to use for the mutation
TYPE:
|
pst_taps
|
The PST tap positions before mutation
TYPE:
|
pst_n_taps
|
The number of taps for each PST. If a PST has N taps in this array, then it is assumed that all taps from 0 to N-1 are valid tap positions. Output taps will be clipped to this range.
TYPE:
|
pst_starting_taps
|
The initial PST taps of each controllable PST.
TYPE:
|
pst_mutation_sigma
|
The sigma to use for the normal distribution to sample the mutation from. The mutation will be sampled as an integer from a normal distribution with mean 0 and sigma pst_mutation_sigma.
TYPE:
|
pst_mutation_probability
|
The probability for an individual PST to be selected for mutation. 1.0 indicates that all PSTs will be mutated, 0.0 indicates that no PSTs will be mutated. Default 0.2
TYPE:
|
pst_reset_probability
|
The probability for an individual PST to be reverted to its initial set point. A value of 0.0 means no reset. A value of 1.0 means all PSTs will be reset. Default 0.1
TYPE:
|
enable_parallel_pst_group_optim
|
Whether to enable parallel PST group optimization, which requires the presence of the parallel_pst_group mask. If enabled, whole groups of PSTs defined in the parallel_pst_group_mask will be mutated together, meaning that the mutation will be the same for all PSTs in a group. The pst_mutation_probability and pst_reset_probability will then apply to the groups instead of individual PSTs.
TYPE:
|
parallel_pst_group_mask
|
A boolean mask defining the parallel PST groups, where True indicates that a PST belongs to a group. The shape of the mask should be (n_parallel_pst_groups, n_controllable_pst). Each column should have exactly one True value, indicating that each PST belongs to exactly one group. If None or empty, parallel group optimization will be disabled regardless of the value of enable_parallel_pst_group_optim.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Int[Array, ' n_controllable_pst']
|
The mutated PST tap positions, clipped to the valid range of taps for each PST. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/mutation/mutate_nodal_inj.py
has_mutable_psts
#
Check whether the PST taps are a mutable part of the genome.
If they are, a topology without splits and without disconnections is still a meaningful individual, because it can differ from other individuals in its PST taps.
This is stricter than the early return of mutate_nodal_injections: a configuration that runs the mutation but can never select a PST for it leaves the taps unchanged as well.
| PARAMETER | DESCRIPTION |
|---|---|
nodal_inj_info
|
The nodal injection optimization results that are part of the genome. If None, the genome does not contain any PST taps.
TYPE:
|
nodal_mutation_config
|
The configuration for the nodal injection mutation. If None, the PST taps are never mutated.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
bool
|
Whether at least one PST tap can be changed by the mutation. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/mutation/mutate_nodal_inj.py
mutate_nodal_injections
#
Mutate the nodal injection optimization results, currently only the PST taps.
| PARAMETER | DESCRIPTION |
|---|---|
random_key
|
The random key to use for the mutation
TYPE:
|
nodal_inj_info
|
The nodal injection optimization results before mutation. If None, no mutation is performed and None is returned.
TYPE:
|
nodal_mutation_config
|
The configuration for the nodal injection mutation. If None, no mutation is performed
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Optional[NodalInjOptimResults]
|
The mutated nodal injection optimization results. If nodal_inj_info was None, returns None. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/mutation/mutate_nodal_inj.py
toop_engine_topology_optimizer.dc.genetic_functions.mutation.utils
#
Mutation utility functions for the genetic algorithm.
sample_new_id
#
Sample a relevant id that is not already used in the active split slots.
| PARAMETER | DESCRIPTION |
|---|---|
random_key
|
Random key used for sampling.
TYPE:
|
already_used_ids
|
Current ids that should not be sampled again.
TYPE:
|
n_available_ids
|
Number of available ids that may be selected.
TYPE:
|
ignored_idx
|
Index in
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Int[Array, ' ']
|
A valid new substation id, or |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/mutation/utils.py
get_random_true_idx
#
Return random index of a True entry, or int_max_value if none are True.
| PARAMETER | DESCRIPTION |
|---|---|
random_key
|
The random key to use for the sampling
TYPE:
|
boolean_array
|
The boolean array to sample from. Should have shape (n_possibilities,). Is true where the index is a valid choice to sample, and false where it is not. If all entries are false, int_max_value is returned.
TYPE:
|
int_max_value
|
The value to return if all entries in boolean_array are False. This should be the maximum integer value used to indicate an empty slot in the genotype.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Int[Array, ' ']
|
A random index of a True entry in boolean_array, or int_max_value if all entries are False. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/mutation/utils.py
do_nothing
#
Return a no-op mutation index and value.
| PARAMETER | DESCRIPTION |
|---|---|
int_max_value
|
The value to use for the no-op mutation, which should be the maximum integer value used to indicate an empty slot in the genotype.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Int[Array, ' ']
|
The index that is changed. This is set to int_max_value to indicate that no index is changed. |
Int[Array, ' ']
|
The new value that is added. This is set to int_max_value to indicate that no value is added. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/genetic_functions/mutation/utils.py
Repertoire#
toop_engine_topology_optimizer.dc.repertoire.discrete_map_elites
#
Core components of the MAP-Elites algorithm.
Adapted from QDax (https://github.com/adaptive-intelligent-robotics/QDax)
DiscreteMapElites
#
DiscreteMapElites(
scoring_function,
emitter,
metrics_function,
n_cells_per_dim,
cell_depth=1,
distributed=False,
)
Discrete MAP-Elites algorithm.
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/repertoire/discrete_map_elites.py
init
#
Initialize a Map-Elites repertoire with an initial population of genotypes.
Requires the definition of centroids that can be computed with any method such as CVT or Euclidean mapping.
Before the repertoire is initialised, individuals are gathered from all the devices.
Args: genotypes: initial genotypes, pytree in which leaves have shape (batch_size, num_features) random_key: a random key used for stochastic operations. n_cells_per_dim: number of cells per dimension in the repertoire
| RETURNS | DESCRIPTION |
|---|---|
An initialized MAP-Elite repertoire with the initial state of the emitter,
|
and a random key. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/repertoire/discrete_map_elites.py
update
#
Perform one iteration of the MAP-Elites algorithm.
- A batch of genotypes is sampled in the repertoire and the genotypes are copied.
- The copies are mutated and crossed-over
- The obtained offsprings are scored and then added to the repertoire.
Before the repertoire is updated, individuals are gathered from all the devices.
Args: repertoire: the MAP-Elites repertoire emitter_state: state of the emitter random_key: a jax PRNG random key
| RETURNS | DESCRIPTION |
|---|---|
the updated MAP-Elites repertoire
|
the updated (if needed) emitter state metrics about the updated repertoire a new jax PRNG key |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/repertoire/discrete_map_elites.py
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | |
toop_engine_topology_optimizer.dc.repertoire.discrete_me_repertoire
#
Contains the DiscreteMapElitesRepertoire class and utility functions.
This file contains util functions and a class to define a repertoire, used to store individuals in the MAP-Elites algorithm as well as several variants. Adapted from QDax (https://github.com/adaptive-intelligent-robotics/QDax)
DiscreteMapElitesRepertoire
#
Bases: Module
A class to store the MAP-Elites repertoire.
genotypes
instance-attribute
#
The genotypes in the repertoire.
The PyTree can be a simple Jax array or a more complex nested structure such as to represent parameters of neural network in Flax.
descriptors
instance-attribute
#
The descriptors of solutions in each cell of the repertoire.
extra_scores
instance-attribute
#
The extra scores of solutions in each cell of the repertoire. Usually the metrics
n_cells_per_dim
class-attribute
instance-attribute
#
The number of cells per dimension.
cell_depth
class-attribute
instance-attribute
#
Each cell contains cell_depth unique individuals
sample
#
Sample elements in the repertoire.
| PARAMETER | DESCRIPTION |
|---|---|
random_key
|
the random key to be used for sampling
TYPE:
|
num_samples
|
the number of samples to be drawn from the repertoire
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
samples
|
the sampled genotypes
TYPE:
|
random_key
|
the updated random key
TYPE:
|
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/repertoire/discrete_me_repertoire.py
__getitem__
#
Get a slice of the repertoire.
| PARAMETER | DESCRIPTION |
|---|---|
index
|
the index of the elements to be selected
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
a new repertoire with the selected elements
|
|
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/repertoire/discrete_me_repertoire.py
get_cells_indices
#
Compute the index for many descriptors at once.
Args: descriptors: an array that contains the descriptors of the solutions. Its shape is (batch_size, num_descriptors) n_cells_per_dim: the number of cells per dimension
| RETURNS | DESCRIPTION |
|---|---|
The index of the cell in which each descriptor belongs.
|
|
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/repertoire/discrete_me_repertoire.py
get_cell_index
#
Compute the index of the cell in which each descriptor belongs.
The index is effectively like the reshape operation, spreading multiple dimensions to a flat single dimension.
Args: descriptor: an array that contains the descriptors. There is one descriptor per dimension n_cells_per_dim: the number of cells per dimension
| RETURNS | DESCRIPTION |
|---|---|
The index of the cell in which each descriptor belongs.
|
|
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/repertoire/discrete_me_repertoire.py
add_to_repertoire
#
add_to_repertoire(
repertoire,
batch_of_genotypes,
batch_of_descriptors,
batch_of_fitnesses,
batch_of_extra_scores=None,
)
Add a batch of elements to the repertoire.
Args: repertoire: the MAP-Elites repertoire to which the elements will be added. batch_of_genotypes: a batch of genotypes to be added to the repertoire. Similarly to the repertoire.genotypes argument, this is a PyTree in which the leaves have a shape (batch_size, num_features) batch_of_descriptors: an array that contains the descriptors of the aforementioned genotypes. Its shape is (batch_size, num_descriptors). This will determine the cell in which the genotype will be stored, all descriptors are clipped to be within the bounds of n_cells_per_dim. batch_of_fitnesses: an array that contains the fitnesses of the aforementioned genotypes. Its shape is (batch_size,) batch_of_extra_scores: tree that contains the extra_scores of aforementioned genotypes.
| RETURNS | DESCRIPTION |
|---|---|
The updated MAP-Elites repertoire.
|
|
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/repertoire/discrete_me_repertoire.py
add_to_repertoire_without_cell_depth
#
add_to_repertoire_without_cell_depth(
repertoire,
batch_of_genotypes,
batch_of_descriptors,
batch_of_fitnesses,
batch_of_extra_scores=None,
)
Add a batch of elements to the repertoire.
| PARAMETER | DESCRIPTION |
|---|---|
repertoire
|
the MAP-Elites repertoire to which the elements will be added. |
batch_of_genotypes
|
a batch of genotypes to be added to the repertoire.
TYPE:
|
batch_of_descriptors
|
an array that contains the descriptors of the genotypes.
TYPE:
|
batch_of_fitnesses
|
an array that contains the fitnesses of the genotypes.
TYPE:
|
batch_of_extra_scores
|
tree that contains the extra_scores of genotypes.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
DiscreteMapElitesRepertoire
|
The updated MAP-Elites repertoire. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/repertoire/discrete_me_repertoire.py
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 | |
add_to_repertoire_with_cell_depth
#
add_to_repertoire_with_cell_depth(
repertoire,
batch_of_genotypes,
batch_of_descriptors,
batch_of_fitnesses,
batch_of_extra_scores=None,
)
Add a batch of elements to a repertoire with depth.
Assumes the repertoire puts elements on a same depth level next to another (layer1 layer1 layer2 layer2 ...) Manipulates abstract indices instead of moving genotypes directly.
| PARAMETER | DESCRIPTION |
|---|---|
repertoire
|
the MAP-Elites repertoire to which the elements will be added. |
batch_of_genotypes
|
a batch of genotypes to be added to the repertoire.
TYPE:
|
batch_of_descriptors
|
an array that contains the descriptors of the genotypes.
TYPE:
|
batch_of_fitnesses
|
an array that contains the fitnesses of the genotypes.
TYPE:
|
batch_of_extra_scores
|
tree that contains the extra_scores of genotypes.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
DiscreteMapElitesRepertoire
|
The updated MAP-Elites repertoire. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/repertoire/discrete_me_repertoire.py
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 | |
init_repertoire
#
Initialize a Map-Elites repertoire with an initial population of genotypes.
Requires the definition of centroids that can be computed with any method such as CVT or Euclidean mapping.
Note: this function has been kept outside of the object MapElites, so it can be called easily called from other modules.
Args: genotypes: initial genotypes, pytree in which leaves have shape (batch_size, num_features) fitnesses: fitness of the initial genotypes of shape (batch_size,) descriptors: descriptors of the initial genotypes of shape (batch_size, num_descriptors) extra_scores: the observed load flow metrics n_cells_per_dim: the number of cells per dimension cell_depth: the number of topologies per cell
| RETURNS | DESCRIPTION |
|---|---|
an initialized MAP-Elite repertoire
|
|
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/repertoire/discrete_me_repertoire.py
toop_engine_topology_optimizer.dc.repertoire.plotting
#
Plotting functions for the Map-Elites algorithm.
plot_repertoire_1d
#
Plot a bar chart of the repertoire's fitnesses.
| PARAMETER | DESCRIPTION |
|---|---|
fitnesses
|
The fitnesses of the repertoire
TYPE:
|
n_cells_per_dim
|
The number of cells per dimension
TYPE:
|
descriptor_metrics
|
The descriptor metrics
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Figure
|
The plot |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/repertoire/plotting.py
plot_repertoire_2d
#
Plot a heatmap of the repertoire's fitnesses.
| PARAMETER | DESCRIPTION |
|---|---|
fitnesses
|
The fitnesses of the repertoire
TYPE:
|
n_cells_per_dim
|
The number of cells per dimension
TYPE:
|
descriptor_metrics
|
The descriptor metrics
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Axes
|
The plot |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/repertoire/plotting.py
plot_repertoire
#
Plot the repertoire (1D or 2D) and saves the figure.
| PARAMETER | DESCRIPTION |
|---|---|
fitnesses
|
The fitnesses of the repertoire
TYPE:
|
iteration
|
The current iteration number
TYPE:
|
folder
|
The folder to save the plot. Will create a "plots" folder inside.
TYPE:
|
n_cells_per_dim
|
The number of cells per dimension
TYPE:
|
descriptor_metrics
|
The descriptor metrics
TYPE:
|
save_plot
|
Whether to save the plot
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Axes | Figure
|
The plot. Axes for heatmap, plt.Figure for barchart. |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/repertoire/plotting.py
Worker#
toop_engine_topology_optimizer.dc.worker.optimizer
#
Callable functions for the optimizer worker.
OptimizerData
dataclass
#
OptimizerData(
start_params,
optimization_id,
solver_configs,
algo,
initial_fitness,
initial_metrics,
jax_data,
start_time,
sent_topologies,
)
A wrapper dataclass for all the data stored by the optimizer.
Because this dataclass holds irrelevant information for the GPU optimization, it is split into two dataclasses. The parent (this one) is used to store all the information and the child (JaxOptimizerData) is used to store the information that is needed on the GPU.
jax_data
instance-attribute
#
Everything that needs to live on GPU. This dataclass is updated per-iteration while OptimizerData is only updated per-epoch, hence there are points in the command flow where this variable is out of sync. At the end of an epoch, this dataclass is updated to match the state in the optimization.
sent_topologies
instance-attribute
#
A set of strategy hashes that have already been sent to the results topic, to avoid sending duplicates.
initialize_optimization
#
initialize_optimization(
params,
optimization_id,
static_information_files,
processed_gridfile_fs,
)
Initialize the optimization run.
This function will be called at the start of the optimization run. It should be used to load the static information files and set up the optimization run.
| PARAMETER | DESCRIPTION |
|---|---|
params
|
The parameters for the optimization run
TYPE:
|
optimization_id
|
The id of the optimization run, used to annotate results and heartbeats
TYPE:
|
static_information_files
|
The paths to the static information files to load
TYPE:
|
processed_gridfile_fs
|
The target filesystem for the preprocessing worker. This contains all processed grid files. During the import job, a new folder import_results.data_folder was created which will be completed with the preprocess call to this function. Internally, only the data folder is passed around as a dirfs. Note that the unprocessed_gridfile_fs is not needed here anymore, as all preprocessing steps that need the unprocessed gridfiles were already done.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
OptimizerData
|
The data to store for the optimization run |
list[DynamicInformationStats]
|
The static information descriptions, will be sent via the heartbeats channel |
Strategy
|
The initial strategy (unsplit) for the grid, including the initial fitness and metrics |
| RAISES | DESCRIPTION |
|---|---|
Exception
|
If an error occurs during the initialization. It will be caught by the worker and sent back to the results topic |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/worker/optimizer.py
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 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | |
convert_metrics
#
Convert a metrics dictionary to a Metrics dataclass.
| PARAMETER | DESCRIPTION |
|---|---|
fitness
|
The fitness value
TYPE:
|
metrics_dict
|
The metrics dictionary
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Metrics
|
The metrics dataclass |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/worker/optimizer.py
run_single_iteration
#
Run a single iteration of the optimization.
This involves updating the genetic algorithm and calling the metrics callback
| PARAMETER | DESCRIPTION | ||
|---|---|---|---|
_i
|
The iteration number, will be ignored. Its only purpose is to make the function signature compatible with lax.fori_loop
TYPE:
|
||
jax_data
|
The data stored for the optimization run from the last epoch or from initialize_optimization
TYPE:
|
||
update_fn
|
The update function of the genetic algorithm
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
JaxOptimizerData
|
The updated data for the optimization run |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/worker/optimizer.py
run_single_device_epoch
#
Run one epoch of the optimization on a single device.
Basically this is just a fori loop over the iterations_per_epoch, calling run_single_iteration This can be used to pass to pmap
| PARAMETER | DESCRIPTION | ||
|---|---|---|---|
jax_data
|
The data stored for the optimization run from the last epoch or from initialize_optimization
TYPE:
|
||
iterations_per_epoch
|
The number of iterations to run in this epoch
TYPE:
|
||
update_fn
|
The update function of the genetic algorithm
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
JaxOptimizerData
|
The updated data for the optimization run |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/worker/optimizer.py
run_epoch
#
Run one epoch of the optimization.
This function will be called repeatedly by the worker. It should include multiple iterations, according to the configuration of the optimizer. Furthermore it should call the metrics_callback during the epoch, at least at the beginning. This could happen through a jax callback to not block the main thread.
| PARAMETER | DESCRIPTION |
|---|---|
optimizer_data
|
The data stored for the optimization run from the last epoch or from initialize_optimization
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
OptimizerData
|
The updated data for the optimization run |
| RAISES | DESCRIPTION |
|---|---|
Exception
|
If an error occurs during the epoch. It will be caught by the worker and sent back to the results topic |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/worker/optimizer.py
extract_topologies
#
Extract unique and not sent topologies from the repertoire.
Will return a list of topologies that have not been sent to the results topic yet. Also it will update the optimizer data sent set in place to include those topologies.
| PARAMETER | DESCRIPTION |
|---|---|
optimizer_data
|
The data stored for the optimization run, the sent_topologies set will be updated in place
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[Topology]
|
The topologies to send to the results topic, in message topo format |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/worker/optimizer.py
convert_topologies_to_messages
#
Convert a list of topologies in message format to a list of TopologyPushResult.
| PARAMETER | DESCRIPTION |
|---|---|
topologies
|
The topologies in message format
TYPE:
|
epoch
|
The epoch number, used to annotate the results
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[TopologyPushResult]
|
The topologies in TopologyPushResult format, ready to be sent to the results topic |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/worker/optimizer.py
toop_engine_topology_optimizer.dc.worker.worker
#
Kafka worker for the genetic algorithm optimization.
Args
#
Bases: BaseModel
Launch arguments for the worker, which can not be changed during the optimization run.
kafka_broker
class-attribute
instance-attribute
#
The Kafka broker to connect to.
optimizer_command_topic
class-attribute
instance-attribute
#
The Kafka topic to listen for commands on.
optimizer_results_topic
class-attribute
instance-attribute
#
The topic to push results to.
optimizer_heartbeat_topic
class-attribute
instance-attribute
#
The topic to push heartbeats to.
heartbeat_interval_ms
class-attribute
instance-attribute
#
The interval in milliseconds to send heartbeats.
max_command_age_hours
class-attribute
instance-attribute
#
The maximum age of a command in hours. If a command is received that is older than this, the command will be ignored.
push_topologies
#
Push topologies to the results topic.
| PARAMETER | DESCRIPTION |
|---|---|
optimizer_data
|
The data of the optimizer, containing the repertoire with topologies to push.
TYPE:
|
epoch
|
The current epoch, used for logging and to include in the messages.
TYPE:
|
send_result_fn
|
A function to call to send results back to the results topic.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
int
|
The number of topologies pushed |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/worker/worker.py
optimization_loop
#
optimization_loop(
dc_params,
grid_files,
send_result_fn,
flush_result_fn,
send_heartbeat_fn,
optimization_id,
processed_gridfile_fs,
)
Run an optimization until the optimization has converged
| PARAMETER | DESCRIPTION |
|---|---|
dc_params
|
The parameters for the optimization run, usually from the start command
TYPE:
|
grid_files
|
The grid files to load, where each gridfile represents one timestep.
TYPE:
|
send_result_fn
|
A function to queue results for the results topic. This callback is not expected to flush and will be called multiple times in every epoch, for every topology discovered. After all topologies have been sent, the flush_result_fn will be called to flush the results to Kafka.
TYPE:
|
flush_result_fn
|
A function to flush queued results to Kafka after one or more calls to
TYPE:
|
send_heartbeat_fn
|
A function to call after every epoch to signal that the worker is still alive.
TYPE:
|
optimization_id
|
The id of the optimization run. This will be used to identify the optimization run in the results. Should stay the same for the whole optimization run and should be equal to the kafka event key.
TYPE:
|
processed_gridfile_fs
|
The target filesystem for the preprocessing worker. This contains all processed grid files. During the import job, a new folder import_results.data_folder was created which will be completed with the preprocess call to this function. Internally, only the data folder is passed around as a dirfs. Note that the unprocessed_gridfile_fs is not needed here anymore, as all preprocessing steps that need the unprocessed gridfiles were already done.
TYPE:
|
| RAISES | DESCRIPTION |
|---|---|
SystemExit
|
If a ShutdownCommand is received |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/worker/worker.py
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | |
main
#
Run the main DC worker loop.
| PARAMETER | DESCRIPTION |
|---|---|
args
|
The command line arguments
TYPE:
|
processed_gridfile_fs
|
The target filesystem for the preprocessing worker. This contains all processed grid files. During the import job, a new folder import_results.data_folder was created which will be completed with the preprocess call to this function. Internally, only the data folder is passed around as a dirfs. Note that the unprocessed_gridfile_fs is not needed here anymore, as all preprocessing steps that need the unprocessed gridfiles were already done.
TYPE:
|
producer
|
The Kafka producer to send results and heartbeats with.
TYPE:
|
command_consumer
|
The Kafka consumer to receive commands with.
TYPE:
|
| RAISES | DESCRIPTION |
|---|---|
SystemExit
|
If the worker receives a ShutdownCommand |
Source code in packages/topology_optimizer_pkg/src/toop_engine_topology_optimizer/dc/worker/worker.py
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 | |