diff --git a/README.md b/README.md index f4655e04..ff9bf09c 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ _Please refer to our [documentation](https://darma-tasking.github.io/lbaf_docs/i ## Getting Started -LBAF currently supports Python 3.8 - 3.11. You can download Python [here](https://www.python.org/downloads/). +LBAF currently supports Python 3.9 - 3.11. You can download Python [here](https://www.python.org/downloads/). ### Optional: Create a virtual environment *(recommended in development)* @@ -37,7 +37,7 @@ source venv/bin/activate ``` > [!NOTE] -> You can create separate virtual environments for different development branches. For example, a Python 3.8 environment for branch 125 could be named `venv38-branch-125`. Within this environment, you can install `lbaf` as an editable package (see below). +> You can create separate virtual environments for different development branches. For example, a Python 3.9 environment for branch 125 could be named `venv38-branch-125`. Within this environment, you can install `lbaf` as an editable package (see below). ## Installation diff --git a/config/synthetic-blocks.yaml b/config/synthetic-blocks.yaml index 596da854..91961c73 100644 --- a/config/synthetic-blocks.yaml +++ b/config/synthetic-blocks.yaml @@ -27,7 +27,7 @@ algorithm: order_strategy: arbitrary transfer_strategy: Clustering max_subclusters: 4 - criterion: TemperedWithUpdates + criterion: Tempered max_objects_per_transfer: 8 deterministic_transfer: true diff --git a/src/lbaf/Execution/lbsCriterionBase.py b/src/lbaf/Execution/lbsCriterionBase.py index 14ab9092..c83d9610 100644 --- a/src/lbaf/Execution/lbsCriterionBase.py +++ b/src/lbaf/Execution/lbsCriterionBase.py @@ -89,11 +89,8 @@ def factory(criterion_name: str, work_model: WorkModelBase, logger: Logger): """Produce the necessary concrete criterion.""" # Load up available criteria - # pylint:disable=W0641:possibly-unused-variable,C0415:import-outside-toplevel from .lbsTemperedCriterion import TemperedCriterion - from .lbsTemperedWithUpdatesCriterion import TemperedWithUpdatesCriterion from .lbsStrictLocalizingCriterion import StrictLocalizingCriterion - # pylint:enable=W0641:possibly-unused-variable,C0415:import-outside-toplevel # Ensure that criterion name is valid try: diff --git a/src/lbaf/Execution/lbsTemperedCriterion.py b/src/lbaf/Execution/lbsTemperedCriterion.py index 9826535e..552f6094 100644 --- a/src/lbaf/Execution/lbsTemperedCriterion.py +++ b/src/lbaf/Execution/lbsTemperedCriterion.py @@ -48,7 +48,7 @@ class TemperedCriterion(CriterionBase): - """A concrete class for the Grapevine criterion modified in line 6.""" + """A concrete class for the Grapevine criterion with update formulae.""" def __init__(self, work_model, lgr: Logger): """Class constructor.""" @@ -57,7 +57,7 @@ def __init__(self, work_model, lgr: Logger): self._logger.info(f"Instantiated {type(self).__name__} concrete criterion") def compute(self, r_src: Rank, o_src: list, r_dst: Rank, o_dst: Optional[list]=None) -> float: - """Tempered work criterion based on L1 norm of works.""" + """Tempered work criterion based on L1 norm of works using update formulae.""" if o_dst is None: o_dst = [] @@ -66,16 +66,10 @@ def compute(self, r_src: Rank, o_src: list, r_dst: Rank, o_dst: Optional[list]=N self._work_model.compute(r_src), self._work_model.compute(r_dst)) - # Move objects into proposed new arrangement - self._phase.transfer_objects(r_src, o_src, r_dst, o_dst) - - # Compute maximum work of proposed new arrangement + # Compute update formulae w_max_new = max( - self._work_model.compute(r_src), - self._work_model.compute(r_dst)) - - # Move objects back into original arrangement - self._phase.transfer_objects(r_dst, o_src, r_src, o_dst) + self._work_model.update(r_src, o_src, o_dst), + self._work_model.update(r_dst, o_dst, o_src)) # Return criterion value return w_max_0 - w_max_new diff --git a/src/lbaf/Execution/lbsTemperedWithUpdatesCriterion.py b/src/lbaf/Execution/lbsTemperedWithUpdatesCriterion.py deleted file mode 100644 index 46ad75dc..00000000 --- a/src/lbaf/Execution/lbsTemperedWithUpdatesCriterion.py +++ /dev/null @@ -1,91 +0,0 @@ -# -#@HEADER -############################################################################### -# -# lbsTemperedWithUpdatesCriterion.py -# DARMA/LB-analysis-framework => LB Analysis Framework -# -# Copyright 2019-2024 National Technology & Engineering Solutions of Sandia, LLC -# (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S. -# Government retains certain rights in this software. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# -# * Neither the name of the copyright holder nor the names of its -# contributors may be used to endorse or promote products derived from this -# software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -# -# Questions? Contact darma@sandia.gov -# -############################################################################### -#@HEADER -# -from logging import Logger -from typing import Optional - -from .lbsCriterionBase import CriterionBase -from ..Model.lbsRank import Rank - - -class TemperedWithUpdatesCriterion(CriterionBase): - """A concrete class for the Grapevine criterion with update formulae.""" - - def __init__(self, work_model, lgr: Logger): - """Class constructor.""" - # Call superclass init - super().__init__(work_model, lgr) - self._logger.info(f"Instantiated {type(self).__name__} concrete criterion") - - def compute(self, r_src: Rank, o_src: list, r_dst: Rank, o_dst: Optional[list]=None) -> float: - """Tempered work criterion based on L1 norm of works using update formulae.""" - if o_dst is None: - o_dst = [] - - # Compute maximum work of original arrangement - w_max_0 = max( - self._work_model.compute(r_src), - self._work_model.compute(r_dst)) - - # Compute update formulae - w_max_up = max( - w1 := self._work_model.update(r_src, o_src, o_dst), - w2 := self._work_model.update(r_dst, o_dst, o_src)) - - # Move objects into proposed new arrangement - self._phase.transfer_objects(r_src, o_src, r_dst, o_dst) - - # Compute maximum work of proposed new arrangement - w_max_new = max( - w3 := self._work_model.compute(r_src), - w4 := self._work_model.compute(r_dst)) - - # Move objects back into original arrangement - self._phase.transfer_objects(r_dst, o_src, r_src, o_dst) - - # Sanity check - if w_max_new != w_max_up: - self._logger.error(f"Updated work: max({w1},{w2}) <> computed: max({w3},{w4})") - raise SystemExit(1) - - # Return criterion value - return w_max_0 - w_max_new diff --git a/src/lbaf/IO/lbsConfigurationValidator.py b/src/lbaf/IO/lbsConfigurationValidator.py index d8bced42..c91c8701 100644 --- a/src/lbaf/IO/lbsConfigurationValidator.py +++ b/src/lbaf/IO/lbsConfigurationValidator.py @@ -67,7 +67,7 @@ "CentralizedPrefixOptimizer", "PrescribedPermutation", "PhaseStepper") -ALLOWED_CRITERIA = ("Tempered", "TemperedWithUpdates", "StrictLocalizing") +ALLOWED_CRITERIA = ("Tempered", "StrictLocalizing") ALLOWED_LOGGING_LEVELS = ("info", "debug", "warning", "error") ALLOWED_LOAD_VOLUME_SAMPLER = ("uniform", "lognormal") diff --git a/src/lbaf/Model/lbsAffineCombinationWorkModel.py b/src/lbaf/Model/lbsAffineCombinationWorkModel.py index 0710624b..9bae141b 100644 --- a/src/lbaf/Model/lbsAffineCombinationWorkModel.py +++ b/src/lbaf/Model/lbsAffineCombinationWorkModel.py @@ -231,9 +231,9 @@ def __update_homing(self, rank: Rank, o_snd: list, o_rcv: list): # Remove object from rank r_obj.discard(o) - # Skip locally homed blocks + # Retrieve shared block and skip if none or not locally homed b = o.get_shared_block() - if b.get_home_id() == r_id: + if b is None or b.get_home_id() == r_id: continue # Determine set of removed non-homed blocks @@ -249,9 +249,9 @@ def __update_homing(self, rank: Rank, o_snd: list, o_rcv: list): # Iterate over all received objects for o in o_rcv: - # Skip locally homed blocks + # Retrieve shared block and skip if none or not locally homed b = o.get_shared_block() - if b.get_home_id() == r_id: + if b is None or b.get_home_id() == r_id: continue # Determine set of added non-homed blocks