diff --git a/include/aidge/graph/Node.hpp b/include/aidge/graph/Node.hpp index 546c3c9d64e5989e255cac52f1f4f26947aa4a2e..6dbd474cc4f13effd844e4ec69f7a4a5e127b735 100644 --- a/include/aidge/graph/Node.hpp +++ b/include/aidge/graph/Node.hpp @@ -42,7 +42,7 @@ class GraphView; /** * @brief Object carrying the topological information of the computational graph. * A Node contains : - * - mName : Optional, the name of the Node. If present, it should be unique + * - mAttrs : the attributes of the Node. If one of them is a name, it should be unique among all other Node name * - mViews: a set of pointers to GraphView instances including this Node instance * - mOperator: a pointer to the Operator associated to the node * - mParents: a vector of parent nodes, which are its inputs @@ -82,8 +82,8 @@ public: /** * @brief Construct a new Node object associated with the inputted Operator. - * @param op The Operator of the Node, it determines its number of connections. - * @param attrs Attributes for the Node. + * @param std::shared_ptr<Operator> op: The Operator of the Node, it determines its number of connections. + * @param std::shared_ptr<DynamicAttributes> attrs: Attributes for the Node. */ Node(std::shared_ptr<Operator> op, std::shared_ptr<DynamicAttributes> attrs); // Node(std::shared_ptr<Operator> op, const DynamicAttributes& attrs); @@ -101,18 +101,34 @@ public: return lhs.shared_from_this() == rhs.shared_from_this(); } + /** + * @brief Add a function before the operator's Forward + * @param std::function<bool()> func: The function to add + */ void addBeforeForward(std::function<bool()> func) { mForward.push_front(func); } + /** + * @brief Add a function after the operator's Forward + * @param std::function<bool()> func: The function to add + */ void addAfterForward(std::function<bool()> func) { mForward.push_back(func); } + /** + * @brief Add a function before the operator's Backward + * @param std::function<bool()> func: The function to add + */ void addBeforeBackward(std::function<bool()> func) { mBackward.push_front(func); } + /** + * @brief Add a function after the operator's Backward + * @param std::function<bool()> func: The function to add + */ void addAfterBackward(std::function<bool()> func) { mBackward.push_back(func); } @@ -124,9 +140,9 @@ public: /** * @brief Functional operator for user-friendly connection interface using an ordered set of Connectors. - * @param ctors Ordered Connectors linking their associated Node to the input of the current Node with the same index. + * @param std::vector<Connector> ctors: Ordered Connectors linking their associated Node to the input of the current Node with the same index. * @warning length of ctors must be lower than the number of input of the Node - * @return Connector + * @return Connector: the new connector of the Node */ Connector operator()(const std::vector<Connector> &ctors); @@ -134,20 +150,26 @@ public: /////////////////////////////////////////////////////// // INNER /////////////////////////////////////////////////////// - + /** + * @brief Returns the attributes of the Node. + * @return std::shared_ptr<DynamicAttributes>: The mAttrs of the Node + */ inline std::shared_ptr<DynamicAttributes> attributes() const { return mAttrs; } + /** - * @brief Name of the Node. - * @return std::string + * @brief Returns the name of the Node. + * @todo there is no error handling, what if node has no name? + * @return std::string: The Name of the Node */ inline std::string name() const noexcept { return mAttrs->getAttr<std::string>("name"); } /** * @brief Set the Node's Name. * @warning Undefined behaviour when several Nodes have the same name, use createUniqueName to avoid complications. - * @param name New name for the node. + * @see createUniqueName + * @param std::string name: New name for the node. */ void setName(const std::string &name); @@ -157,14 +179,14 @@ public: * @details if the inputted name is not yet used, it will be used as is * if it is used, the returned name will be "name_X" * name being the inputted name and X the smaller integer allowing name uniqueness - * @param name Base name to make unique. - * @return A unique name in all the GraphView which contains this one. + * @param std::string name: Base name to make unique. + * @return std::string A name not yet used in any of the GraphView which contains this node. */ std::string createUniqueName(std::string name); /** * @brief Type of the Node's operator. - * @return std::string + * @return std::string the type of the Node's operator */ inline std::string type() const { return mOperator->type(); } @@ -184,7 +206,7 @@ public: /** * @brief Get the Operator object of the Node. - * @return std::shared_ptr<Operator> + * @return std::shared_ptr<Operator> the Operator of the Node */ inline std::shared_ptr<Operator> getOperator() const { return (*mOperator)(mAttrs); } // inline std::shared_ptr<Operator> getOperator() const { return mOperator; } @@ -195,32 +217,31 @@ public: /** * @brief Whether or not every input of the Node is linked to a Parent. - * If true then the Node is ready to be executed. - * @return bool + * @return bool: True if every input of the Node is linked to a Parent, false otherwise. */ bool valid() const; /** - * @brief List the pairs <Parent, ID of the data intput> of the Node's inputs. + * @brief Returns the input parents of the Node. * @details When an input is not linked to any Parent, the pair is <nullptr, gk_IODefaultIndex>. * Data inputs exclude inputs expecting parameters (weights or bias). - * @return std::vector<std::pair<std::shared_ptr<Node>, IOIndex_t>> + * @return std::vector<std::pair<std::shared_ptr<Node>, IOIndex_t>> : List of the pairs <Parent, output ID of the Parent> of the Node's inputs. */ std::vector<std::pair<NodePtr, IOIndex_t>> dataInputs() const; /** - * @brief List the pairs <Parent, ID of the input> of the Node's inputs. + * @brief Returns the inputs of the Node. * @details When an input is not linked to any Parent, the pair is <nullptr, gk_IODefaultIndex>. - * as opposed to dataInputs, inputs includes parent nodes containing parameters (e.g. weights or biases) - * @return std::vector<std::pair<std::shared_ptr<Node>, IOIndex_t>> + * As opposed to dataInputs(), inputs() includes parent nodes containing parameters (e.g. weights or biases) + * @return std::vector<std::pair<std::shared_ptr<Node>, IOIndex_t>> : List of the pairs <Parent, output ID of the Parent> of the Node's inputs. */ std::vector<std::pair<NodePtr, IOIndex_t>> inputs() const; /** * @brief Accessor of <parent_node, parent_node_output> linked to the inID-th input input of this node. * If the input is not linked to any Parent, the pair is <nullptr, gk_IODefaultIndex>. - * @param inID : the ID of the input that we want to know the parent of - * @return std::pair<std::shared_ptr<Node>, IOIndex_t> + * @param IOIndex_t inID : the ID of the input that we want to know the parent of + * @return std::pair<std::shared_ptr<Node>, IOIndex_t>: The pair <Parent, output ID of the Parent> of the Node's inID-th input. */ inline std::pair<NodePtr, IOIndex_t> input(const IOIndex_t inID) const { assert((inID != gk_IODefaultIndex) && (inID < nbInputs()) && "Input index out of bound."); @@ -232,7 +253,8 @@ public: * @brief Get the lowest index in the InputData Parent list equal to the * nullptr (i.e. the ID of the first free data input). * Data inputs exclude inputs expecting parameters (weights or bias). - * @return std::size_t + * if there is no free input, will return gk_IODefaultIndex (max of uint16) + * @return IOIndex_t: the index of the first free (parentless) data input. */ inline IOIndex_t getFirstFreeDataInput() const { IOIndex_t i = 0; @@ -250,30 +272,29 @@ public: * @brief Returns the number of free data inputs of the Node * (i.e. data inputs that are not linked to an other node) * @warning Node cannot run until all of its mandatory inputs are filled - * @return IOIndex_t + * @return IOIndex_t: the number of free (parentless) data inputs */ IOIndex_t getNbFreeDataInputs() const; /** - * @brief Lists children of the Node and the ID of the child's input linked to the current Node. + * @brief Returns the outputs of the Node. * @details The parent vector size matches the number of outputs of the node. * Each sub-vector size will match the number of children connected to the n-th output (i.e. if 3 nodes are connected to the 3rd output parent_vec[3].size() == 3). - * @return std::vector<std::vector<std::pair<std::shared_ptr<Node>, IOIndex_t>>> + * @return std::vector<std::vector<std::pair<std::shared_ptr<Node>, IOIndex_t>>>: Vector of vectors of children of the Node and the ID of the child's input linked to the current Node. */ std::vector<std::vector<std::pair<NodePtr, IOIndex_t>>> outputs() const; /** * @brief Lists Nodes and input ids of children linked to specified output of the Node - * @param outId ID of the output from which we want to know the children - * @return std::vector<std::pair<std::shared_ptr<Node>, IOIndex_t>> + * @param IOIndex_t outId: ID of the output from which we want to know the children + * @return std::vector<std::pair<std::shared_ptr<Node>, IOIndex_t>> vector of children of the Node's outId's output and the ID of the child's input linked to the current Node. */ - std::vector<std::pair<NodePtr, IOIndex_t>> - output(IOIndex_t outId) const; + std::vector<std::pair<NodePtr, IOIndex_t>> output(IOIndex_t outId) const; /** * @brief Number of inputs, including both data and learnable parameters. * @details ex: [data, data, weight, bias] => 4 - * @return IOIndex_t + * @return IOIndex_t : The number of inputs of the Node's Operator */ inline IOIndex_t nbInputs() const noexcept { return getOperator()->nbInputs(); } @@ -281,7 +302,8 @@ public: * @brief Returns the category of a specific input (Data or Param, optional or not). * Data inputs exclude inputs expecting parameters (weights or bias). * @details ex: with [datatype1, datatype2, weight, bias], inputCategory(1) returns datatype2 - * @return InputCategory + * @param IOIndex_t idx: The index of the input for which we determine the category. + * @return InputCategory: the category of the specified input */ inline InputCategory inputCategory(IOIndex_t idx) const { return getOperator()->inputCategory(idx); @@ -290,8 +312,8 @@ public: /** * @brief Returns whether the given node parent index is a back edge * A back edge is an edge from a Node to one of its ancestor. - * @param idx Index of the Node's connection we want to test - * @return true if the operator defines it as a back edge + * @param IOIndex_t idx!: Index of the Node's connection we want to test + * @return bool: True if the operator defines it as a back edge, False otherwise */ inline bool parentIsBackEdge(IOIndex_t idx) const { return getOperator()->isBackEdge(idx); @@ -300,16 +322,22 @@ public: /** * @brief Number of inputs linked to a Parent's output. * @warning Unconnected Inputs will throw errors when compiling graph. - * @return IOIndex_t + * @return IOIndex_t: The number of inputs that have a parent. */ IOIndex_t nbValidInputs() const; /** * @brief Getter for the number of Output Tensors of the Node. - * @return IOIndex_t + * @return IOIndex_t, the number of outputs of the Node's Operator */ inline IOIndex_t nbOutputs() const noexcept { return getOperator()->nbOutputs(); } + + /** + * @brief Number of outputs linked to a Child's input. + * @details an output having several children still counts only as one + * @return IOIndex_t: The number of outputs that have at least a child. + */ IOIndex_t nbValidOutputs() const; /////////////////////////////////////////////////////// @@ -318,7 +346,7 @@ public: /** * @brief Set of pointers to each GraphView containing this Node - * @return std::set<GraphView> + * @return std::set<GraphView>: the set of GraphView containing this Node */ inline std::set<std::shared_ptr<GraphView>> views() const noexcept { std::set<std::shared_ptr<GraphView>> res; @@ -333,7 +361,7 @@ public: /** * @brief Add a GraphView pointer to the list of GraphView containing * the current Node. This feature allows transparent GraphViews. - * @param graphPtr Pointer to GraphView to add to the list. + * @param std::shared_ptr<GraphView> graphPtr Weak pointer to GraphView to add to the list. */ inline void addView(const std::shared_ptr<GraphView> &graphPtr) { mViews.insert(std::weak_ptr<GraphView>(graphPtr)); @@ -343,7 +371,7 @@ public: * @brief Remove the reference of this Node to the GraphView passed as argument. * @warning This function does not remove the reference of the GraphView to the Node. * As such, this function is used in other function and should be not used as is by an user - * @param graphPtr Pointer to GraphView to remove from the list. + * @param std::shared_ptr<GraphView> graphPtr: Pointer to GraphView to remove from the list. */ inline void removeView(const std::shared_ptr<GraphView> &graphPtr) { mViews.erase(graphPtr); @@ -351,26 +379,24 @@ public: /** * @brief Link another Node to an output of the current Node. - * @param otherNode Pointer to the other Node. - * @param outId ID of the current Node output to connect to the other Node. + * @param NodePtr otherNode: Pointer to the other Node. + * @param IOIndex_t outId: ID of the current Node output to connect to the other Node. * Default to 0. - * @param otherInId ID of the other Node input to connect to the current Node. - * Default to the first available data input. + * @param IOIndex_t otherInId: ID of the other Node input to connect to the current Node. + * Default out of range input (leaving default value will cause an exception. */ void addChild(NodePtr otherNode, const IOIndex_t outId = IOIndex_t(0), IOIndex_t otherInId = gk_IODefaultIndex); /** - * @brief Link a Node from a specific GraphView to the current Node. - * @param otherView Pointer to the GraphView whose content should be + * @brief Link an input Node from a specific GraphView to the current Node. + * @param std::shared_ptr<GraphView> otherView: Pointer to the GraphView whose content should be * linked to the current Node. - * @param outId ID of the output Tensor to connect to the other Node. + * @param IOIndex_t outId: ID of the output Tensor to connect to the other Node. * Default to 0. - * @param otherInId Pair of pointer to Node and Tensor ID for specifying the - * connection. If the GraphView whose content is linked has only one input - * Node, then it defaults to the first available data input Tensor of this - * Node. + * @param std::pair<NodePtr, IOIndex_t> otherInId: Pair of pointer to Node and Tensor ID for specifying the connection. + * Default pair is (nullptr, gk_IODefaultIndex), leading to an exception. */ void addChild(std::shared_ptr<GraphView> otherView, const IOIndex_t outId = IOIndex_t(0), @@ -381,14 +407,14 @@ public: * @brief Get the list of parent Nodes. * Each input can only be linked to one Node. * If an input has no linked node, the associated parent is nullptr - * @return std::vector<std::shared_ptr<Node>> + * @return std::vector<std::shared_ptr<Node>> The vector of parent Nodes */ std::vector<NodePtr> getParents() const; /** * @brief Get the pointer to parent of the specified input index. This pointer is nullptr if no parent is linked. - * @param inId Input index. - * @return std::shared_ptr<Node>& + * @param IOIndex_t inId: Input index. + * @return std::shared_ptr<Node>& the pointer to the parent of the specified input */ inline NodePtr &getParent(const IOIndex_t inId) { assert(inId != gk_IODefaultIndex); @@ -398,23 +424,23 @@ public: /** * @brief Unlink the parent Node at the specified input index and return its pointer. * Return a nullptr is no parent was linked. - * @param inId Input index. - * @return std::shared_ptr<Node> + * @param IOIndex_t inId: Input index. + * @return std::shared_ptr<Node> the pointer to the parent of the specified input */ NodePtr popParent(const IOIndex_t inId); /** * @brief unlinks the parent from the Node and replaces it with nullptr (for coherence with remaining parents) - * @param inId Input index of the parent to be removed - * @return std::bool true if parent has been removed. + * @param IOIndex_t inId: Input index of the parent to be removed + * @return std::bool True if parent has been removed, false otherwise. */ bool removeParent(const IOIndex_t inId); /** - * @brief Get the set of pointers to children Nodes linked to the current Node.object. - * @details The returned set does not include any nullptr as an output maybe linked to - * an undefined number of Nodes. It does not change the computation of its associated Operator. - * @return std::set<std::shared_ptr<Node>>> + * @brief Get the set of pointers to children Nodes linked to the current Node. + * @details The returned set does not include any nullptr as an output. + * Node that are several times child of this one (several of its input come from this Node) appear only once + * @return std::set<std::shared_ptr<Node>>> the set of children of the Node */ std::set<NodePtr> getChildren() const; @@ -423,29 +449,31 @@ public: * @details The parent vector size matches the number of outputs of the node. * Each sub-vector size will match the number of children connected to the n-th output * (i.e. if 3 nodes are connected to the 3rd output parent_vec[2].size() == 3). - * @returns std::vector<std::vector<std::shared_ptr<Node>>> + * @returns std::vector<std::vector<std::shared_ptr<Node>>> The vector (main vector,size=number of outputs) + * of vectors (one per output of the Node) of children */ std::vector<std::vector<NodePtr>> getOrderedChildren() const; /** * @brief Get the list of children Nodes linked to the output at specified index. - * @param outId Output index. - * @return std::vector<std::shared_ptr<Node>> + * @param IOIndex_t outId: Output index. + * @return std::vector<std::shared_ptr<Node>> Vector of children of the outId-th output */ std::vector<NodePtr> getChildren(const IOIndex_t outId) const; /** * @brief Remove registered child from children list of specified output if possible. * If so, also remove current Node from child's parent. - * @param std::shared_ptr<Node> Node to remove. - * @param outId Output index. Default 0. - * @return true Child found and removed for given output index. - * @return false Child not found at given index. Nothing removed. + * @param NodePtr nodePtr: to remove. + * @param IOIndex_t outId: Output index. Default 0. + * @return bool True if Child found and removed for given output index, false otherwise */ bool removeChild(const NodePtr nodePtr, const IOIndex_t outId = 0); /** - * @brief Remove every link of surrounding nodes to it and conversely + * @brief Remove every link between this Node and its parents and children + * @param bool includeLearnableParam: If False, connections with data and OptionalData are kept, + * if true, they are removed as well */ void resetConnections(bool includeLearnableParam = false); @@ -455,26 +483,26 @@ public: /** * @brief Clone the current Node. The Operator attribute of the new Node is not copied but shared with the current Node. The new node has no connection. - * @return NodePtr + * @return NodePtr Pointer to the cloned Node */ NodePtr cloneSharedOperators() const; /** * @brief Clone the Node. Every attribute is copied, even Operator pointer except for Producers for which it is shared. The new Node has no connection. - * @return NodePtr + * @return NodePtr Pointer to the cloned Node */ NodePtr cloneSharedProducers() const; /** * @brief Clone the Node and its Operator. The new Node has no connection. - * @return NodePtr + * @return NodePtr Pointer to the cloned Node */ NodePtr clone() const; /** * @brief Callback function to clone the Node keeping the same Operator object instance. The new Node has no connection. - * @param node Node to clone. - * @return NodePtr + * @param node Node: to clone. + * @return NodePtr Pointer to the cloned Node */ static NodePtr cloneSharedOperators(NodePtr node) { return node->cloneSharedOperators(); @@ -482,8 +510,8 @@ public: /** * @brief Callback function to clone the Node. Every attribute is copied, even Operator pointer except for Producers for which it is shared. The new Node has no connection. - * @param node Node to clone. - * @return NodePtr + * @param node Node: to clone. + * @return NodePtr Pointer to the cloned Node */ static NodePtr cloneSharedProducers(NodePtr node) { return node->cloneSharedProducers(); @@ -491,8 +519,8 @@ public: /** * @brief Callback function to clone the Node and its Operator. The new Node has no connection. - * @param node Node to clone. - * @return NodePtr + * @param node Node: to clone. + * @return NodePtr Pointer to the cloned Node */ static NodePtr clone(NodePtr node) { return node->clone(); @@ -501,12 +529,13 @@ public: /** * @brief Get the set of pointers to connected node at a distance of a delta. - * @details positive value are toward children, negative toward parents (ex: -2 would give grandparents) - * Return a nullptr is nothing found. - * @param int delta Input delta. - * @param std::set<Aidge::NodePtr> nodeSee is used in the recursion to avoid looping on the same nodes, + * @details positive value are toward children, negative toward parents + * (ex: -2 would give grandparents, +1 gives direct children) + * @param int delta: Input delta. + * @param std::set<Aidge::NodePtr> nodeSee: is used in the recursion to avoid looping on the same nodes, * should be empty when calling the method * @return std::set<Aidge::NodePtr> set of nodes within expected distance from the original node + * If no node is found at searched level, returns nullptr */ std::set<NodePtr> getNodeDelta(int delta,std::set<Aidge::NodePtr> nodeSee); @@ -546,8 +575,8 @@ private: /** * @brief Updates mIdOutParents by giving the value newNodeOutID to the inID-th member of the list - * @param IOIndex_t inID input of the Node that is being changed - * @param IOIndex_t newNodeOutID updated value, corresponds to the new output of the parent Node + * @param IOIndex_t inID: input of the Node that is being changed + * @param IOIndex_t newNodeOutID: updated value, corresponds to the new output of the parent Node */ void setInputId(const IOIndex_t inID, const IOIndex_t newNodeOutID); @@ -557,19 +586,18 @@ private: /** * @brief Add the given Node as a child for the current Node. - * @param otherNode - * @param outId - * @param otherInId + * @param NodePtr otherNode: The new child of the current Node + * @param IOIndex_t outId: The output of the current Node that will welcome the new child + * @param IOIndex_t otherInId: the input of the new child that welcomes the current Node */ void addChildOp(NodePtr otherNode, const IOIndex_t outId, const IOIndex_t otherInId); /** * @brief Add the given GraphView's input Node as a child for the current Node - * @param otherGraph - * @param outId - * @param otherInId pointer the GraphView's input Node and its input index. Defaults to the - * only input Node if the GraphView has got one. + * @param std::shared_ptr<GraphView> otherGraph: Graphview that will take the current Node as parent + * @param IOIndex_t outId: The output of the current Node that will be linked to the graphView + * @param std::pair<NodePtr, IOIndex_t> otherInId) otherInId: pointer the GraphView's input Node and its input index. */ void addChildView(std::shared_ptr<GraphView> otherGraph, const IOIndex_t outId, @@ -577,8 +605,8 @@ private: /** * @brief Add a Node to the list of parents. - * @param otherNode Node to add to parents list. - * @param inId index for adding the parent. + * @param NodePtr otherNode: Node to add to parents list. + * @param IOIndex_t inId: input index of the Node where the parent will be added. */ void addParent(const NodePtr otherNode, const IOIndex_t inId);