Skip to content

Commit

Permalink
Remove typing hints
Browse files Browse the repository at this point in the history
  • Loading branch information
AntoineGautier committed Sep 20, 2023
1 parent cec6bb1 commit e6dbfdb
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 78 deletions.
4 changes: 4 additions & 0 deletions Buildings/Resources/Scripts/BuildingsPy/conf.yml
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,10 @@
openmodelica:
comment: Translation failed.
translate: false
- model_name: Buildings.Templates.Components.Validation.Fans
openmodelica:
comment: Translation failed.
translate: false
- model_name: Buildings.Templates.ZoneEquipment.Validation.VAVBoxCoolingOnly
openmodelica:
comment: Translation failed.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

# Tested modifications should at least cover the options specified at:
# https://github.com/lbl-srg/ctrl-flow-dev/blob/main/server/scripts/sequence-doc/src/version/Current%20G36%20Decisions/Guideline%2036-2021%20(mappings).csv
MODIF_GRID: dict[str, dict[str, list[str]]] = {
MODIF_GRID = {
'Buildings.Templates.ChilledWaterPlants.Validation.AirCooledOpenLoop': dict(
CHI__typArrChi_select=[
'Buildings.Templates.ChilledWaterPlants.Types.ChillerArrangement.Parallel',
Expand Down Expand Up @@ -125,7 +125,7 @@
]

# See docstring of `prune_modifications` function for the structure of REMOVE_MODIF.
REMOVE_MODIF: dict[str, list[tuple[list[str], list[str]]]] = {
REMOVE_MODIF = {
'Buildings.Templates.ChilledWaterPlants.Validation.AirCooledOpenLoop': [
(
[
Expand Down Expand Up @@ -195,8 +195,8 @@
# Prune class modifications.
prune_modifications(
combinations=combinations,
remove_modif=REMOVE_MODIF,
exclude=EXCLUDE,
remove_modif=REMOVE_MODIF,
fraction_test_coverage=FRACTION_TEST_COVERAGE,
)

Expand Down
8 changes: 4 additions & 4 deletions Buildings/Resources/Scripts/travis/templates/VAVBox.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@

# Tested modifications should at least cover the options specified at:
# https://github.com/lbl-srg/ctrl-flow-dev/blob/main/server/scripts/sequence-doc/src/version/Current%20G36%20Decisions/Guideline%2036-2021%20(mappings).csv
MODIF_GRID: dict[str, dict[str, list[str]]] = {
MODIF_GRID = {
'Buildings.Templates.ZoneEquipment.Validation.VAVBoxCoolingOnly': dict(
VAVBox_1__ctl__have_occSen=[
'true',
Expand Down Expand Up @@ -61,10 +61,10 @@


# See docstring of `prune_modifications` function for the structure of EXCLUDE.
EXCLUDE: dict[str, list[list[str]]] = None
EXCLUDE = None

# See docstring of `prune_modifications` function for the structure of REMOVE_MODIF.
REMOVE_MODIF: dict[str, list[tuple[list[str], list[str]]]] = {
REMOVE_MODIF = {
'Buildings.Templates.ZoneEquipment.Validation.VAVBoxReheat': [
(
[
Expand All @@ -87,8 +87,8 @@
# Prune class modifications.
prune_modifications(
combinations=combinations,
remove_modif=REMOVE_MODIF,
exclude=EXCLUDE,
remove_modif=REMOVE_MODIF,
fraction_test_coverage=FRACTION_TEST_COVERAGE,
)

Expand Down
8 changes: 4 additions & 4 deletions Buildings/Resources/Scripts/travis/templates/VAVMultiZone.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

# Tested modifications should at least cover the options specified at:
# https://github.com/lbl-srg/ctrl-flow-dev/blob/main/server/scripts/sequence-doc/src/version/Current%20G36%20Decisions/Guideline%2036-2021%20(mappings).csv
MODIF_GRID: dict[str, dict[str, list[str]]] = {
MODIF_GRID = {
'Buildings.Templates.AirHandlersFans.Validation.VAVMultiZone': {
# FIXME(AntoineGautier #3526): Some options are currently not supported by G36 controller.
'VAV_1__redeclare__coiHeaPre': [
Expand Down Expand Up @@ -97,7 +97,7 @@
}

# See docstring of `prune_modifications` function for the structure of EXCLUDE.
EXCLUDE: dict[str, list[list[str]]] = {
EXCLUDE = {
'Buildings.Templates.AirHandlersFans.Validation.VAVMultiZone': [
[
'Buildings.Templates.Components.Fans.None fanSupBlo',
Expand All @@ -116,7 +116,7 @@
}

# See docstring of `prune_modifications` function for the structure of REMOVE_MODIF.
REMOVE_MODIF: dict[str, list[tuple[list[str], list[str]]]] = {
REMOVE_MODIF = {
'Buildings.Templates.AirHandlersFans.Validation.VAVMultiZone': [
(
[
Expand Down Expand Up @@ -227,8 +227,8 @@
# Prune class modifications.
prune_modifications(
combinations=combinations,
remove_modif=REMOVE_MODIF,
exclude=EXCLUDE,
remove_modif=REMOVE_MODIF,
fraction_test_coverage=FRACTION_TEST_COVERAGE,
)

Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
a4a8b0ecbf6f5b1be6aea3f073390f4c
177a82e207ad761a6fd52b3b5184c1ec
163 changes: 97 additions & 66 deletions Buildings/Resources/Scripts/travis/templates/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@
import random
import re
import sys

# For CPU- and I/O-heavy jobs, we prefer multiprocessing.Pool because it provides better process isolation.
from multiprocessing import Pool

import pandas as pd

assert sys.version_info >= (3, 9), "This script requires a Python version >= 3.9."
assert sys.version_info >= (3, 8), "This script requires a Python version >= 3.8."

# Simulator is used later with case-insensitive match, e.g., both Dymola and dymola can be used.
try:
Expand All @@ -35,18 +36,15 @@
CEND = '\033[0m'


def simulate_case(
arg: tuple[str, list[str], str],
simulator: str,
) -> tuple[int, str]:
def simulate_case(arg, simulator):
"""Set common parameters and run simulation with buildingspy.
Args:
arg: tuple with (model name, list of class modifications, suffix for mat file name)
simulator: Modelica tool for simulating the model
arg: tuple[str, list[str], str]: Model name, list of class modifications, suffix for mat file name.
simulator: str: Modelica tool for simulating the model.
Returns:
(error code, log) tuple: error code is 0 for success
tuple[int, str]: Error code, log.
"""
# Local imports required for multiprocessing in Jupyter notebook.
import glob
Expand Down Expand Up @@ -132,15 +130,16 @@ def simulate_case(
return toreturn, log


def simulate_cases(
args: list[tuple[str, list[str]]],
simulator: str,
asy: bool = True,
) -> list[tuple[int, str]]:
"""Main method that configures and runs all simulations.
def simulate_cases(args, simulator, asy=True):
"""Configure and run all simulations.
Args:
args: list[tuple[str, list[str]]]: List of (model name, list of class modifications, suffix for mat file name).
simulator: str: Modelica tool for simulating the model.
asy: bool: If True run simulations asynchronously.
Returns:
List of (error code, log) tuples
list[tuple[int, str]]: List of (error code, log).
"""
# Workaround for multiprocessing that isn't strictly supported on Windows Jupyter Notebook.
with open('tmp_func.py', 'w') as file:
Expand All @@ -162,16 +161,19 @@ def simulate_cases(
return results


def generate_modif_list(dic: dict[str, list[str]]) -> list[str]:
"""Generates a list of class modifications.
def generate_modif_list(dic):
"""Generate list of class modifications.
Args:
dic: A dictionary where each key is the component or variable to be modified,
and the corresponding value is a list of modifications to be applied.
Bindings for parameters of redeclared components can be appended as class modifications, e.g.
'VAV_1__redeclare__fanSupBlo': [
'Buildings.Templates.Components.Fans.ArrayVariable(nFan=2)',
],
dic: dict[str, list[str]]: Dictionary where each key is the component or variable to be modified,
and each value is a list of modifications to be applied.
Bindings for parameters of redeclared components can be appended as class modifications, e.g.
'VAV_1__redeclare__fanSupBlo': [
'Buildings.Templates.Components.Fans.ArrayVariable(nFan=2)',
],
Returns:
list[str]: List of class modifications.
"""
to_return = []
for param, val in dic.items():
Expand All @@ -196,25 +198,36 @@ def generate_modif_list(dic: dict[str, list[str]]) -> list[str]:
return to_return


def remove_items_by_indices(lst: list, indices: list[int]) -> None:
"""Removes (inplace) items from list based on their indices."""
def remove_items_by_indices(lst, indices):
"""Removes (inplace) items from list based on their indices.
Args:
lst: list
indices: list[int]
Returns:
None
"""
for idx in sorted(list(dict.fromkeys(indices)), reverse=True):
if idx < len(lst):
lst.pop(idx)


def generate_combinations(
models: list[str],
modif_grid: dict[str, dict[str, list[str]]],
) -> list[tuple[str, list[str], str]]:
def generate_combinations(models, modif_grid):
"""Generate all possible combinations.
Returns: a list of 3-tuples where
the first item of the tuple is a model to be simulated,
the second item of the tuple is the list of class modifications,
the third item of the tuple is a tag.
"""
Args:
models: list[str]: List of model names.
modif_grid: dict[str, dict[str, list[str]]]: Dictionary where each key is a model name,
and each value is a dictionary where each key resolves into a component to modify
and each value is a list of modifications to be applied to the component.
Returns:
list[tuple[str, list[str], str]]: List of 3-tuples where
the first item of the tuple is a model to be simulated,
the second item of the tuple is the list of class modifications,
the third item of the tuple is a tag.
"""
# Generate combinations.
# combinations_dicts is a dictionary where
# each key is a model to be simulated,
Expand All @@ -235,38 +248,51 @@ def generate_combinations(
return combinations


def prune_modifications(
combinations: list[tuple[str, list[str], str]],
remove_modif: dict[str, list[tuple[list[str], list[str]]]],
exclude: dict[str, list[list[str]]],
fraction_test_coverage: float,
) -> None:
def prune_modifications(combinations, exclude, remove_modif, fraction_test_coverage):
"""Remove class modifications, and update combination tag.
A combination is a model and a list of class modifications (and a tag).
For a given combination:
- The `remove_modif` argument is used to exclude a single class modification.
Removing class modifications this way yields many duplicate combinations.
These duplicates are pruned afterwards.
- The `exclude` argument is used to exclude a combination entirely, i.e., all class modifications.
EXCLUDE (first): A combination is excluded if the following exclusion test returns true.
- Look for the model (key) in exclude (dict).
- Iterate over the list of list of class modifications for this model (value of exclude[model]).
- For a given list of class modifications, return true if all strings are found in the original
class modifications of the combination (concatenated).
- Note: re patterns are supported, e.g., negative lookahead using (?!pattern)
REMOVE (after EXCLUDE): A class modification is removed from a combination according to the following rules.
For each item (2-tuple) of the list provided (as value) for each model (key) in remove_modif (dict):
- if all patterns of item[0] are found in the original class modifications of the combination (concatenated), and
- if a class modification contains any item within item[1], then
- this class modification is removed.
- Note: re patterns are supported, e.g., negative lookahead using (?!pattern)
Args:
combinations: list[tuple[str, list[str], str]]: List of combinations as generated
by `generate_combinations`.
remove_modif: dict[str, list[tuple[list[str], list[str]]]]: Dictionary providing modifications
to be removed, see below.
exclude: dict[str, list[list[str]]]: Dictionary providing modifications to be excluded, see below.
fraction_test_coverage: float = Fraction (>0 and <=1) of test coverage to further reduce the number
of combinations (randomly). 1 should be for used for PR against master.
Returns:
None (modifies inplace)
Details:
A combination is a model and a list of class modifications (and a tag).
For a given combination:
- The `remove_modif` argument is used to remove a *single* class modification.
Removing class modifications this way yields many duplicate combinations.
These duplicates are pruned afterwards.
- The `exclude` argument is used to exclude a combination entirely, i.e., *all* class modifications.
Exclude (first): A combination is excluded if the following exclusion test returns true.
- Look for the model (key) in exclude (dict).
- Iterate over the list of list of class modifications for this model (value of exclude[model]).
- For a given list of class modifications, return true if all strings are found in the original
class modifications of the combination (concatenated).
- Note: re patterns are supported, e.g., negative lookahead using (?!pattern)
Remove (after exclude): A class modification is removed from a combination according to the following rules.
For each item (2-tuple) of the list provided (as value) for each model (key) in remove_modif (dict):
- if all patterns of item[0] are found in the original class modifications of the combination (concatenated), and
- if a class modification contains any item within item[1], then
- this class modification is removed.
- Note: re patterns are supported, e.g., negative lookahead using (?!pattern)
Example:
- Exclude: For a CHW plant, a combination with chillers in series arrangement and dedicated primary CHW pumps
can be excluded.
- Remove single modification: For a VAV air handler, a combination with a electric heating coil and a three-way valve
for the heating coil should use `remove_modif` to remove the valve component modification. We cannot use
`exclude` here because there is a modification of the valve component in each combination, so we would end up
excluding all combinations with a electric heating coil.
"""
# Exclude cases.
## We iterate over a copy of the `combinations` list to allow removing items of `combinations` during iteration.
Expand Down Expand Up @@ -315,11 +341,16 @@ class modifications of the combination (concatenated).
combinations[i] = (*combinations[i][:2], str(i))


def report_clean(
combinations: list[tuple[str, list[str], str]],
results: list[tuple[int, str]],
) -> pd.DataFrame:
"""Report and clean after simulations."""
def report_clean(combinations, results):
"""Report and clean after simulations.
Args:
combinations: list[tuple[str, list[str], str]]: List of combinations.
results: list[tuple[int, str]]: List of (error code, log).
Returns:
pd.DataFrame
"""

try:
os.unlink('tmp_func.py')
Expand Down

0 comments on commit e6dbfdb

Please sign in to comment.