← Back to InConsistencySize documentation
InConsistencySize - Source Code¶
File: Distributed_Design_Optimizer/middlelevel/consensus_alc/InConsistencySize.py
# Copyright (C) The DistributedDesignOptimizer Contributors
# Licensed under the GNU General Public License v3.0. See LICENSE file for details.
"""Inconsistency size computation for consensus-based ALC.
This module provides functionality for computing inconsistency sizes
between coupled variables in consensus-based ALC.
"""
from typing import List
import copy
from Distributed_Design_Optimizer.middlelevel import InConsistencySizeBasis
from Distributed_Design_Optimizer.subsystem.tools import update_state_listprimitive
class InConsistencySize(InConsistencySizeBasis):
"""Inconsistency size storage for consensus-based ALC.
Stores and computes the size of inconsistencies between coupled
variables in consensus-based ALC coordination.
"""
def __init__(self,
id: str) -> None:
"""Initialize inconsistency size.
Args:
id: Identifier for this inconsistency measure.
"""
# call __init__() of InConsistencySizeBasis
super().__init__(id)
# FOR CONSENSUS CONSTRAINTS:
self._auxiliary_minus_mappedresponse: List[float] | None = None
self._auxiliary_minus_couplingvariable: List[float] | None = None
self._auxiliary_minus_shareddesignvariable: List[float] | None = None
self._auxiliary_minus_targetshareddesignvariable: List[float] | None = None
self._auxiliary_minus_mappedresponse_infynorm: float | None = None
self._auxiliary_minus_couplingvariable_infynorm: float | None = None
self._auxiliary_minus_shareddesignvariable_infynorm: float | None = None
self._auxiliary_minus_targetshareddesignvariable_infynorm: float | None = None
self._auxiliary_minus_mappedresponse_infynormID: int | None = None
self._auxiliary_minus_couplingvariable_infynormID: int | None = None
self._auxiliary_minus_shareddesignvariable_infynormID: int | None = None
self._auxiliary_minus_targetshareddesignvariable_infynormID: int | None = None
self._oscillationindex_auxiliary_minus_mappedresponse: List[float | None] | None = None
self._oscillationindex_auxiliary_minus_couplingvariable: List[float | None] | None = None
self._oscillationindex_auxiliary_minus_shareddesignvariable: List[float | None] | None = None
self._oscillationindex_auxiliary_minus_targetshareddesignvariable: List[float | None] | None = None
# Auxiliary minus mapped response
def evaluate_Auxiliary_Minus_MappedResponse(self, auxiliary: List[float], mappedresponse: List[float]) -> None:
"""Set the inconsistency between the auxiliary variable and the mapped response for consensus constraints.
Args:
auxiliary: Auxiliary variable values.
mappedresponse: Mapped response values.
"""
# No copy.copy() needed - list comprehension creates a new list with no reference
# to the input lists, so modifications in the caller cannot affect the class attribute.
# element-wise difference using list comprehension (faster than np.array conversion)
self._auxiliary_minus_mappedresponse = [s - d for s, d in zip(auxiliary, mappedresponse)]
# Single-pass computation of infinity norm and its index
max_idx, max_val = max(enumerate(self._auxiliary_minus_mappedresponse), key=lambda x: abs(x[1]))
self._auxiliary_minus_mappedresponse_infynorm = abs(max_val)
self._auxiliary_minus_mappedresponse_infynormID = max_idx
def get_Auxiliary_Minus_MappedResponse(self) -> List[float] | None:
"""Get the inconsistency between the auxiliary variable and the mapped response for consensus constraints.
Returns:
List of inconsistency values or None if not set.
"""
# copy.copy() used - List[float] is mutable. This prevents modifications
# in the caller from being reflected back to the class attribute.
return copy.copy(self._auxiliary_minus_mappedresponse)
def get_Auxiliary_Minus_MappedResponse_InfyNorm(self) -> float | None:
"""Get the maximum auxiliary-minus-mapped-response inconsistency (infinity norm).
Returns:
Maximum inconsistency value or None if not set.
"""
# No copy.copy() needed - float is a primitive/immutable type.
# Assigning this return value to a variable in the caller creates a new binding;
# modifications there won't affect this class's attribute.
return self._auxiliary_minus_mappedresponse_infynorm
def get_Auxiliary_Minus_MappedResponse_InfyNormID(self) -> int | None:
"""Get the index of the maximum auxiliary-minus-mapped-response inconsistency.
Returns:
Index of maximum inconsistency or None if not set.
"""
# No copy.copy() needed - int is a primitive/immutable type.
# Assigning this return value to a variable in the caller creates a new binding;
# modifications there won't affect this class's attribute.
return self._auxiliary_minus_mappedresponse_infynormID
# Auxiliary minus coupling variable
def evaluate_Auxiliary_Minus_CouplingVariable(self, auxiliary: List[float], couplingvariable: List[float]) -> None:
"""Set the inconsistency between the auxiliary variable and the coupling variable for consensus constraints.
Args:
auxiliary: Auxiliary variable values.
couplingvariable: Coupling variable values.
"""
# No copy.copy() needed - list comprehension creates a new list with no reference
# to the input lists, so modifications in the caller cannot affect the class attribute.
# element-wise difference using list comprehension (faster than np.array conversion)
self._auxiliary_minus_couplingvariable = [s - d for s, d in zip(auxiliary, couplingvariable)]
# Single-pass computation of infinity norm and its index
max_idx, max_val = max(enumerate(self._auxiliary_minus_couplingvariable), key=lambda x: abs(x[1]))
self._auxiliary_minus_couplingvariable_infynorm = abs(max_val)
self._auxiliary_minus_couplingvariable_infynormID = max_idx
def get_Auxiliary_Minus_CouplingVariable(self) -> List[float] | None:
"""Get the inconsistency between the auxiliary variable and the coupling variable for consensus constraints.
Returns:
List of inconsistency values or None if not set.
"""
# copy.copy() used - List[float] is mutable. This prevents modifications
# in the caller from being reflected back to the class attribute.
return copy.copy(self._auxiliary_minus_couplingvariable)
def get_Auxiliary_Minus_CouplingVariable_InfyNorm(self) -> float | None:
"""Get the maximum auxiliary-minus-coupling-variable inconsistency (infinity norm).
Returns:
Maximum inconsistency value or None if not set.
"""
# No copy.copy() needed - float is a primitive/immutable type.
# Assigning this return value to a variable in the caller creates a new binding;
# modifications there won't affect this class's attribute.
return self._auxiliary_minus_couplingvariable_infynorm
def get_Auxiliary_Minus_CouplingVariable_InfyNormID(self) -> int | None:
"""Get the index of the maximum auxiliary-minus-coupling-variable inconsistency.
Returns:
Index of maximum inconsistency or None if not set.
"""
# No copy.copy() needed - int is a primitive/immutable type.
# Assigning this return value to a variable in the caller creates a new binding;
# modifications there won't affect this class's attribute.
return self._auxiliary_minus_couplingvariable_infynormID
# Auxiliary minus shared design variable
def evaluate_Auxiliary_Minus_SharedDesignVariable(self, auxiliary: List[float], shareddesignvariable: List[float]) -> None:
"""Set the inconsistency for shared design variables in consensus constraints.
Args:
auxiliary: Auxiliary variable values.
shareddesignvariable: Shared design variable values.
"""
# No copy.copy() needed - list comprehension creates a new list with no reference
# to the input lists, so modifications in the caller cannot affect the class attribute.
# element-wise difference using list comprehension (faster than np.array conversion)
self._auxiliary_minus_shareddesignvariable = [s - d for s, d in zip(auxiliary, shareddesignvariable)]
# Single-pass computation of infinity norm and its index
max_idx, max_val = max(enumerate(self._auxiliary_minus_shareddesignvariable), key=lambda x: abs(x[1]))
self._auxiliary_minus_shareddesignvariable_infynorm = abs(max_val)
self._auxiliary_minus_shareddesignvariable_infynormID = max_idx
def get_Auxiliary_Minus_SharedDesignVariable(self) -> List[float] | None:
"""Get the inconsistency for shared design variables in consensus constraints.
Returns:
List of inconsistency values or None if not set.
"""
# copy.copy() used - List[float] is mutable. This prevents modifications
# in the caller from being reflected back to the class attribute.
return copy.copy(self._auxiliary_minus_shareddesignvariable)
def get_Auxiliary_Minus_SharedDesignVariable_InfyNorm(self) -> float | None:
"""Get the maximum shared design variables auxiliary inconsistency (infinity norm).
Returns:
Maximum inconsistency value or None if not set.
"""
# No copy.copy() needed - float is a primitive/immutable type.
# Assigning this return value to a variable in the caller creates a new binding;
# modifications there won't affect this class's attribute.
return self._auxiliary_minus_shareddesignvariable_infynorm
def get_Auxiliary_Minus_SharedDesignVariable_InfyNormID(self) -> int | None:
"""Get the index of the maximum shared design variables auxiliary inconsistency.
Returns:
Index of maximum inconsistency or None if not set.
"""
# No copy.copy() needed - int is a primitive/immutable type.
# Assigning this return value to a variable in the caller creates a new binding;
# modifications there won't affect this class's attribute.
return self._auxiliary_minus_shareddesignvariable_infynormID
# Auxiliary minus target shared design variable
def evaluate_Auxiliary_Minus_TargetSharedDesignVariable(self, auxiliary: List[float], targetshareddesignvariable: List[float]) -> None:
"""Set the inconsistency for target shared design variables in consensus constraints.
Args:
auxiliary: Auxiliary variable values.
targetshareddesignvariable: Target shared design variable values.
"""
# No copy.copy() needed - list comprehension creates a new list with no reference
# to the input lists, so modifications in the caller cannot affect the class attribute.
# element-wise difference using list comprehension (faster than np.array conversion)
self._auxiliary_minus_targetshareddesignvariable = [s - d for s, d in zip(auxiliary, targetshareddesignvariable)]
# Single-pass computation of infinity norm and its index
max_idx, max_val = max(enumerate(self._auxiliary_minus_targetshareddesignvariable), key=lambda x: abs(x[1]))
self._auxiliary_minus_targetshareddesignvariable_infynorm = abs(max_val)
self._auxiliary_minus_targetshareddesignvariable_infynormID = max_idx
def get_Auxiliary_Minus_TargetSharedDesignVariable(self) -> List[float] | None:
"""Get the inconsistency for target shared design variables in consensus constraints.
Returns:
List of inconsistency values or None if not set.
"""
# copy.copy() used - List[float] is mutable. This prevents modifications
# in the caller from being reflected back to the class attribute.
return copy.copy(self._auxiliary_minus_targetshareddesignvariable)
def get_Auxiliary_Minus_TargetSharedDesignVariable_InfyNorm(self) -> float | None:
"""Get the maximum target shared design variables auxiliary inconsistency (infinity norm).
Returns:
Maximum inconsistency value or None if not set.
"""
# No copy.copy() needed - float is a primitive/immutable type.
# Assigning this return value to a variable in the caller creates a new binding;
# modifications there won't affect this class's attribute.
return self._auxiliary_minus_targetshareddesignvariable_infynorm
def get_Auxiliary_Minus_TargetSharedDesignVariable_InfyNormID(self) -> int | None:
"""Get the index of the maximum target shared design variables auxiliary inconsistency.
Returns:
Index of maximum inconsistency or None if not set.
"""
# No copy.copy() needed - int is a primitive/immutable type.
# Assigning this return value to a variable in the caller creates a new binding;
# modifications there won't affect this class's attribute.
return self._auxiliary_minus_targetshareddesignvariable_infynormID
# Auxiliary inconsistency oscillations
def set_OscillationIndex_Auxiliary_Minus_MappedResponse(self, oscillationindex: List[float | None]) -> None:
"""Set oscillation index for auxiliary-minus-mapped-response inconsistency.
Args:
oscillationindex: List of oscillation index values.
"""
# copy.copy() used - List[float | None] is mutable. This prevents modifications
# in the caller from being reflected back to the class attribute.
self._oscillationindex_auxiliary_minus_mappedresponse = copy.copy(oscillationindex)
def get_OscillationIndex_Auxiliary_Minus_MappedResponse(self) -> List[float | None] | None:
"""Get oscillation index for auxiliary-minus-mapped-response inconsistency.
Returns:
List of oscillation index values or None if not set.
"""
# copy.copy() used - List[float | None] is mutable. This prevents modifications
# in the caller from being reflected back to the class attribute.
return copy.copy(self._oscillationindex_auxiliary_minus_mappedresponse)
def set_OscillationIndex_Auxiliary_Minus_CouplingVariable(self, oscillationindex: List[float | None]) -> None:
"""Set oscillation index for auxiliary-minus-coupling-variable inconsistency.
Args:
oscillationindex: List of oscillation index values.
"""
# copy.copy() used - List[float | None] is mutable. This prevents modifications
# in the caller from being reflected back to the class attribute.
self._oscillationindex_auxiliary_minus_couplingvariable = copy.copy(oscillationindex)
def get_OscillationIndex_Auxiliary_Minus_CouplingVariable(self) -> List[float | None] | None:
"""Get oscillation index for auxiliary-minus-coupling-variable inconsistency.
Returns:
List of oscillation index values or None if not set.
"""
# copy.copy() used - List[float | None] is mutable. This prevents modifications
# in the caller from being reflected back to the class attribute.
return copy.copy(self._oscillationindex_auxiliary_minus_couplingvariable)
def set_OscillationIndex_Auxiliary_Minus_SharedDesignVariable(self, oscillationindex: List[float | None]) -> None:
"""Set oscillation index for shared design variables auxiliary inconsistency.
Args:
oscillationindex: List of oscillation index values.
"""
# copy.copy() used - List[float | None] is mutable. This prevents modifications
# in the caller from being reflected back to the class attribute.
self._oscillationindex_auxiliary_minus_shareddesignvariable = copy.copy(oscillationindex)
def get_OscillationIndex_Auxiliary_Minus_SharedDesignVariable(self) -> List[float | None] | None:
"""Get oscillation index for shared design variables auxiliary inconsistency.
Returns:
List of oscillation index values or None if not set.
"""
# copy.copy() used - List[float | None] is mutable. This prevents modifications
# in the caller from being reflected back to the class attribute.
return copy.copy(self._oscillationindex_auxiliary_minus_shareddesignvariable)
def set_OscillationIndex_Auxiliary_Minus_TargetSharedDesignVariable(self, oscillationindex: List[float | None]) -> None:
"""Set oscillation index for target shared design variables auxiliary inconsistency.
Args:
oscillationindex: List of oscillation index values.
"""
# copy.copy() used - List[float | None] is mutable. This prevents modifications
# in the caller from being reflected back to the class attribute.
self._oscillationindex_auxiliary_minus_targetshareddesignvariable = copy.copy(oscillationindex)
def get_OscillationIndex_Auxiliary_Minus_TargetSharedDesignVariable(self) -> List[float | None] | None:
"""Get oscillation index for target shared design variables auxiliary inconsistency.
Returns:
List of oscillation index values or None if not set.
"""
# copy.copy() used - List[float | None] is mutable. This prevents modifications
# in the caller from being reflected back to the class attribute.
return copy.copy(self._oscillationindex_auxiliary_minus_targetshareddesignvariable)
# necessary method when running multiprocessing
def update_state(self, other_inconsistency: 'InConsistencySize') -> None:
"""Update the state of this InConsistencySize with the state of another InConsistencySize.
This method updates the numerical information stored in the class's attributes
without changing the original memory address location. This is necessary for
multiprocessing, where executed subsystems return from separate processes and
their state must be transferred back to the original objects in the main process.
Args:
other_inconsistency: The source instance to copy state from.
"""
# Call the base class update_state to handle all non-auxiliary attributes
super().update_state(other_inconsistency)
# FOR CONSENSUS CONSTRAINTS (AUXILIARY):
# Auxiliary inconsistency values - List[float] updated via utility function
self._auxiliary_minus_mappedresponse: List[float] | None = update_state_listprimitive(self._auxiliary_minus_mappedresponse, other_inconsistency.get_Auxiliary_Minus_MappedResponse())
self._auxiliary_minus_couplingvariable: List[float] | None = update_state_listprimitive(self._auxiliary_minus_couplingvariable, other_inconsistency.get_Auxiliary_Minus_CouplingVariable())
self._auxiliary_minus_shareddesignvariable: List[float] | None = update_state_listprimitive(self._auxiliary_minus_shareddesignvariable, other_inconsistency.get_Auxiliary_Minus_SharedDesignVariable())
self._auxiliary_minus_targetshareddesignvariable: List[float] | None = update_state_listprimitive(self._auxiliary_minus_targetshareddesignvariable, other_inconsistency.get_Auxiliary_Minus_TargetSharedDesignVariable())
# Auxiliary infinity norms - float is immutable, no copy.copy() needed
self._auxiliary_minus_mappedresponse_infynorm: float | None = other_inconsistency.get_Auxiliary_Minus_MappedResponse_InfyNorm()
self._auxiliary_minus_couplingvariable_infynorm: float | None = other_inconsistency.get_Auxiliary_Minus_CouplingVariable_InfyNorm()
self._auxiliary_minus_shareddesignvariable_infynorm: float | None = other_inconsistency.get_Auxiliary_Minus_SharedDesignVariable_InfyNorm()
self._auxiliary_minus_targetshareddesignvariable_infynorm: float | None = other_inconsistency.get_Auxiliary_Minus_TargetSharedDesignVariable_InfyNorm()
# Auxiliary infinity norm IDs - int is immutable, no copy.copy() needed
self._auxiliary_minus_mappedresponse_infynormID: int | None = other_inconsistency.get_Auxiliary_Minus_MappedResponse_InfyNormID()
self._auxiliary_minus_couplingvariable_infynormID: int | None = other_inconsistency.get_Auxiliary_Minus_CouplingVariable_InfyNormID()
self._auxiliary_minus_shareddesignvariable_infynormID: int | None = other_inconsistency.get_Auxiliary_Minus_SharedDesignVariable_InfyNormID()
self._auxiliary_minus_targetshareddesignvariable_infynormID: int | None = other_inconsistency.get_Auxiliary_Minus_TargetSharedDesignVariable_InfyNormID()
# Auxiliary inconsistency oscillation indices - List[float | None] updated via utility function
self._oscillationindex_auxiliary_minus_mappedresponse: List[float | None] | None = update_state_listprimitive(self._oscillationindex_auxiliary_minus_mappedresponse, other_inconsistency.get_OscillationIndex_Auxiliary_Minus_MappedResponse())
self._oscillationindex_auxiliary_minus_couplingvariable: List[float | None] | None = update_state_listprimitive(self._oscillationindex_auxiliary_minus_couplingvariable, other_inconsistency.get_OscillationIndex_Auxiliary_Minus_CouplingVariable())
self._oscillationindex_auxiliary_minus_shareddesignvariable: List[float | None] | None = update_state_listprimitive(self._oscillationindex_auxiliary_minus_shareddesignvariable, other_inconsistency.get_OscillationIndex_Auxiliary_Minus_SharedDesignVariable())
self._oscillationindex_auxiliary_minus_targetshareddesignvariable: List[float | None] | None = update_state_listprimitive(self._oscillationindex_auxiliary_minus_targetshareddesignvariable, other_inconsistency.get_OscillationIndex_Auxiliary_Minus_TargetSharedDesignVariable())