From a23f7ca82d91ef7dd72af9d8cf5a592f7736107e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Dutheillet-Lamonth=C3=A9zie?= Date: Tue, 6 Jun 2023 12:41:50 +0200 Subject: [PATCH] #386: move used function of rank_object_enumerator to lbsStatistsics module and deprecate rank_object_enumerator --- .../Applications/rank_object_enumerator.py | 76 +------------------ src/lbaf/IO/lbsStatistics.py | 73 ++++++++++++++++++ 2 files changed, 76 insertions(+), 73 deletions(-) diff --git a/src/lbaf/Applications/rank_object_enumerator.py b/src/lbaf/Applications/rank_object_enumerator.py index bda4f21ee..344bd5887 100644 --- a/src/lbaf/Applications/rank_object_enumerator.py +++ b/src/lbaf/Applications/rank_object_enumerator.py @@ -9,55 +9,12 @@ from lbaf import PROJECT_PATH from lbaf.IO.lbsVTDataReader import LoadReader from lbaf.Utils.exception_handler import exc_handler -from lbaf.Utils.logging import get_logger, Logger +from lbaf.Utils.logging import get_logger from lbaf.Utils.path import abspath from lbaf.Model.lbsPhase import Phase +from lbaf.IO.lbsStatistics import compute_arrangement_works, compute_min_max_arrangements_work -def compute_load(objects: tuple, rank_object_ids: list) -> float: - """Return a load as a sum of all object loads - """ - - return sum([objects[i].get_load() for i in rank_object_ids]) - - -def compute_volume(objects: tuple, rank_object_ids: list, direction: str) -> float: - """Return a volume of rank objects""" - - # Initialize volume - volume = 0. - - # Iterate over all rank objects - for i in rank_object_ids: - volume += sum(v for (k, v) in getattr(objects[0], direction, {}).items() if k not in rank_object_ids) - - # Return computed volume - return volume - - -def compute_arrangement_works(objects: tuple, arrangement: tuple, alpha: float, beta: float, gamma: float) -> dict: - """Return a dictionary with works of rank objects""" - - # Build object rank map from arrangement - ranks = {} - for i, j in enumerate(arrangement): - ranks.setdefault(j, []).append(i) - - # iterate over ranks - works = {} - for rank, rank_objects in ranks.items(): - # Compute per-rank loads - works[rank] = alpha * compute_load(objects, rank_objects) - - # Compute communication volumes - works[rank] += beta * max(compute_volume(objects, rank_objects, "from"), - compute_volume(objects, rank_objects, "to")) - - # Add constant - works[rank] += gamma - - # Return arrangement works - return works - +get_logger().warning('this module has been deprecated') def compute_pairwise_reachable_arrangements(objects: tuple, arrangement: tuple, alpha: float, beta: float, gamma: float, w_max: float, from_id: int, to_id: int, n_ranks: int, @@ -129,33 +86,6 @@ def compute_all_reachable_arrangements(objects: tuple, arrangement: tuple, alpha # Return dict of reachable arrangements return reachable - -def compute_min_max_arrangements_work(objects: tuple, alpha: float, beta: float, gamma: float, n_ranks: int): - """Compute all possible arrangements with repetition and minimax work""" - - # Initialize quantities of interest - n_arrangements = 0 - works_min_max = math.inf - arrangements_min_max = [] - for arrangement in itertools.product(range(n_ranks), repeat=len(objects)): - # Compute per-rank works for current arrangement - works = compute_arrangement_works(objects, arrangement, alpha, beta, gamma) - - # Update minmax when relevant - work_max = max(works.values()) - if work_max < works_min_max: - works_min_max = work_max - arrangements_min_max = [arrangement] - elif work_max == works_min_max: - arrangements_min_max.append(arrangement) - - # Keep track of number of arrangements for sanity - n_arrangements += 1 - - # Return quantities of interest - return n_arrangements, works_min_max, arrangements_min_max - - def recursively_compute_transitions(stack: list, visited: dict, objects: tuple, arrangement: tuple, alpha: float, beta: float, gamma: float, w_max: float, w_min_max: float, n_ranks: int, max_objects: int = None): diff --git a/src/lbaf/IO/lbsStatistics.py b/src/lbaf/IO/lbsStatistics.py index c61b15b6f..4939a9d6b 100644 --- a/src/lbaf/IO/lbsStatistics.py +++ b/src/lbaf/IO/lbsStatistics.py @@ -1,3 +1,4 @@ +import itertools import math import random as rnd from logging import Logger @@ -153,6 +154,78 @@ def inverse_transform_sample(cmf): return k +def compute_volume(objects: tuple, rank_object_ids: list, direction: str) -> float: + """Return a volume of rank objects""" + + # Initialize volume + volume = 0. + + # Iterate over all rank objects + for i in rank_object_ids: + volume += sum(v for (k, v) in getattr(objects[0], direction, {}).items() if k not in rank_object_ids) + + # Return computed volume + return volume + + +def compute_load(objects: tuple, rank_object_ids: list) -> float: + """Return a load as a sum of all object loads + """ + + return sum([objects[i].get_load() for i in rank_object_ids]) + + +def compute_arrangement_works(objects: tuple, arrangement: tuple, alpha: float, beta: float, gamma: float) -> dict: + """Return a dictionary with works of rank objects""" + + # Build object rank map from arrangement + ranks = {} + for i, j in enumerate(arrangement): + ranks.setdefault(j, []).append(i) + + # iterate over ranks + works = {} + for rank, rank_objects in ranks.items(): + # Compute per-rank loads + works[rank] = alpha * compute_load(objects, rank_objects) + + # Compute communication volumes + works[rank] += beta * max(compute_volume(objects, rank_objects, "from"), + compute_volume(objects, rank_objects, "to")) + + # Add constant + works[rank] += gamma + + # Return arrangement works + return works + + +def compute_min_max_arrangements_work(objects: tuple, alpha: float, beta: float, gamma: float, n_ranks: int): + """Compute all possible arrangements with repetition and minimax work""" + + # Initialize quantities of interest + n_arrangements = 0 + works_min_max = math.inf + arrangements_min_max = [] + for arrangement in itertools.product(range(n_ranks), repeat=len(objects)): + # Compute per-rank works for current arrangement + works = compute_arrangement_works(objects, arrangement, alpha, beta, gamma) + + # Update minmax when relevant + work_max = max(works.values()) + if work_max < works_min_max: + works_min_max = work_max + arrangements_min_max = [arrangement] + elif work_max == works_min_max: + arrangements_min_max.append(arrangement) + + # Keep track of number of arrangements for sanity + n_arrangements += 1 + + # Return quantities of interest + return n_arrangements, works_min_max, arrangements_min_max + + def compute_function_statistics(population, fct) -> Statistics: """Compute descriptive statistics of a function over a population."""