// Copyright (c) 2024 PaddlePaddle Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #pragma once #include #include "paddle/ap/include/adt/adt.h" #include "paddle/ap/include/graph/node.h" #include "paddle/ap/include/graph/tags.h" namespace ap::graph { template class NodeArena : public std::enable_shared_from_this> { public: NodeArena() {} NodeArena(const NodeArena&) = delete; NodeArena(NodeArena&&) = delete; adt::Result At(const tNodeId& node_id) const { if (node_id.value() >= nodes_.size()) { return adt::errors::IndexError{"node_id out of ranges."}; } return nodes_.at(node_id.value()); } template const T& New(const ConstructorT& Constructor) { tNodeId node_id{nodes_.size()}; const auto& node = Constructor(Node{node_id, this->shared_from_this()}); return EmplaceBackNode(node); } template adt::Result TryNew(const ConstructorT& Constructor) { tNodeId node_id{nodes_.size()}; ADT_LET_CONST_REF(node, Constructor(Node{node_id, this->shared_from_this()})); return EmplaceBackNode(node); } adt::Result> DownstreamNodes4SrcNodeId( const tNodeId& src_id) { if (src_id.value() >= src_node_id2downstream_nodes_.size()) { return adt::errors::IndexError{"src node_id out of ranges."}; } return src_node_id2downstream_nodes_.at(src_id.value()); } adt::Result> UpstreamNodes4DstNodeId( const tNodeId& dst_id) { if (dst_id.value() >= dst_node_id2upstream_nodes_.size()) { return adt::errors::IndexError{"dst node_id out of ranges."}; } return dst_node_id2upstream_nodes_.at(dst_id.value()); } adt::Result Connect( const Node& src_node, const ValidListTag& src_downstream_type, const Node& dst_node, const ValidListTag& dst_unstream_type) { const auto& src_id = src_node.node_id(); if (src_node.node_arena().lock() != this->shared_from_this()) { return adt::errors::RuntimeError{ "Connection between nodes from different arena is not supported. "}; } if (src_id.value() >= this->src_node_id2downstream_nodes_.size()) { return adt::errors::IndexError{ "src_id.value() is out of range " "this->src_node_id2downstream_nodes_."}; } const auto& dst_id = dst_node.node_id(); if (dst_node.node_arena().lock() != this->shared_from_this()) { return adt::errors::RuntimeError{ "Connection between nodes from different arena is not supported. "}; } if (dst_id.value() >= this->dst_node_id2upstream_nodes_.size()) { return adt::errors::IndexError{ "src_id.value() is out of range this->dst_node_id2upstream_nodes_."}; } ADT_LET_CONST_REF( downstream_nodes_data, GetNodeListData(&src_node_id2downstream_nodes_[src_id.value()], src_downstream_type)); downstream_nodes_data->emplace_back( Node{dst_id, this->shared_from_this()}); ADT_LET_CONST_REF( upstream_nodes_data, GetNodeListData(&dst_node_id2upstream_nodes_[dst_id.value()], dst_unstream_type)); upstream_nodes_data->emplace_back( Node{src_id, this->shared_from_this()}); return adt::Ok{}; } const std::vector& nodes() const { return nodes_; } private: adt::Result>> GetNodeListData( NodeList* node_list, const ValidListTag& type) { using RetDataT = adt::List>; using RetT = adt::Result; if (node_list->template Has>()) { return type.Match( [&](const IndexedTag&) -> RetT { IndexedTag data{RetDataT{}}; *node_list = data; return data.data; }, [&](const UnindexedTag&) -> RetT { UnindexedTag data{RetDataT{}}; *node_list = data; return data.data; }); } const auto& pattern_match = ::common::Overloaded{ [&](const IndexedTag& l, const IndexedTag&) -> RetT { return l.data; }, [&](const UnindexedTag& l, const UnindexedTag&) -> RetT { return l.data; }, [&](const auto&, const auto&) -> RetT { return adt::errors::TypeError{"ap graph node list type mismatch."}; }}; return std::visit(pattern_match, node_list->variant(), type.variant()); } const T& EmplaceBackNode(const T& node) { nodes_.emplace_back(node); src_node_id2downstream_nodes_.resize(nodes_.size()); dst_node_id2upstream_nodes_.resize(nodes_.size()); return nodes_.at(nodes_.size() - 1); } std::vector nodes_; std::vector> src_node_id2downstream_nodes_; std::vector> dst_node_id2upstream_nodes_; }; template adt::Result Node::Get() const { ADT_LET_CONST_REF(arena, adt::WeakPtrLock(this->node_arena())); return arena->At(this->node_id()); } template adt::Result> Node::DownstreamNodes() const { ADT_LET_CONST_REF(arena, adt::WeakPtrLock(this->node_arena())); return arena->DownstreamNodes4SrcNodeId(this->node_id()); } template adt::Result> Node::UpstreamNodes() const { ADT_LET_CONST_REF(arena, adt::WeakPtrLock(this->node_arena())); return arena->UpstreamNodes4DstNodeId(this->node_id()); } template adt::Result Node::ConnectTo( const Node& dst_node, const ValidListTag& src_downstream_type, const ValidListTag& dst_unstream_type) const { ADT_LET_CONST_REF(arena, adt::WeakPtrLock(this->node_arena())); return arena->Connect( *this, src_downstream_type, dst_node, dst_unstream_type); } } // namespace ap::graph