@@ -3,7 +3,7 @@ Copyright 2024 Huawei Technologies Co., Ltd.
33
44Licensed under the Apache License, Version 2.0 (the "License");
55you may not use this file except in compliance with the License.
6- You may obtain a copy of the License at
6+ you may obtain a copy of the License at
77
88 http://www.apache.org/licenses/LICENSE-2.0
99
@@ -18,9 +18,12 @@ limitations under the License.
1818
1919#pragma once
2020
21+ #include < algorithm>
2122#include < set>
2223#include < stdexcept>
24+ #include < type_traits>
2325#include < unordered_map>
26+ #include < utility>
2427#include < vector>
2528
2629#include " osp/auxiliary/hash_util.hpp"
@@ -32,6 +35,7 @@ limitations under the License.
3235namespace osp {
3336
3437/* *
38+ * @class MerkleHashComputer
3539 * @brief Computes Merkle hashes for graph vertices to identify isomorphic orbits.
3640 *
3741 * The Merkle hash of a vertex is computed recursively based on its own properties
@@ -57,7 +61,7 @@ class MerkleHashComputer : public HashComputer<VertexIdxT<GraphT>> {
5761
5862 NodeHashFuncT nodeHashFunc_;
5963
60- inline void ComputeHashesHelper (const VertexType &v, std::vector<std::size_t > &parentChildHashes) {
64+ void ComputeHashesHelper (const VertexType &v, std::vector<std::size_t > &parentChildHashes) {
6165 std::sort (parentChildHashes.begin (), parentChildHashes.end ());
6266
6367 std::size_t hash = nodeHashFunc_ (v);
@@ -76,64 +80,84 @@ class MerkleHashComputer : public HashComputer<VertexIdxT<GraphT>> {
7680
7781 template <typename RetT = void >
7882 std::enable_if_t <forward, RetT> ComputeHashes (const GraphT &graph) {
79- vertexHashes_.resize (graph.NumVertices ());
83+ const size_t numVertices = graph.NumVertices ();
84+ vertexHashes_.resize (numVertices);
85+ std::vector<std::size_t > neighborHashes;
8086
8187 for (const VertexType &v : TopSortView (graph)) {
82- std::vector<std:: size_t > parentHashes ;
88+ neighborHashes. clear () ;
8389 for (const VertexType &parent : graph.Parents (v)) {
84- parentHashes .push_back (vertexHashes_[parent]);
90+ neighborHashes .push_back (vertexHashes_[parent]);
8591 }
86- ComputeHashesHelper (v, parentHashes );
92+ ComputeHashesHelper (v, neighborHashes );
8793 }
8894 }
8995
9096 template <typename RetT = void >
9197 std::enable_if_t <not forward, RetT> ComputeHashes (const GraphT &graph) {
92- vertexHashes_.resize (graph.NumVertices ());
98+ const size_t numVertices = graph.NumVertices ();
99+ vertexHashes_.resize (numVertices);
100+ std::vector<std::size_t > neighborHashes;
93101
94102 const auto topSort = GetTopOrderReverse (graph);
95103 for (auto it = topSort.cbegin (); it != topSort.cend (); ++it) {
96104 const VertexType &v = *it;
97- std::vector<std:: size_t > childHashes ;
105+ neighborHashes. clear () ;
98106 for (const VertexType &child : graph.Children (v)) {
99- childHashes .push_back (vertexHashes_[child]);
107+ neighborHashes .push_back (vertexHashes_[child]);
100108 }
101- ComputeHashesHelper (v, childHashes );
109+ ComputeHashesHelper (v, neighborHashes );
102110 }
103111 }
104112
105113 public:
114+ /* *
115+ * @brief Constructs the MerkleHashComputer and immediately computes the hashes.
116+ * @tparam Args Arguments forwarded to the NodeHashFuncT constructor.
117+ * @param graph The graph to process.
118+ * @param args Arguments for the node hash function.
119+ */
106120 template <typename ... Args>
107121 MerkleHashComputer (const GraphT &graph, Args &&...args)
108122 : HashComputer<VertexType>(), nodeHashFunc_(std::forward<Args>(args)...) {
109123 ComputeHashes (graph);
110124 }
111125
112- virtual ~MerkleHashComputer () override = default ;
126+ ~MerkleHashComputer () override = default ;
113127
114- inline std::size_t GetVertexHash (const VertexType &v) const override { return vertexHashes_[v]; }
128+ std::size_t GetVertexHash (const VertexType &v) const override { return vertexHashes_[v]; }
115129
116- inline const std::vector<std::size_t > &GetVertexHashes () const override { return vertexHashes_; }
130+ const std::vector<std::size_t > &GetVertexHashes () const override { return vertexHashes_; }
117131
118- inline std::size_t NumOrbits () const override { return orbits_.size (); }
132+ std::size_t NumOrbits () const override { return orbits_.size (); }
119133
120- inline const std::vector<VertexType> &GetOrbit (const VertexType &v) const override {
134+ const std::vector<VertexType> &GetOrbit (const VertexType &v) const override {
121135 return this ->GetOrbitFromHash (this ->GetVertexHash (v));
122136 }
123137
124- inline const std::unordered_map<std::size_t , std::vector<VertexType>> &GetOrbits () const override { return orbits_; }
138+ const std::unordered_map<std::size_t , std::vector<VertexType>> &GetOrbits () const override { return orbits_; }
125139
126- inline const std::vector<VertexType> &GetOrbitFromHash (const std::size_t &hash) const override { return orbits_.at (hash); }
140+ const std::vector<VertexType> &GetOrbitFromHash (const std::size_t &hash) const override { return orbits_.at (hash); }
127141};
128142
143+ /* *
144+ * @brief Checks if two graphs are isomorphic based on Merkle hashes.
145+ * @note This is a necessary but not sufficient condition for graph isomorphism in general cases,
146+ * but sufficient for the kinds of DAGs often encountered in this context.
147+ *
148+ * @tparam GraphT The graph type.
149+ * @tparam NodeHashFuncT The node hash function type.
150+ * @tparam forward Direction of hash computation.
151+ * @param g1 The first graph.
152+ * @param g2 The second graph.
153+ * @return True if they have the same orbit structure, false otherwise.
154+ */
129155template <typename GraphT, typename NodeHashFuncT = UniformNodeHashFunc<VertexIdxT<GraphT>>, bool forward = true >
130156bool AreIsomorphicByMerkleHash (const GraphT &g1, const GraphT &g2) {
131- // Basic check: Different numbers of vertices or edges mean they can't be isomorphic.
132157 if (g1.NumVertices () != g2.NumVertices () || g1.NumEdges () != g2.NumEdges ()) {
133158 return false ;
134159 }
135160
136- // --- Compute Hashes in the Specified Direction ---
137161 MerkleHashComputer<GraphT, NodeHashFuncT, forward> hash1 (g1);
138162 MerkleHashComputer<GraphT, NodeHashFuncT, forward> hash2 (g2);
139163
0 commit comments