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

Optional callback after repair and on accept #71

Closed
leonlan opened this issue May 23, 2022 · 6 comments
Closed

Optional callback after repair and on accept #71

leonlan opened this issue May 23, 2022 · 6 comments

Comments

@leonlan
Copy link
Collaborator

leonlan commented May 23, 2022

It would be nice to have a callback function to be called at moments other than when a new best solution is found. As fair as I know, the most frequent alternatives are:

  • after_repair: After the repair step, before acceptance. Rationale: "explore with destroy/repair, exploit with local search"
  • on_accept: When accepted, before best. Rationale: "good enough" to be spend additional resources improving the solution

Ideally, the callback functions should all be different. For example, a callback function to be called after the repair step should only explore small neighborhoods since it will be called frequently, whereas we may want to spend more resources when we accepted the solution.

I also know of one paper that performs local search between the destroy and repair step, but it is quite niche and I haven't read an ALNS paper so far describing the same method.

@N-Wouda
Copy link
Owner

N-Wouda commented May 23, 2022

I am not opposed to such callbacks, but: what's stopping you from writing your own AcceptanceCriterion that does both?

Minimal example:

from alns.accept import HillClimbing


class MyAcceptanceCriterion(HillClimbing):
    def __call__(..., cand, ...):
        <do after_repair around candidate>

        if accept := super().__call__(..., cand, ...):  # modified candidate was accepted
            <do on_accept around candidate>

        return accept

In both cases you can, as far as I can tell, freely modify the passed-in candidate argument without having to worry about copying anything.

@leonlan
Copy link
Collaborator Author

leonlan commented May 23, 2022

Nothing is stopping me personally since I've already hacked through the entire ALNS class for my research :-). That's indeed a good suggestion which covers the proposed implementations.

@N-Wouda
Copy link
Owner

N-Wouda commented May 23, 2022

I've already hacked through the entire ALNS class for my research :-)

shame

😄

@N-Wouda
Copy link
Owner

N-Wouda commented May 23, 2022

But that's OK. Clearly there's some demand for callbacks and such then - I believed in #30 that there was not. I will leave this issue open to revisit at some point in the near future!

@leonlan
Copy link
Collaborator Author

leonlan commented Jun 27, 2022

After some experimenting, I no longer think it's beneficial to have more callbacks in ALNS.

As you said before, the acceptance criterion can be easily modified to apply local search after repair/on accept. This same principle can be also applied directly to destroy/repair operators, e.g., by decorating the operators.

I think it's good to keep the ALNS class as simple as possible. Rather than adding more callbacks to the ALNS class, the current implementation provides enough flexibility for the user to define their own callbacks through the destroy/repair and acceptance criteria interfaces. These use cases can be demonstrated in the documentation/cookbook (#88).

Feel free to close the issue if you agree/have no other remarks.

@N-Wouda
Copy link
Owner

N-Wouda commented Jun 27, 2022

This same principle can be also applied directly to destroy/repair operators, e.g., by decorating the operators.

I agree. The paper you referenced having a destroy-local search-repair cycle is completely equivalent to (destroy + local search)-repair, or destroy-(local search + repair). I think we are better off not adding all sorts of callbacks for these things into the library, but instead push those ideas off into user code.

These use cases can be demonstrated in the documentation/cookbook (#88).

Sounds like a good idea to me. We can definitely document some common 'callback use cases' there, and the recommended way to do that in the library.


I am open to adding new callbacks when something is hard to do currently. But I cannot think of anything right now. So I will wait until there's a concrete use case :-).

@N-Wouda N-Wouda closed this as completed Jun 27, 2022
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

No branches or pull requests

2 participants