File indexing completed on 2024-05-19 05:42:16
0001 // ct_lvtqtc_alg_transitive_reduction.h -*-C++-*- 0002 0003 /* 0004 // Copyright 2023 Codethink Ltd <codethink@codethink.co.uk> 0005 // SPDX-License-Identifier: Apache-2.0 0006 // 0007 // Licensed under the Apache License, Version 2.0 (the "License"); 0008 // you may not use this file except in compliance with the License. 0009 // You may obtain a copy of the License at 0010 // 0011 // http://www.apache.org/licenses/LICENSE-2.0 0012 // 0013 // Unless required by applicable law or agreed to in writing, software 0014 // distributed under the License is distributed on an "AS IS" BASIS, 0015 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 0016 // See the License for the specific language governing permissions and 0017 // limitations under the License. 0018 */ 0019 0020 #ifndef INCLUDED_CT_LVTQTC_ALG_TRANSITIVE_REDUCTION 0021 #define INCLUDED_CT_LVTQTC_ALG_TRANSITIVE_REDUCTION 0022 0023 #include <QElapsedTimer> 0024 #include <QObject> 0025 #include <QString> 0026 #include <QThreadPool> 0027 0028 #include <memory> 0029 #include <shared_mutex> 0030 #include <string> 0031 #include <unordered_map> 0032 #include <unordered_set> 0033 #include <vector> 0034 0035 #include "lvtqtc_export.h" 0036 0037 namespace Codethink::lvtldr { 0038 class LakosianNode; 0039 } 0040 0041 namespace Codethink::lvtqtc { 0042 class LakosRelation; 0043 class LakosEntity; 0044 struct EdgeCollection; 0045 0046 class LVTQTC_EXPORT AlgorithmTransitiveReduction : public QObject { 0047 // Inherits QObject for QObject::tr() 0048 Q_OBJECT 0049 public: 0050 void setVertices(std::vector<LakosEntity *> entities); 0051 // the list of the vertices we will run the algorithm on. 0052 0053 void run(); 0054 0055 bool hasRun() const; 0056 bool hasError() const; 0057 long long totalRunTime() const; 0058 0059 QString errorMessage() const; 0060 0061 std::unordered_map<LakosEntity *, std::vector<std::shared_ptr<EdgeCollection>>>& redundantEdgesByNode(); 0062 // Returns a reference so we don't need to copy it all the time. 0063 // be careful not to hold to the reference. 0064 0065 void reset(); 0066 // reset the result of the algorithm and make it usable again. 0067 0068 private: 0069 // Algorithm Steps. 0070 0071 void startLookingForRedundantEdgesOnNode(LakosEntity *entity); 0072 // for each direct connection from `entity` to any other entity, 0073 // we have a redundant relation if we find a longer path that also 0074 // connects `entity` to its direct connection. 0075 // if so, the direct connecction is a redundant connection. 0076 0077 bool 0078 recursiveTransitiveSearch(LakosEntity *target, LakosEntity *current, std::unordered_set<LakosEntity *>& visited); 0079 // target is the direct connection from the original entity 0080 // current is where we are right now on the graph tree. 0081 // if current == target, that means we found a redundant edge. 0082 0083 class RunnableThread; 0084 0085 std::shared_mutex d_collectionSerialiser; 0086 std::unordered_map<LakosEntity *, std::vector<std::shared_ptr<EdgeCollection>>> d_redundantEdgesByNode; 0087 std::unordered_set<std::shared_ptr<EdgeCollection>> d_redundantEdges; 0088 std::vector<LakosEntity *> d_entities; 0089 0090 using InputHashKey = unsigned long long; 0091 using CachedOutput = std::vector<std::tuple<lvtldr::LakosianNode *, lvtldr::LakosianNode *>>; 0092 std::unordered_map<InputHashKey, CachedOutput> d_redundantEdgesCache; 0093 0094 QElapsedTimer d_totalTimer; 0095 // total time it took to run the algorithm. 0096 0097 QString d_errorMessage; 0098 0099 QThreadPool d_pool; 0100 0101 bool d_hasRun = false; 0102 bool d_hasError = false; 0103 0104 long long d_totalTime = 0; 0105 }; 0106 0107 } // namespace Codethink::lvtqtc 0108 0109 #endif