Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

XpyriMentor and Suggestors #296

Merged
merged 31 commits into from
Dec 11, 2024
Merged

XpyriMentor and Suggestors #296

merged 31 commits into from
Dec 11, 2024

Conversation

SRFU-NN
Copy link
Collaborator

@SRFU-NN SRFU-NN commented Dec 4, 2024

XpyriMentor, Suggestor, LHSSuggestor, RandomSuggestor, InitialPointSuggestor, DefaultSuggestor and suggestor_factory implemented.

Small fixes in old PO code:
ProcessOptimizer.Optimizer.update_next() recognizes changes in number of told points
ProcessOptimizer.utils.is_listlike returns true on np.ndarray
ProcessOptimizer.utils.is_2Dlistlike returns true on 2D np.ndarray

Also removes support for Python 3.8, which is now in end-of-life and no longer gets security updates.

@SRFU-NN SRFU-NN changed the title WIP: Expyrementor and Suggestors WIP: XpyriMentor and Suggestors Dec 5, 2024
@SRFU-NN SRFU-NN changed the title WIP: XpyriMentor and Suggestors XpyriMentor and Suggestors Dec 6, 2024
@SRFU-NN SRFU-NN requested a review from CoRiis December 6, 2024 11:06
Copy link
Collaborator

@CoRiis CoRiis left a comment

Choose a reason for hiding this comment

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

I only went through the XpyriMentor code, and I should probably have started with the suggestor.py script instead of going through the files from the top.

@SRFU-NN
Copy link
Collaborator Author

SRFU-NN commented Dec 11, 2024

We could change "name" to "suggestor_name" in suggestor definition dicts.

On the one hand, in means that only suggestor and things starting with suggestor_ is disallowed as inputs in Suggestor.__init__()'s, and it makes for more readable suggestor definitions.

On the other hand, it makes for more typing to make suggestor definitions.

Thoughts? If nobody complains, I'll change it.

Old style:

suggestor_definition = {
    "name": "Sequential",
    "suggestors": [
        {"suggestor_budget": 7, "name": "LHS"},
        {
            "suggestor_budget": 20,
            "name": "Random",
            "suggestors": [
                {"suggestor_usage_ratio": 80, "name": "PO", "acq_func_kwargs": {"xi": 10}},
                {"suggestor_usage_ratio": 20, "name": "PO", "acq_func_kwargs": {"xi": 0.00001}},
            ],
        },
        {"suggestor_budget": float("inf"), "name": "PO", "acq_func_kwargs": {"xi": 0.00001}},
    ]
}

New style:

suggestor_definition = {
    "suggestor_name": "Sequential",
    "suggestors": [
        {"suggestor_budget": 7, "suggestor_name": "LHS"},
        {
            "suggestor_budget": 20,
            "suggestor_name": "Random",
            "suggestors": [
                {"suggestor_usage_ratio": 80, "suggestor_name": "PO", "acq_func_kwargs": {"xi": 10}},
                {"suggestor_usage_ratio": 20, "suggestor_name": "PO", "acq_func_kwargs": {"xi": 0.00001}},
            ],
        },
        {"suggestor_budget": float("inf"), "suggestor_name": "PO", "acq_func_kwargs": {"xi": 0.00001}},
    ]
}

@SRFU-NN SRFU-NN self-assigned this Dec 11, 2024
@SRFU-NN SRFU-NN merged commit 891788f into develop Dec 11, 2024
6 checks passed
@SRFU-NN SRFU-NN deleted the director branch December 11, 2024 13:00
Stratgizer that uses a sequence of suggestors, each with a budget of suggestions to
make.

It uses the suggestors in order, skipping suggestors with a budget of suggestions
Copy link
Collaborator

Choose a reason for hiding this comment

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

"skipping" can be hard to interpret. I get why (starting with n data points it jumps to n+1) but maybe make it another sentence.

" If n data points are supplied, the strategizer will behave as if these points are generated by the suggestors and start from n+1 evaluations in the sequential list of suggestors."

Not great but at least more descriptive.


If the first suggestor is a DefaultSuggestor, it will be replaced with a
LHSSuggestor with the same budget. If any other suggestor is a
DefaultSuggestor, it will be replaced with a POSuggestor.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Example in docstring would be nice

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I would prefer to provide examples in the format the factory accepts. In general, the factory input is designed to be readable and modifiable, while the init() inputs for suggestors are designed to be easy to work with.

Does that make sense? Should we write that down somewhere in the documentation? Should we have more examples in the factory docstring, or in the suggestor docstrings?

* suggestors [`list[tuple[int, Suggestor]]`]:
A list of tuples where the first element is the number of suggestions the
suggestor can make and the second element is the suggestor. A negative number
of suggestions is interpreted as infinity, aand can only be used as the last
Copy link
Collaborator

Choose a reason for hiding this comment

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

... used as budget for the last suggestor.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done, much better phrasing.

rng=suggestor.rng,
n_objectives=suggestor.n_objectives,
))
if budget <= 0:
Copy link
Collaborator

Choose a reason for hiding this comment

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

I would probably say sharp smaller than

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Makes sense, I've written negative all over. A budget of 0 will still work, it will just mean the suggestor is never used.

)
if math.isinf(suggestors[n][0]):
if n < len(suggestors) - 1:
raise ValueError("Infinite budget must be the last budget")
Copy link
Collaborator

Choose a reason for hiding this comment

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

Change Error msg: Only the last suggestor can have infinite budget

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done, much better phrasing.

if number_to_skip + number_left_to_find >= budget:
# If we need more points than the suggestor can give us, we take all the
# points the suggestor can give us and continue with the next suggestor.
number_from_this_suggestor = budget - number_to_skip
Copy link
Collaborator

Choose a reason for hiding this comment

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

Something seems a bit off here. I will take a deeper look later.

What if you have 3 suggestors, 5 points budget each and load in 7 data points.
How would that work. I guess it is the tracking of what has already happened and what budget each suggestor has that is a bit confusing.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'll move the testing whether we are done to a separate if clause at the end, and moved updating suggestions and number_left_to_find out of the main if loop. That makes the flow slightly clearer.

If we ask for 4 points, we will start out with number_left_to_skip = 7 and number_left_to_find =4

For the first suggestor, we have to skip it completely (number_left_to_skip >= budget; 7>=5)

We then have number_left_to_skip = 2 and number_left_to_find =4

For the second suggestor, we will use it, but need more points than the suggestor can provide (number_left_to_skip + number_left_to_find >= budget; 2 + 4 > 5). We use that suggestor to find 3 points (number_from_this_suggestor = budget - number_left_to_skip = 5 - 2 = 3).

We then have number_left_to_skip = 0 and number_left_to_find =1

We use the final suggestor to find one point (else).

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.

3 participants