Skip to content

Commit

Permalink
Merge branch 'main' into feature/binary-search-tap-changer
Browse files Browse the repository at this point in the history
  • Loading branch information
Jerry-Jinfeng-Guo authored Jul 11, 2024
2 parents 29ee28d + 782deca commit d6e362f
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 4 deletions.
9 changes: 5 additions & 4 deletions src/power_grid_model/validation/rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -917,10 +917,11 @@ def all_supported_tap_control_side( # pylint: disable=too-many-arguments
invalid = np.zeros_like(mask)

for ref_component, ref_field in tap_side_fields:
indices = get_indexer(data[ref_component]["id"], data[component][regulated_object_field], default_value=-1)
found = indices != -1
ref_comp_values = data[ref_component][ref_field][indices[found]]
invalid[found] = np.logical_or(invalid[found], values[found] == ref_comp_values)
if ref_component in data:
indices = get_indexer(data[ref_component]["id"], data[component][regulated_object_field], default_value=-1)
found = indices != -1
ref_comp_values = data[ref_component][ref_field][indices[found]]
invalid[found] = np.logical_or(invalid[found], values[found] == ref_comp_values)

if invalid.any():
return [
Expand Down
4 changes: 4 additions & 0 deletions src/power_grid_model/validation/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,12 +196,16 @@ def get_indexer(source: np.ndarray, target: np.ndarray, default_value: Optional[
Raises:
IndexError: if default_value is None and there were values in target that were not in source
"""

permutation_sort = np.argsort(source) # complexity O(N_input * logN_input)
indices = np.searchsorted(source, target, sorter=permutation_sort) # complexity O(N_update * logN_input)

if default_value is None:
return permutation_sort[indices]

if len(source) == 0:
return np.full_like(target, fill_value=default_value)

clipped_indices = np.take(permutation_sort, indices, mode="clip")
return np.where(source[clipped_indices] == target, permutation_sort[clipped_indices], default_value)

Expand Down
34 changes: 34 additions & 0 deletions tests/unit/validation/test_rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
NotUniqueError,
SameValueError,
TwoValuesZeroError,
UnsupportedTransformerRegulationError,
)
from power_grid_model.validation.rules import (
all_between,
Expand All @@ -44,6 +45,7 @@
all_less_than,
all_not_two_values_equal,
all_not_two_values_zero,
all_supported_tap_control_side,
all_unique,
all_valid_clocks,
all_valid_enum_values,
Expand Down Expand Up @@ -545,3 +547,35 @@ def test_all_valid_fault_phases():
errors = all_valid_fault_phases(invalid, "fault", "foo", "bar")
assert len(errors) == 1
assert FaultPhaseError("fault", fields=["foo", "bar"], ids=list(range(26))) in errors


def test_supported_tap_control_side():
valid = {
"foo": np.array([(0, 4)], dtype=[("id", "i4"), ("foofoo", "i1")]),
"bar": np.array([(1, 5)], dtype=[("id", "i4"), ("barbar", "i1")]),
"baz": np.array([], dtype=[("id", "i4"), ("bazbaz", "i1")]),
"regulator": np.array([(2, 0, 6), (3, 1, 7)], dtype=[("id", "i4"), ("regulated", "i4"), ("control", "i1")]),
}
errors = all_supported_tap_control_side(
valid,
"regulator",
"control",
"regulated",
[("foo", "foofoo"), ("bar", "barbar"), ("baz", "bazbaz"), ("bla", "blabla")],
)
assert not errors

invalid = {
"foo": np.array([(0, 4)], dtype=[("id", "i4"), ("foofoo", "i1")]),
"bar": np.array([(1, 5)], dtype=[("id", "i4"), ("barbar", "i1")]),
"regulator": np.array([(2, 0, 4), (3, 1, 5)], dtype=[("id", "i4"), ("regulated", "i4"), ("control", "i1")]),
}
errors = all_supported_tap_control_side(
invalid,
"regulator",
"control",
"regulated",
[("foo", "foofoo"), ("bar", "barbar"), ("baz", "bazbaz")],
)
assert len(errors) == 1
assert UnsupportedTransformerRegulationError(component="regulator", fields=["control", "regulated"], ids=[2, 3])

0 comments on commit d6e362f

Please sign in to comment.