114cf0368Sopenharmony_ci/* 214cf0368Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 314cf0368Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 414cf0368Sopenharmony_ci * you may not use this file except in compliance with the License. 514cf0368Sopenharmony_ci * You may obtain a copy of the License at 614cf0368Sopenharmony_ci * 714cf0368Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 814cf0368Sopenharmony_ci * 914cf0368Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1014cf0368Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1114cf0368Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1214cf0368Sopenharmony_ci * See the License for the specific language governing permissions and 1314cf0368Sopenharmony_ci * limitations under the License. 1414cf0368Sopenharmony_ci */ 1514cf0368Sopenharmony_ci#define LOG_TAG "Graph" 1614cf0368Sopenharmony_ci#include "graph.h" 1714cf0368Sopenharmony_ci#include "logger.h" 1814cf0368Sopenharmony_cinamespace OHOS { 1914cf0368Sopenharmony_cinamespace UDMF { 2014cf0368Sopenharmony_ciGraph::Graph(uint32_t vertexNum, const std::map<std::string, uint32_t> &typeIdIndex) 2114cf0368Sopenharmony_ci : vertexNum_(vertexNum), typeIdIndex_(typeIdIndex) 2214cf0368Sopenharmony_ci{ 2314cf0368Sopenharmony_ci for (uint32_t node = 0; node < vertexNum_; node++) { 2414cf0368Sopenharmony_ci adjList_.push_back({node, nullptr}); 2514cf0368Sopenharmony_ci } 2614cf0368Sopenharmony_ci visited_.resize(vertexNum_); 2714cf0368Sopenharmony_ci fill(visited_.begin(), visited_.end(), 0); 2814cf0368Sopenharmony_ci} 2914cf0368Sopenharmony_ci 3014cf0368Sopenharmony_ciGraph::~Graph() 3114cf0368Sopenharmony_ci{ 3214cf0368Sopenharmony_ci for (const auto &vertexNode : adjList_) { 3314cf0368Sopenharmony_ci EdgeNode *edge = vertexNode.firstEdge; 3414cf0368Sopenharmony_ci while (edge != nullptr) { 3514cf0368Sopenharmony_ci EdgeNode *nextEdge = edge->next; 3614cf0368Sopenharmony_ci delete edge; 3714cf0368Sopenharmony_ci edge = nextEdge; 3814cf0368Sopenharmony_ci } 3914cf0368Sopenharmony_ci } 4014cf0368Sopenharmony_ci} 4114cf0368Sopenharmony_ci 4214cf0368Sopenharmony_civoid Graph::AddEdge(const std::string &startNode, const std::string &endNode) 4314cf0368Sopenharmony_ci{ 4414cf0368Sopenharmony_ci int32_t start = GetIndex(startNode); 4514cf0368Sopenharmony_ci int32_t end = GetIndex(endNode); 4614cf0368Sopenharmony_ci if (start < 0 || end < 0) { 4714cf0368Sopenharmony_ci LOG_WARN(UDMF_CLIENT, "abnormal edge, startNode:%{public}s, endNode:%{public}s. ", 4814cf0368Sopenharmony_ci startNode.c_str(), endNode.c_str()); 4914cf0368Sopenharmony_ci return; 5014cf0368Sopenharmony_ci } 5114cf0368Sopenharmony_ci AddEdge(start, end); 5214cf0368Sopenharmony_ci} 5314cf0368Sopenharmony_ci 5414cf0368Sopenharmony_civoid Graph::AddEdge(uint32_t start, uint32_t end) 5514cf0368Sopenharmony_ci{ 5614cf0368Sopenharmony_ci EdgeNode *edge = new EdgeNode; // add new edge 5714cf0368Sopenharmony_ci edge->adjIndex = end; 5814cf0368Sopenharmony_ci edge->next = adjList_[start].firstEdge; 5914cf0368Sopenharmony_ci adjList_[start].firstEdge = edge; 6014cf0368Sopenharmony_ci} 6114cf0368Sopenharmony_ci 6214cf0368Sopenharmony_cibool Graph::Dfs(uint32_t startNode, Action action, bool isInit) 6314cf0368Sopenharmony_ci{ 6414cf0368Sopenharmony_ci if (isInit) { 6514cf0368Sopenharmony_ci visited_.resize(vertexNum_); 6614cf0368Sopenharmony_ci fill(visited_.begin(), visited_.end(), 0); 6714cf0368Sopenharmony_ci } 6814cf0368Sopenharmony_ci std::stack<uint32_t> nodes; 6914cf0368Sopenharmony_ci EdgeNode *edge = nullptr; 7014cf0368Sopenharmony_ci visited_[startNode] = 1; 7114cf0368Sopenharmony_ci nodes.push(startNode); 7214cf0368Sopenharmony_ci if (action(adjList_[startNode].value)) { 7314cf0368Sopenharmony_ci return true; 7414cf0368Sopenharmony_ci } 7514cf0368Sopenharmony_ci while (!nodes.empty()) { 7614cf0368Sopenharmony_ci edge = adjList_[nodes.top()].firstEdge; 7714cf0368Sopenharmony_ci while (edge) { 7814cf0368Sopenharmony_ci if (visited_[edge->adjIndex] == 0) { 7914cf0368Sopenharmony_ci visited_[edge->adjIndex] = 1; 8014cf0368Sopenharmony_ci nodes.push(edge->adjIndex); 8114cf0368Sopenharmony_ci if (action(adjList_[edge->adjIndex].value)) { 8214cf0368Sopenharmony_ci return true; 8314cf0368Sopenharmony_ci } 8414cf0368Sopenharmony_ci edge = adjList_[edge->adjIndex].firstEdge; 8514cf0368Sopenharmony_ci } else if (visited_[edge->adjIndex] == 1) { 8614cf0368Sopenharmony_ci return false; 8714cf0368Sopenharmony_ci } else { 8814cf0368Sopenharmony_ci edge = edge->next; 8914cf0368Sopenharmony_ci } 9014cf0368Sopenharmony_ci } 9114cf0368Sopenharmony_ci visited_[nodes.top()] = 2; // 2: all edge of the adj is visited. 9214cf0368Sopenharmony_ci nodes.pop(); 9314cf0368Sopenharmony_ci } 9414cf0368Sopenharmony_ci return true; 9514cf0368Sopenharmony_ci} 9614cf0368Sopenharmony_ci 9714cf0368Sopenharmony_cibool Graph::DfsUnconnectedGraph(Action action) 9814cf0368Sopenharmony_ci{ 9914cf0368Sopenharmony_ci visited_.resize(vertexNum_); 10014cf0368Sopenharmony_ci fill(visited_.begin(), visited_.end(), 0); 10114cf0368Sopenharmony_ci for (uint32_t node = 0; node < vertexNum_; node++) { 10214cf0368Sopenharmony_ci if (!visited_[node]) { 10314cf0368Sopenharmony_ci if (!Dfs(node, action, false)) { 10414cf0368Sopenharmony_ci return false; 10514cf0368Sopenharmony_ci } 10614cf0368Sopenharmony_ci } 10714cf0368Sopenharmony_ci } 10814cf0368Sopenharmony_ci return true; 10914cf0368Sopenharmony_ci} 11014cf0368Sopenharmony_ci 11114cf0368Sopenharmony_cibool Graph::IsValidType(const std::string &node) 11214cf0368Sopenharmony_ci{ 11314cf0368Sopenharmony_ci if (typeIdIndex_.find(node) == typeIdIndex_.end()) { 11414cf0368Sopenharmony_ci LOG_ERROR(UDMF_CLIENT, "invalid typeId. typeId:%{public}s ", node.c_str()); 11514cf0368Sopenharmony_ci return false; 11614cf0368Sopenharmony_ci } 11714cf0368Sopenharmony_ci return true; 11814cf0368Sopenharmony_ci} 11914cf0368Sopenharmony_ci 12014cf0368Sopenharmony_ciint32_t Graph::GetIndex(const std::string &node) 12114cf0368Sopenharmony_ci{ 12214cf0368Sopenharmony_ci auto idx = typeIdIndex_.find(node); 12314cf0368Sopenharmony_ci if (idx == typeIdIndex_.end()) { 12414cf0368Sopenharmony_ci return -1; 12514cf0368Sopenharmony_ci } 12614cf0368Sopenharmony_ci return idx->second; 12714cf0368Sopenharmony_ci} 12814cf0368Sopenharmony_ci 12914cf0368Sopenharmony_cibool Graph::IsDAG() 13014cf0368Sopenharmony_ci{ 13114cf0368Sopenharmony_ci return DfsUnconnectedGraph([&](uint32_t currNode) -> bool { return false; }); 13214cf0368Sopenharmony_ci} 13314cf0368Sopenharmony_ci} // namespace UDMF 13414cf0368Sopenharmony_ci} // namespace OHOS 135