Source code for conex.nn.structure.synapsis

from .container import Container
from typing import Union, Dict, List, Tuple
from pymonntorch import Network, Behavior, NetworkObject, SynapseGroup, NeuronGroup
import torch
import copy
from conex.nn.utils.replication import behaviors_to_list, build_behavior_dict
from .io_layer import InputLayer, OutputLayer


[docs]class Synapsis(Container): """Synapsis structure This structure connects two ports, and connects all the possible synapsegroups between them. Args: net (Network): The network of the layer. src (NetworkObject): The source of synpsis object. dst (NetworkObject): The destination of synpsis object. input_port (str): The input label of source port. output_port (str): The output label of destination port. synapsis_behavior (dict): the behavior of synapses created. synapstic_tag (str): The tag of the synapses created. behavior (dictionary): A dictionary of keys and behaviors attached to the container. tag (str): tag of the container divided by ",". device (device): device of the structure. defaults to the netowrk device. """ def __init__( self, net: Network, src: NetworkObject = None, dst: NetworkObject = None, input_port: str = None, output_port: str = None, synapsis_behavior: Dict[int, Behavior] = None, synaptic_tag: str = None, behavior: Dict[int, Behavior] = None, tag: str = None, device: Union[torch.device, int, str] = None, ): super().__init__( net=net, sub_structures=[], behavior=behavior, tag=tag, device=device ) self.input_port = input_port self.output_port = output_port self.synapsis_behavior = synapsis_behavior self.synaptic_tag = synaptic_tag self.src = src self.dst = dst self.synapses = self.sub_structures if self.src is not None and self.dst is not None: self.create_synapses()
[docs] def connect_src(self, src: NetworkObject): if self.src is None and src is not None: self.src = src if self.dst is not None: self.create_synapses()
[docs] def connect_dst(self, dst: NetworkObject): if self.dst is None and dst is not None: self.dst = dst if self.src is not None: self.create_synapses()
@staticmethod def _port2ng( label: Union[str, None], object: NetworkObject, src_port: bool = True ) -> List[Tuple[NeuronGroup, Dict[int, Behavior]]]: if isinstance(object, NeuronGroup): return [[object, {}]] elif isinstance(object, (Container, InputLayer, OutputLayer)): result = [] search_port = object.output_ports if src_port else object.input_ports for port in search_port.get(label, [[], []])[1]: p_behavior = port.behavior if port.behavior is not None else {} port_result = Synapsis._port2ng(port.label, port.object, src_port) for i, x in enumerate(port_result): x[1] = { **copy.deepcopy(p_behavior), **copy.deepcopy(x[1] if x[1] is not None else {}), } result.extend(port_result) return result else: return []
[docs] def create_synapses(self): if not self.synapses: src_ng = Synapsis._port2ng(self.input_port, self.src) dst_ng = Synapsis._port2ng(self.output_port, self.dst, src_port=False) for x in src_ng: for y in dst_ng: self.synapses.append( SynapseGroup( net=self.network, src=x[0], dst=y[0], behavior={**x[1], **y[1], **self.synapsis_behavior}, tag=self.synaptic_tag, ) )
def __repr__(self) -> str: result = ( self.__class__.__name__ + str(self.tags) + "(Synapses:" + str([value.tags[0] for value in self.synapses]) + "){" ) for k in sorted(list(self.behavior.keys())): result += str(k) + ":" + str(self.behavior[k]) return result + "}"
[docs] def required_helper(self) -> List[NetworkObject]: """A function to find required structures. This function should return a list of structures required in time of creating the instance. """ return []
[docs] def save_helper(self, all_structures: List[NetworkObject]) -> dict: """A function to help saving the structures. into a dictionary. If tag and behavior parameters are not provided, they be handled by higher saving paradigm. Network should be excluded. Args: all_structures (list): a list containing the output of required_helper which are structures required to make same instance. """ result_parameters = { "input_port": self.input_port, "output_port": self.output_port, "src": all_structures.index(self.src) if self.src in all_structures else None, "dst": all_structures.index(self.dst) if self.dst in all_structures else None, "synapsis_behavior": behaviors_to_list(self.synapsis_behavior), "synaptic_tag": self.synaptic_tag, } return result_parameters
[docs] @staticmethod def build_helper( parameter_dic: dict, built_structures: Dict[int, NetworkObject] ) -> dict: """Function to edit the parameter dictionary into acceptable argument of the class constructor. Note: behavior can also be edited in this function as thay later will be constructed. """ parameter_dic["src"] = ( built_structures[parameter_dic["src"]] if parameter_dic["src"] is not None else None ) parameter_dic["dst"] = ( built_structures[parameter_dic["dst"]] if parameter_dic["dst"] is not None else None ) parameter_dic["synapsis_behavior"] = build_behavior_dict( built_structures["synapsis_behavior"] ) return parameter_dic