-
Notifications
You must be signed in to change notification settings - Fork 88
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
[Feat] Add Local Search for Solution Improvement #140
Conversation
Great job! 🚀 Another detail I cannot review above: tt seems that the installation fails for Python=3.8. This should be because |
Changes
|
Changes
@fedebotu @leonlan |
Hi @hyeok9855, I don't have time to go over the code in full detail, but I had a quick glance at the PyVRP part. It looks good to me with a small comment on the constant. |
@@ -27,7 +29,10 @@ class AntSystem: | |||
pheromone: Initial pheromone matrix. Defaults to `torch.ones_like(log_heuristic)`. | |||
require_logprobs: Whether to require the log probability of actions. Defaults to False. | |||
use_local_search: Whether to use local_search provided by the env. Default to False. | |||
local_search_params: Arguments to be passed to the local_search function. | |||
use_nls: Whether to use neural-guided local search provided by the env. Default to False. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the difference between use_nls
and use_local_search
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nls
indicates the local search with neural-guided perturbation, proposed in DeepACO. See here.
@@ -166,6 +167,19 @@ def check_solution_validity(td: TensorDict, actions: torch.Tensor): | |||
== actions.data.sort(1)[0] | |||
).all(), "Invalid tour" | |||
|
|||
def generate_data(self, batch_size) -> TensorDict: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So you mean I can just remove the method?
return heuristic_dist | ||
|
||
@staticmethod | ||
def select_start_node_fn( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Minor, for now]
By default, now we look for this function inside of the environment as done here, which is a bit more modular. But since we have to transfer this functions yet and is not a hard task, no need to do it now
return actions, reward # type: ignore | ||
td_cpu = td.detach().cpu() # Convert to CPU in advance to minimize the overhead from device transfer | ||
td_cpu["distances"] = get_distance_matrix(td_cpu["locs"]) | ||
# TODO: avoid or generalize this, e.g., pre-compute for local search in each env |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we can keep this as todo
, but it should be generalized. I think this could be a common classmethod
for routing environments
|
||
return heatmaps_logits | ||
heatmap += 1e-10 if heatmap.dtype != torch.float16 else 3e-8 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, I see a huge trick here!
These values should ideally be constants at the top, e.g:
LOWEST_POSVAL_FP32 = 1e-10
LOWEST_POSVAL_FP16 = 3e-8
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The lowest positive value for FP32 is not 1e-10 actually. It is much smaller than that, but 1e-10 is used in DeepACO.
tests/test_envs.py
Outdated
@@ -79,6 +79,10 @@ def test_routing(env_cls, batch_size=2, size=20): | |||
def test_mtvrp(variant, batch_size=2, size=20): | |||
env = MTVRPEnv(generator_params=dict(num_loc=size, variant_preset=variant)) | |||
reward, td, actions = rollout(env, env.reset(batch_size=[batch_size]), random_policy) | |||
try: | |||
env.local_search(td, actions) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you add the local search to this environment?
We should have this available for all 16 variants with the code @leonlan made
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, I only added LS to TSP and CVRP.
I don't remember if I added the lines. This might be due to the unexpected behavior of git merge.
I will just remove it for now!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should have this available for all 16 variants with the code @leonlan made
Where can I find the code? Is that about local search?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's about full solutions, but my guess is that it will work with any variant with minor modifications! Here is the code~
I think we should skip the local search testing with Like: @pytest.mark.skipif(sys.version_info < (3, 9))
[...] Maybe in the near future we could just remove testing Python 3.8 since it's a really old version anyways |
Unresolved comments will be dealt with in the following PR. |
Description
Add local search operators as a post-processing to improve a given solution.
Here, we implement 2-opt for TSP and LocalSearch operator provided by PyVRP for CVRP.
For other problems (e.g., PDP or scheduling), we couldn't find such a plug-and-play local search operator, and we're looking for contributions to local search for other problems!
Note that I also made some refactorings regarding type hinting.
Motivation and Context
Local search is an essential component for an enhanced CO solver. Many research projects in the NCO field utilize local search operators, such as our recent work GFACS, which trains NN using the solution refined by local search in an off-policy manner.
Types of changes
What types of changes does your code introduce? Remove all that do not apply:
Checklist
Go over all the following points, and put an
x
in all the boxes that apply.If you are unsure about any of these, don't hesitate to ask. We are here to help!