From 1d4b893bb8fdf0c4de2b33b0f0021bf839887875 Mon Sep 17 00:00:00 2001 From: Elton Cardoso do Nascimento <43186596+EltonCN@users.noreply.github.com> Date: Tue, 26 Nov 2024 14:00:55 -0300 Subject: [PATCH] Core code documentation --- src/cst_python/core/entities/coalition.py | 7 + src/cst_python/core/entities/code_rack.py | 55 ++++++++ src/cst_python/core/entities/memory.py | 88 ++++++++++++ src/cst_python/core/entities/memory_buffer.py | 5 + .../core/entities/memory_container.py | 12 ++ src/cst_python/core/entities/memory_object.py | 34 +++++ src/cst_python/core/entities/mind.py | 127 ++++++++++++++++++ src/cst_python/core/entities/raw_memory.py | 93 +++++++++++++ 8 files changed, 421 insertions(+) diff --git a/src/cst_python/core/entities/coalition.py b/src/cst_python/core/entities/coalition.py index f6b9733..47022af 100644 --- a/src/cst_python/core/entities/coalition.py +++ b/src/cst_python/core/entities/coalition.py @@ -1,4 +1,11 @@ class Coalition: + ''' + A Coalition is a group of Codelets which are gathered in order to perform a + task by summing up their abilities or to form a specific context. + + In CST, two codelets belong to the same coalition when they share information + - pragmatically, when they write in and read from the same memory object. + ''' def __init__(self) -> None: raise NotImplementedError() \ No newline at end of file diff --git a/src/cst_python/core/entities/code_rack.py b/src/cst_python/core/entities/code_rack.py index 93de444..e609e44 100644 --- a/src/cst_python/core/entities/code_rack.py +++ b/src/cst_python/core/entities/code_rack.py @@ -7,12 +7,22 @@ class CodeRack: + ''' + Following Hofstadter and Mitchell + "The copycat project: A model of mental fluidity and analogy-making". Pool of + all alive codelets in the system. The whole arena in the Baars-Franklin + metaphor. + ''' + def __init__(self) -> None: self._all_codelets :List[Codelet] = [] #@alias.alias("getAllCodelets", "get_all_codelets") @property def all_codelets(self) -> List[Codelet]: + ''' + List of all alive codelets in the system + ''' return self._all_codelets #@alias.alias("setAllCodelets", "set_all_codelets") @@ -22,10 +32,26 @@ def all_codelets(self, value:List[Codelet]) -> None: #@alias.alias("add_codelet") def add_codelet(self, codelet:Codelet) -> None: + ''' + Adds a new Codelet to the Coderack + + Args: + codelet (Codelet): codelet to be added. + ''' self._all_codelets.append(codelet) #@alias.alias("insertCodelet") def insert_codelet(self, codelet:Codelet) -> Codelet: + ''' + Creates a codelet and adds it to this coderack. + + Args: + codelet (Codelet): codelet to be created. + + Returns: + Codelet: the own codelet inserted, if it is needed to concatenate to + further methods calls. + ''' self.add_codelet(codelet) return codelet @@ -34,6 +60,20 @@ def insert_codelet(self, codelet:Codelet) -> Codelet: def create_codelet(self, activation:float, broadcast:List[Memory], inputs:List[Memory], outputs:List[Memory], codelet:Codelet) -> Codelet: + ''' + Creates a codelet and adds it to this coderack. + + Args: + activation (float): codelet's activation. + broadcast (List[Memory]): list of memory objects which were broadcast lately (treated as + input memories). + inputs (List[Memory]): list of input memories. + outputs (List[Memory]): list o output memories. + codelet (Codelet): codelet to be created. + + Returns: + Codelet: the codelet created. + ''' try: codelet.activation = activation @@ -50,18 +90,33 @@ def create_codelet(self, activation:float, broadcast:List[Memory], #@alias.alias("destroyCodelet") def destroy_codelet(self, codelet:Codelet) -> None: + ''' + Removes a codelet from coderack. + + Args: + codelet (Codelet): the codelet to be destroyed. + ''' codelet.stop() self._all_codelets.remove(codelet) #@alias.alias("shutDown", "shut_down") def shutdow(self): + ''' + Destroys all codelets. Stops CodeRack's thread. + ''' self.stop() self._all_codelets.clear() def start(self) -> None: + ''' + Starts all codelets in coderack. + ''' for codelet in self._all_codelets: codelet.start() def stop(self) -> None: + ''' + Stops all codelets within CodeRack. + ''' for codelet in self._all_codelets: codelet.stop() diff --git a/src/cst_python/core/entities/memory.py b/src/cst_python/core/entities/memory.py index 15da8a9..f12b58c 100644 --- a/src/cst_python/core/entities/memory.py +++ b/src/cst_python/core/entities/memory.py @@ -5,65 +5,153 @@ from.memory_observer import MemoryObserver class Memory(abc.ABC): + ''' + This class represents the interface for all kinds of memories that exist in + CST. In order to be recognized as a Memory, an entity must implement this + interface. Currently, there are to kinds of Memory: MemoryObject and + MemoryContainer. However, other forms of Memory might come up as CST + develops. + ''' #@alias.alias("getI", "get_I") @abc.abstractmethod def get_info(self) -> Any: + ''' + Gets the info inside this memory. + + Returns: + Any: the info in memory. + ''' ... #@alias.alias("setT", "set_I") @abc.abstractmethod def set_info(self, value:Any) -> int: + ''' + Sets the info inside this Memory. + + Args: + value (Any): the updated info to set in memory. + + Returns: + int: index of the memory inside the container or -1 if not a + container. + ''' ... #@alias.alias("getEvaluation") @abc.abstractmethod def get_evaluation(self) -> float: + ''' + Gets the evaluation of this memory. + + Returns: + float: the evaluation of this memory. + ''' ... #@alias.alias("getName") @abc.abstractmethod def get_name(self) -> str: + ''' + Gets the type of this memory. + + Returns: + str: the type of the memory. + ''' ... #@alias.alias("setName") @abc.abstractmethod def set_name(self, name:str) -> None: + ''' + Sets the name of this memory. + + Args: + name (str): the value to be set as name. + ''' ... #@alias.alias("setEvaluation") @abc.abstractmethod def set_evaluation(self, evaluation:float) -> None: + ''' + Sets the evaluation of this memory. + + Args: + evaluation (float): the value to be set as evaluation. + ''' ... #@alias.alias("getTimestamp") @abc.abstractmethod def get_timestamp(self) -> int: + ''' + Gets the timestamp of this Memory. + + Returns: + int: the timestamp of this Memory. + ''' ... #@alias.alias("addMemoryObserver") @abc.abstractmethod def add_memory_observer(self, observer:MemoryObserver) -> None: + ''' + Add a memory observer to its list. + + Args: + observer (MemoryObserver): MemoryObserver to be added. + ''' ... #@alias.alias("removeMemoryObserver") @abc.abstractmethod def remove_memory_observer(self, observer:MemoryObserver) -> None: + ''' + Remove a memory observer from its list. + + Args: + observer (MemoryObserver): MemoryObserver to be removed. + ''' ... #@alias.alias("getId") @abc.abstractmethod def get_id(self) -> int: + ''' + Gets the id of the Memory. + + Returns: + int: the id of the Memory. + ''' ... #@alias.alias("setId") @abc.abstractmethod def set_id(self, memory_id:int) -> None: + ''' + Sets the id of the Memory. + + Args: + memory_id (int): the id of the Memory to set. + ''' ... def compare_name(self, other_name:str) -> bool: + ''' + Compares tha name of this memory with another. + + Comparation is case insensitive. + + Args: + other_name (str): name of the other memory. + + Returns: + bool: True if is the same name. + ''' if self._name is None: return False diff --git a/src/cst_python/core/entities/memory_buffer.py b/src/cst_python/core/entities/memory_buffer.py index d60b418..1ed1687 100644 --- a/src/cst_python/core/entities/memory_buffer.py +++ b/src/cst_python/core/entities/memory_buffer.py @@ -1,3 +1,8 @@ class MemoryBuffer: + ''' + MemoryBuffer is a generic holder for memory objects. It may be used to + produce sensory buffers, action buffers or other very short term memory + structures. + ''' def __init__(self) -> None: raise NotImplementedError() \ No newline at end of file diff --git a/src/cst_python/core/entities/memory_container.py b/src/cst_python/core/entities/memory_container.py index fe7bbc5..235fd76 100644 --- a/src/cst_python/core/entities/memory_container.py +++ b/src/cst_python/core/entities/memory_container.py @@ -1,6 +1,18 @@ from .memory import Memory class MemoryContainer(Memory): + ''' + This class represents a Memory Container. The Memory Container is responsible + for implementing an important element in the Dynamic Subsumption mechanism + used in CST. All the Memory Objects in a Container are of the same type, and + hold the same parameters. The only differences among them are that they were + generated by a different codelet, and they might have different evaluations. + An evaluation is an inner parameter from any Memory Object, which holds a + value (usually a real value between 0 and 1) that measures a relative + importance given by the codelet, and which is used by the Evaluation codelet + within the Container to decide which from all input Memory Objects will be + sent to the output. + ''' def __init__(self) -> None: super().__init__() diff --git a/src/cst_python/core/entities/memory_object.py b/src/cst_python/core/entities/memory_object.py index 48a8160..cf12eab 100644 --- a/src/cst_python/core/entities/memory_object.py +++ b/src/cst_python/core/entities/memory_object.py @@ -8,8 +8,31 @@ from .memory_observer import MemoryObserver class MemoryObject(Memory): + ''' + A Memory Object is a generic information holder, acting as a sign or an + internal representation, which is responsible to store any auxiliary or + perennial information necessary for the cognitive architecture to perform its + behavior. Codelets and Memory Objects are intrinsically coupled to each + other, in the sense that Memory Objects hold the information necessary for + the Codelets to run, and are also the placeholders of any new information + generated by the codelet. The main property being hold by a Memory Object is + its Information (I). This information can be simply a number, or hold complex + structures like lists, trees, graphs or whole networks. In our computational + implementation, the information I is a generic Java Object, which can be used + to represent virtually anything. A Memory Object also has two extra kinds of + meta-information: a time stamp (T), which tags the Memory Object with a + marker indicating its last update, and an evaluation (E), which has many + different uses within CST. This evaluation is simply a number, which can be + used, e.g. as an appraisal factor in an emotional module, or simply as a + discriminator to differentiate among two or more Memory Objects of the same + type. These meta-information can be simply ignored by simpler codelets, or be + useful while implementing more sophisticated cognitive models. + ''' def __init__(self) -> None: + ''' + Creates a MemoryObject. + ''' self._id = 0 self._timestamp = 0 self._evaluation = 0.0 @@ -44,7 +67,15 @@ def _notify_memory_observers(self) -> None: for observer in self._memory_observers: observer.notify_codelet() + def update_info(self, info:Any) -> None: + ''' + Args: + info (Any): the info in memory object to set. + + .. deprecated:: + Use set_info() instead + ''' self.set_info(info) def get_timestamp(self) -> int: @@ -52,6 +83,9 @@ def get_timestamp(self) -> int: @property def timestamp(self) -> int: + ''' + Date when the data was "created" in milliseconds. + ''' return self._timestamp #@alias.alias("setTimestamp") diff --git a/src/cst_python/core/entities/mind.py b/src/cst_python/core/entities/mind.py index 4900171..6b2d3e2 100644 --- a/src/cst_python/core/entities/mind.py +++ b/src/cst_python/core/entities/mind.py @@ -11,7 +11,14 @@ from .memory_container import MemoryContainer class Mind: + ''' + This class represents the Mind of the agent, wrapping all the CST's core + entities. + ''' def __init__(self) -> None: + ''' + Creates the Mind. + ''' self._code_rack = CodeRack() self._raw_memory = RawMemory() self._codelet_groups : Dict[str, List[Codelet]] = dict() @@ -39,22 +46,57 @@ def memory_groups(self) -> Dict[str, List[Memory]]: #@alias.alias("createCodeletGroup") def create_codelet_group(self, group_name:str) -> None: + ''' + Creates a Codelet Group. + + Args: + group_name (str): The Group name. + ''' self._codelet_groups[group_name] = [] #@alias.alias("createMemoryGroup") def create_memory_group(self, group_name:str) -> None: + ''' + Creates a Memory Group. + + Args: + group_name (str): The Group name. + ''' self._memory_groups[group_name] = [] #@alias.alias("getCodeletGroupsNumber") def get_codelet_groups_number(self) -> int: + ''' + Returns the number of registered codelet groups + + Returns: + int: the number of registered groups + ''' return len(self._memory_groups) #@alias.alias("getMemoryGroupsNumber") def get_memory_groups_number(self) -> int: + ''' + Returns the number of registered memory groups + + Returns: + int: the number of registered groups + ''' + return len(self._memory_groups) #@alias.alias("createMemoryContainer") def create_memory_container(self, name:str) -> Optional[MemoryContainer]: + ''' + Creates a Memory Container inside the Mind of a given type. + + Args: + name (str): the type of the Memory Container to be created inside the + Mind. + + Returns: + Optional[MemoryContainer]: the Memory Container created. + ''' mc = None if self._raw is not None: @@ -66,6 +108,19 @@ def create_memory_container(self, name:str) -> Optional[MemoryContainer]: def create_rest_memory_object(self, name:str, port:int, hostname:Optional[str]=None) -> Optional[RESTMemoryObject]: + ''' + Creates a new MemoryObject and adds it to the Raw Memory, using provided + info and type. + + Args: + name (str): memory object name. + port (int): port of the REST server + hostname (Optional[str], optional): hostname of the REST server. If is None, + uses 'localhost'. Defaults to None. + + Returns: + Optional[RESTMemoryObject]: created MemoryObject + ''' if hostname is None: hostname = "localhost" @@ -81,6 +136,19 @@ def create_rest_memory_object(self, name:str, def create_rest_memory_container(self, name:str, port:int, hostname:Optional[str]=None) -> Optional[RESTMemoryContainer]: + ''' + Creates a new MemoryObject and adds it to the Raw Memory, using provided + info and type. + + Args: + name (str): memory object name. + port (int): port of the REST server + hostname (Optional[str], optional): hostname of the REST server. If is None, + uses 'localhost'. Defaults to None. + + Returns: + Optional[RESTMemoryContainer]: created MemoryObject + ''' if hostname is None: hostname = "localhost" @@ -94,6 +162,17 @@ def create_rest_memory_container(self, name:str, #@alias.alias("createMemoryObject") def create_memory_object(self, name:str, info:Optional[Any]=None) -> Optional[MemoryObject]: + ''' + Creates a new MemoryObject and adds it to the Raw Memory, using provided + type. + + Args: + name (str): memory object type. + info (Optional[Any], optional): memory object info. Defaults to None. + + Returns: + Optional[MemoryObject]: created MemoryObject. + ''' mo = None if self._raw_memory is not None: @@ -103,6 +182,16 @@ def create_memory_object(self, name:str, info:Optional[Any]=None) -> Optional[Me #@alias.alias("insertCodelet") def insert_codelet(self, co:Codelet, group_name:Optional[str]=None) -> Codelet: + ''' + Inserts the Codelet passed in the Mind's CodeRack. + + Args: + co (Codelet): the Codelet passed + group_name (Optional[str], optional): the Codelet group name. Defaults to None. + + Returns: + Codelet: the Codelet. + ''' if self._code_rack is not None: self._code_rack.add_codelet(co) @@ -112,12 +201,26 @@ def insert_codelet(self, co:Codelet, group_name:Optional[str]=None) -> Codelet: #@alias.alias("registerCodelet") def register_codelet(self, co:Codelet, group_name:str) -> None: + ''' + Register a Codelet within a group. + + Args: + co (Codelet): the Codelet. + group_name (str): the group name. + ''' if group_name in self._codelet_groups: group_list = self._codelet_groups[group_name] group_list.append(co) #@alias.alias("registerMemory") def register_memory(self, memory:Union[Memory,str], group_name:str) -> None: + ''' + Register a Memory within a group + + Args: + memory (Union[Memory,str]): the Memory or the memory name. + group_name (str): the group name + ''' if group_name in self._memory_groups: to_register = [] @@ -131,17 +234,41 @@ def register_memory(self, memory:Union[Memory,str], group_name:str) -> None: #@alias.alias("getCodeletGroupList") def get_codelet_group_list(self, group_name:str) -> List[Codelet]: + ''' + Get a list of all Codelets belonging to a group + + Args: + group_name (str): the group name to which the Codelets belong + + Returns: + List[Codelet]: A list of all codeletGroups belonging to the group indicated by groupName + ''' return self._codelet_groups[group_name] #@alias.alias("getMemoryGroupList") def get_memory_group_list(self, group_name:str) -> List[Memory]: + ''' + Get a list of all Memories belonging to a group + + Args: + group_name (str): the group name to which the Memory belong + + Returns: + List[Memory]: A list of all memoryGroups belonging to the group indicated by groupName + ''' return self._memory_groups[group_name] def start(self) -> None: + ''' + Starts all codeletGroups in coderack. + ''' if self._code_rack is not None: self._code_rack.start() #@alias.alias("shutDown", "shut_down") def shutdown(self) -> None: + ''' + Stops codeletGroups thread. + ''' if self._code_rack is not None: self._code_rack.shutdow() \ No newline at end of file diff --git a/src/cst_python/core/entities/raw_memory.py b/src/cst_python/core/entities/raw_memory.py index c270498..6f7fabf 100644 --- a/src/cst_python/core/entities/raw_memory.py +++ b/src/cst_python/core/entities/raw_memory.py @@ -14,11 +14,17 @@ class RawMemory: _last_id = 0 def __init__(self) -> None: + ''' + Creates a Raw Memory. + ''' self._all_memories : List[Memory] = [] #Should be a set? #@alias.alias("getAllMemoryObjects", "get_all_memory_objects") @property def all_memories(self) -> List[Memory]: + ''' + List of all memories in the system. + ''' return self._all_memories #@alias.alias("setAllMemoryObjects", "set_all_memory_objects") @@ -33,6 +39,15 @@ def all_memories(self, value:List[Memory]) -> None: #@alias.alias("getAllOfType") def get_all_of_type(self, type:str) -> List[Memory]: + ''' + Returns a list of all memories in raw memory of a given type + + Args: + type (str): type of memory + + Returns: + List[Memory]: list of Ms of a given type + ''' list_of_type = [] for m in self._all_memories: @@ -43,29 +58,92 @@ def get_all_of_type(self, type:str) -> List[Memory]: #@alias.alias("printContent") def print_content(self) -> None: + ''' + Print Raw Memory contents. + ''' for m in self._all_memories: print(m) #@alias.alias("addMemoryObject", "add_memory_object", "addMemory") def add_memory(self, m:Memory) -> None: + ''' + Adds a new Memory to the Raw Memory. + + Args: + m (Memory): memory to be added. + ''' self._all_memories.append(m) m.set_id(self._last_id) self._last_id += 1 #@alias.alias("createMemoryContainer") def create_memory_container(self, name:str) -> MemoryContainer: + ''' + Creates a memory container of the type passed. + + Args: + name (str): the type of the memory container passed. + + Raises: + NotImplementedError: method is not implemented. + + Returns: + MemoryContainer: the memory container created. + ''' raise NotImplementedError() #@alias.alias("createRESTMemoryObject") def create_rest_memory_object(self, name:str, port:int, hostname:Optional[str]=None) -> RESTMemoryObject: + ''' + Creates a new RestMemory and adds it to the Raw Memory, using provided + name, hostname and port . + + Args: + name (str): memory object type. + port (int): the port of the REST server + hostname (Optional[str], optional): the hostname of the REST server. If None, + uses 'localhost'. Defaults to None. + + Raises: + NotImplementedError: method is not implemented. + + Returns: + RESTMemoryObject: created MemoryObject. + ''' raise NotImplementedError() #@alias.alias("createRESTMemoryContainer") def create_rest_memory_container(self, name:str, port:int, hostname:Optional[str]=None) -> RESTMemoryContainer: + ''' + Creates a new RestMemory and adds it to the Raw Memory, using provided + name, hostname and port . + + Args: + name (str): memory object type. + port (int): the port of the REST server + hostname (Optional[str], optional): the hostname of the REST server. If None, + uses 'localhost'. Defaults to None. + + Raises: + NotImplementedError: method is not implemented. + + Returns: + RESTMemoryContainer: created MemoryObject. + ''' raise NotImplementedError() #@alias.alias("createMemoryObject") def create_memory_object(self, name:str, info:Optional[Any]=None) -> MemoryObject: + ''' + Creates a new MemoryObject and adds it to the Raw Memory. + + Args: + name (str): memory object type. + info (Optional[Any], optional): memory object info. Defaults to None. + + Returns: + MemoryObject: created MemoryObject. + ''' if info is None: info = "" @@ -80,12 +158,27 @@ def create_memory_object(self, name:str, info:Optional[Any]=None) -> MemoryObjec #@alias.alias("destroyMemoryObject", "destroy_memory_object") def destroy_memory(self, m:Memory): + ''' + Destroys a given memory from raw memory + + Args: + m (Memory): the memory to destroy. + ''' self._all_memories.remove(m) #@alias.alias("size") def __len__(self) -> int: + ''' + Gets the size of the raw memory. + + Returns: + int: size of Raw Memory. + ''' return len(self._all_memories) #@alias.alias("shutDown", "shut_down") def shutdown(self) -> None: + ''' + Removes all memory objects from RawMemory. + ''' self._all_memories = [] \ No newline at end of file