Skip to content

Combine nchoosek to support variables being shared across nchoosek#753

Open
dlinzner-bcs wants to merge 22 commits into
mainfrom
combine_nchoosek_to_support_variables_being_shared_across_nchoosek
Open

Combine nchoosek to support variables being shared across nchoosek#753
dlinzner-bcs wants to merge 22 commits into
mainfrom
combine_nchoosek_to_support_variables_being_shared_across_nchoosek

Conversation

@dlinzner-bcs
Copy link
Copy Markdown
Contributor

Motivation

We have use-cases, where variables need to be subject to multiple nchoosek constraints at once. This is currently not supported.

Have you read the Contributing Guidelines on pull requests?

Yes

Have you updated CHANGELOG.md?

yes

Test Plan

Added three tests to tests\bofire\strategies\test_doe.py

Copy link
Copy Markdown
Contributor

@bertiqwerty bertiqwerty left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Dominik! Please check my current comments. I hope that we can clarify some of the confusion that goes on in my mind. I will have another look and also check the rest afterwards.

Comment thread bofire/strategies/doe/utils.py Outdated
"""Checks if NChooseK constraints of domain can be formulated as bounds.
def _iter_nchoosek_combined_patterns(
domain: Domain,
) -> "Iterator[Tuple[int, ...]]":
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the return type a string? Why Tuple and not tuple

Comment thread bofire/strategies/doe/utils.py Outdated

all_keys = domain.inputs.get_keys()

def _constraint_patterns(constraint):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

type hint missing

Comment thread bofire/strategies/doe/utils.py Outdated
else:
yield {idx: True for idx in ind}

def _merge_two(patterns_a, patterns_b):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

type hint missing

Comment thread bofire/strategies/doe/utils.py Outdated
list_b = list(patterns_b)

# Identify shared feature indices between the two sides.
keys_a = set().union(*(pa.keys() for pa in list_a)) if list_a else set()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That looks strange. Either i don't get what this does or it a very confusing way of creating a set comprehension.

Comment thread bofire/strategies/doe/utils.py Outdated

def _build_nchoosek_combined_patterns(
domain: Domain,
) -> List[Tuple[int, ...]]:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lower case

Comment thread bofire/strategies/doe/utils.py Outdated
yield {idx: True for idx in ind}

def _merge_two(patterns_a, patterns_b):
"""Yield merged dicts from two pattern iterables, filtering conflicts.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is a lot of zoologic description. but i cannot immediately derive what the purpose of this function is. There is not even a description of what a patterna actually is. What is a pattern?

Comment thread bofire/strategies/doe/utils.py Outdated
merged.update(pb)
yield merged
else:
# No shared features — full cross-product, no conflicts possible.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

full product sounds exhaustive. is this what happened before the change without shared nchoosek?

Copy link
Copy Markdown
Contributor

@bertiqwerty bertiqwerty left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Dominik. Just a few minor points.

Comment thread bofire/strategies/doe/utils.py Outdated

all_keys = domain.inputs.get_keys()

def _constraint_patterns(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd move _constraint_pattern and _merge_two out of _iter_nchoosek_combined_patterns and directly into the module. I find the function _iter_nchoosek_combined_patterns really long and confusing to read. It looks like _merge_two is not even currying anything.

if not nchoosek_constraints:
return []

all_keys = domain.inputs.get_keys()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move all_keys into _constraint_patterns, since you only use it there.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure why you didn't do this. maybe you had a good reason that I overlooked.

Comment thread bofire/strategies/doe/utils.py Outdated
"""Determines the box bounds for the decision variables.

When multiple NChooseK constraints share features, their patterns are
combined via Cartesian product and filtered for consistency so that
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment above says

When multiple constraints share
features, patterns are merged incrementally (pairwise) rather than via
a single giant Cartesian product, pruning inconsistent combinations
early.

which sounds as if it is contradicting this comment.

Comment thread bofire/strategies/doe/utils.py Outdated
return result.x


if __name__ == "__main__":
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this a test? make proper test out of it? is it just you playing aroung? then delete it?

Comment thread bofire/strategies/doe/utils.py Outdated
be >= 0 (so that "inactive" variables can be pinned to 0) and the upper
bound must be > 0. The feature sets of different NChooseKConstraints must
be pairwise disjoint.
def _iter_nchoosek_combined_patterns(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since this function returns a list, call it _get_nchoosek... instead of _iter_....

Comment thread bofire/strategies/doe/utils.py Outdated

"""
# Identify shared feature indices between the two sides.
shared = set(patterns_of_constraint_a[0].keys()).intersection(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it intentional that this crashes in case patterns_... is empty? can this ever happen?

@dlinzner-bcs
Copy link
Copy Markdown
Contributor Author

@bertiqwerty schau noch mal plz!

Copy link
Copy Markdown
Contributor

@bertiqwerty bertiqwerty left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Dominik. Please check my last comment. And merge as you see fit.

if not nchoosek_constraints:
return []

all_keys = domain.inputs.get_keys()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure why you didn't do this. maybe you had a good reason that I overlooked.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants