Shortcuts

Source code for rl4co.models.nn.env_embeddings.init

import torch
import torch.nn as nn


[docs]def env_init_embedding(env_name: str, config: dict) -> nn.Module: """Get environment initial embedding. The init embedding is used to initialize the general embedding of the problem nodes without any solution information. Consists of a linear layer that projects the node features to the embedding space. Args: env: Environment or its name. config: A dictionary of configuration options for the environment. """ embedding_registry = { "tsp": TSPInitEmbedding, "atsp": TSPInitEmbedding, "cvrp": VRPInitEmbedding, "sdvrp": VRPInitEmbedding, "pctsp": PCTSPInitEmbedding, "spctsp": PCTSPInitEmbedding, "op": OPInitEmbedding, "dpp": DPPInitEmbedding, "mdpp": MDPPInitEmbedding, "pdp": PDPInitEmbedding, "mtsp": MTSPInitEmbedding, } if env_name not in embedding_registry: raise ValueError( f"Unknown environment name '{env_name}'. Available init embeddings: {embedding_registry.keys()}" ) return embedding_registry[env_name](**config)
[docs]class TSPInitEmbedding(nn.Module): """Initial embedding for the Traveling Salesman Problems (TSP). Embed the following node features to the embedding space: - locs: x, y coordinates of the cities """ def __init__(self, embedding_dim, linear_bias=True): super(TSPInitEmbedding, self).__init__() node_dim = 2 # x, y self.init_embed = nn.Linear(node_dim, embedding_dim, linear_bias)
[docs] def forward(self, td): out = self.init_embed(td["locs"]) return out
[docs]class VRPInitEmbedding(nn.Module): """Initial embedding for the Vehicle Routing Problems (VRP). Embed the following node features to the embedding space: - locs: x, y coordinates of the nodes (depot and customers separately) - demand: demand of the customers """ def __init__(self, embedding_dim, linear_bias=True): super(VRPInitEmbedding, self).__init__() node_dim = 3 # x, y, demand self.init_embed = nn.Linear(node_dim, embedding_dim, linear_bias) self.init_embed_depot = nn.Linear( 2, embedding_dim, linear_bias ) # depot embedding
[docs] def forward(self, td): # [batch, 1, 2]-> [batch, 1, embedding_dim] depot, cities = td["locs"][:, :1, :], td["locs"][:, 1:, :] depot_embedding = self.init_embed_depot(depot) # [batch, n_city, 2, batch, n_city, 1] -> [batch, n_city, embedding_dim] node_embeddings = self.init_embed( torch.cat((cities, td["demand"][..., None]), -1) ) # [batch, n_city+1, embedding_dim] out = torch.cat((depot_embedding, node_embeddings), -2) return out
[docs]class PCTSPInitEmbedding(nn.Module): """Initial embedding for the Prize Collecting Traveling Salesman Problems (PCTSP). Embed the following node features to the embedding space: - locs: x, y coordinates of the nodes (depot and customers separately) - expected_prize: expected prize for visiting the customers. In PCTSP, this is the actual prize. In SPCTSP, this is the expected prize. - penalty: penalty for not visiting the customers """ def __init__(self, embedding_dim, linear_bias=True): super(PCTSPInitEmbedding, self).__init__() node_dim = 4 # x, y, prize, penalty self.init_embed = nn.Linear(node_dim, embedding_dim, linear_bias) self.init_embed_depot = nn.Linear(2, embedding_dim, linear_bias)
[docs] def forward(self, td): depot, cities = td["locs"][:, :1, :], td["locs"][:, 1:, :] depot_embedding = self.init_embed_depot(depot) node_embeddings = self.init_embed( torch.cat( ( cities, td["expected_prize"][..., None], td["penalty"][..., 1:, None], ), -1, ) ) # batch, n_city+1, embedding_dim out = torch.cat((depot_embedding, node_embeddings), -2) return out
[docs]class OPInitEmbedding(nn.Module): """Initial embedding for the Orienteering Problems (OP). Embed the following node features to the embedding space: - locs: x, y coordinates of the nodes (depot and customers separately) - prize: prize for visiting the customers """ def __init__(self, embedding_dim, linear_bias=True): super(OPInitEmbedding, self).__init__() node_dim = 3 # x, y, prize self.init_embed = nn.Linear(node_dim, embedding_dim, linear_bias) self.init_embed_depot = nn.Linear( 2, embedding_dim, linear_bias ) # depot embedding
[docs] def forward(self, td): depot, cities = td["locs"][:, :1, :], td["locs"][:, 1:, :] depot_embedding = self.init_embed_depot(depot) node_embeddings = self.init_embed( torch.cat( ( cities, td["prize"][..., 1:, None], # exclude depot ), -1, ) ) out = torch.cat((depot_embedding, node_embeddings), -2) return out
[docs]class DPPInitEmbedding(nn.Module): """Initial embedding for the Decap Placement Problem (DPP), EDA (electronic design automation). Embed the following node features to the embedding space: - locs: x, y coordinates of the nodes (cells) - probe: index of the (single) probe cell. We embed the euclidean distance from the probe to all cells. """ def __init__(self, embedding_dim, linear_bias=True): super(DPPInitEmbedding, self).__init__() node_dim = 2 # x, y self.init_embed = nn.Linear(node_dim, embedding_dim // 2, linear_bias) # locs self.init_embed_probe = nn.Linear(1, embedding_dim // 2, linear_bias) # probe
[docs] def forward(self, td): node_embeddings = self.init_embed(td["locs"]) probe_embedding = self.init_embed_probe( self._distance_probe(td["locs"], td["probe"]) ) return torch.cat([node_embeddings, probe_embedding], -1)
def _distance_probe(self, locs, probe): # Euclidean distance from probe to all locations probe_loc = torch.gather(locs, 1, probe.unsqueeze(-1).expand(-1, -1, 2)) return torch.norm(locs - probe_loc, dim=-1).unsqueeze(-1)
[docs]class MDPPInitEmbedding(nn.Module): """Initial embedding for the Multi-port Placement Problem (MDPP), EDA (electronic design automation). Embed the following node features to the embedding space: - locs: x, y coordinates of the nodes (cells) - probe: indexes of the probe cells (multiple). We embed the euclidean distance of each cell to the closest probe. """ def __init__(self, embedding_dim, linear_bias=True): super(MDPPInitEmbedding, self).__init__() node_dim = 2 # x, y self.init_embed = nn.Linear(node_dim, embedding_dim, linear_bias) # locs self.init_embed_probe_distance = nn.Linear( 1, embedding_dim, linear_bias ) # probe_distance self.project_out = nn.Linear(embedding_dim * 2, embedding_dim, linear_bias)
[docs] def forward(self, td): probes = td["probe"] locs = td["locs"] node_embeddings = self.init_embed(locs) # Get the shortest distance from any probe dist = torch.cdist(locs, locs, p=2) dist[~probes] = float("inf") min_dist, _ = torch.min(dist, dim=1) min_probe_dist_embedding = self.init_embed_probe_distance(min_dist[..., None]) return self.project_out( torch.cat([node_embeddings, min_probe_dist_embedding], -1) )
[docs]class PDPInitEmbedding(nn.Module): """Initial embedding for the Pickup and Delivery Problem (PDP). Embed the following node features to the embedding space: - locs: x, y coordinates of the nodes (depot, pickups and deliveries separately) Note that pickups and deliveries are interleaved in the input. """ def __init__(self, embedding_dim, linear_bias=True): super(PDPInitEmbedding, self).__init__() node_dim = 2 # x, y self.init_embed_depot = nn.Linear(2, embedding_dim, linear_bias) self.init_embed_pick = nn.Linear(node_dim * 2, embedding_dim, linear_bias) self.init_embed_delivery = nn.Linear(node_dim, embedding_dim, linear_bias)
[docs] def forward(self, td): depot, locs = td["locs"][..., 0:1, :], td["locs"][..., 1:, :] num_locs = locs.size(-2) pick_feats = torch.cat( [locs[:, : num_locs // 2, :], locs[:, num_locs // 2 :, :]], -1 ) # [batch_size, graph_size//2, 4] delivery_feats = locs[:, num_locs // 2 :, :] # [batch_size, graph_size//2, 2] depot_embeddings = self.init_embed_depot(depot) pick_embeddings = self.init_embed_pick(pick_feats) delivery_embeddings = self.init_embed_delivery(delivery_feats) # concatenate on graph size dimension return torch.cat([depot_embeddings, pick_embeddings, delivery_embeddings], -2)
[docs]class MTSPInitEmbedding(nn.Module): """Initial embedding for the Multiple Traveling Salesman Problem (mTSP). Embed the following node features to the embedding space: - locs: x, y coordinates of the nodes (depot, cities) """ def __init__(self, embedding_dim, linear_bias=True): """NOTE: new made by Fede. May need to be checked""" super(MTSPInitEmbedding, self).__init__() node_dim = 2 # x, y self.init_embed = nn.Linear(node_dim, embedding_dim, linear_bias) self.init_embed_depot = nn.Linear( 2, embedding_dim, linear_bias ) # depot embedding
[docs] def forward(self, td): depot_embedding = self.init_embed_depot(td["locs"][..., 0:1, :]) node_embedding = self.init_embed(td["locs"][..., 1:, :]) return torch.cat([depot_embedding, node_embedding], -2)

© Copyright Federico Berto, Chuanbo Hua, Junyoung Park. Revision f4bc96ca.

Built with Sphinx using a theme provided by Read the Docs.