[docs]classAECEnv():""" Environment base class. """DEFAULT_SEED=2925def__init__(self,instance_generator_object:InstanceBuilder,obs_builder_object:ObservationBuilder,agent_selector_object:BaseSelector,reward_evaluator:RewardFn,seed:int=None,device:Optional[str]=None,batch_size:Optional[torch.Size]=None,):""" Constructor Args: instance_generator_object(InstanceBuilder): Generator instance. obs_builder_object(ObservationBuilder): Observations instance. agent_selector_object(BaseSelector): Agent selector instance reward_evaluator(RewardFn): Reward evaluator instance. seed(int): Random number generator seed. Defaults to None. device(str, optional): Type of processing. It can be "cpu" or "gpu". Defaults to None. batch_size(torch.Size): Batch size. Defaults to None. """ifseedisNone:self._set_seed(self.DEFAULT_SEED)else:self._set_seed(seed)self.agent_selector=agent_selector_objectself.inst_generator=instance_generator_objectself.inst_generator._set_seed(self.seed)self.obs_builder=obs_builder_objectself.obs_builder.set_env(self)self.reward_evaluator=reward_evaluatorself.reward_evaluator.set_env(self)ifdevice==None:self.device=instance_generator_object.deviceelse:self.device=deviceifbatch_sizeisNone:self.batch_size=self.inst_generator.batch_sizeelse:batch_size=[batch_size]ifisinstance(batch_size,int)elsebatch_sizeself.batch_size=torch.Size(batch_size)instance_generator_object.batch_size=torch.Size(batch_size)self.num_nodes=self.inst_generator.max_num_nodesself.num_agents=self.inst_generator.max_num_agentsself.nodes_static_feat_dim=self.obs_builder.get_nodes_static_feat_dim()self.nodes_dynamic_feat_dim=self.obs_builder.get_nodes_dynamic_feat_dim()self.agent_feat_dim=self.obs_builder.get_agent_feat_dim()self.agents_feat_dim=self.obs_builder.get_other_agents_feat_dim()self.global_feat_dim=self.obs_builder.get_global_feat_dim()def_set_seed(self,seed:Optional[int]):""" Set the random seed used by the environment. Args: seed(int, optional): Seed to be set. Returns: None. """self.seed=seedrng=torch.manual_seed(self.seed)self.rng=rngdefobserve(self,is_reset=False)->TensorDict:""" Compute the environment. Args: is_reset(bool): If the environment is on reset. Defauts to False. Returns TensorDict: Current agent observaions and masks dictionary. """raiseNotImplementedError()defsample_action(self,td:TensorDict)->TensorDict:""" Compute a random action from avaliable actions to current agent. Args: td(TensorDict): Environment instance tensor. Returns: TensorDict: Tensor environment instance with updated action. """raiseNotImplementedError()defreset(self)->TensorDict:""" Reset the environment to a starting state and return infos dict. Args: n/a. Returns: TensorDict: Environment information. """raiseNotImplementedError()defstep(self,td:TensorDict)->TensorDict:""" Perform an environment step for active agent. Args: td(TensorDict): Environment tensor instance. Returns: TensorDict: Updated tensor environment instance. """raiseNotImplementedError()def_get_current_instance_data(self)->dict[str,dict[str,torch.Tensor]|str]:""" Return a lightweight, plotting-friendly view of the current instance. Expected to include at least: - 'data': a dict with tensors such as 'coords' (shape [B, N, 2] or [N, 2]), 'is_depot' or 'depot_idx' if available, and any other fields listed in self.instance_data_keys. - 'name': a human-friendly instance name. This structure is consumed by plotting utilities like plot_instance_coords. """instance={"name":getattr(self,"instance_name",f"{self.env_name.upper()}-Instance"),"data":{}}keys=getattr(self,"instance_data_keys",None)# If instance_data_keys is not defined, fall back to common fields.ifkeysisNone:keys=[]forkin("coords","is_depot","depot_idx"):ifkinself.td_state:keys.append(k)forkinkeys:ifkinself.td_state:instance["data"][k]=self.td_state[k]returninstance