From 4d331a33078674bc1adb8705209adfcb6578a2f0 Mon Sep 17 00:00:00 2001 From: Harsh Agrawal Date: Thu, 13 Oct 2022 17:43:06 +0530 Subject: [PATCH 1/3] Reformat files --- Makefile | 3 + include/ARGraph.hpp | 1250 +++++++++++------------ include/Options.hpp | 268 +++-- include/VFLib.h | 26 +- include/loaders/EdgeStreamARGLoader.hpp | 234 ++--- include/loaders/FastStreamARGLoader.hpp | 165 ++- main.cpp | 380 ++++--- 7 files changed, 1116 insertions(+), 1210 deletions(-) diff --git a/Makefile b/Makefile index 1bdd5de..74da872 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,9 @@ all: vf3 vf3l vf3: $(CC) $(CFLAGS) $(CPPFLAGS) -o bin/$@ main.cpp -DVF3 +vf3.so: + $(CC) $(CFLAGS) $(CPPFLAGS) -fPIC -shared -o bin/$@ main.cpp -DVF3 + vf3l: $(CC) $(CFLAGS) $(CPPFLAGS) -o bin/$@ main.cpp -DVF3L diff --git a/include/ARGraph.hpp b/include/ARGraph.hpp index 9986e9e..b56996e 100644 --- a/include/ARGraph.hpp +++ b/include/ARGraph.hpp @@ -3,7 +3,8 @@ * @author P. Foggia (pfoggia\@unisa.it) * @author V.Carletti (vcarletti\@unisa.it) * @date December, 2014 - * @brief Definition of a class representing an Attributed Relational Graph (ARG). + * @brief Definition of a class representing an Attributed Relational Graph + * (ARG). */ #ifndef ARGRAPH_H @@ -12,659 +13,610 @@ #include #include #include + +#include #include +#include #include -#include +namespace vflib { + +typedef uint32_t nodeID_t; /**::max)(); /**>(std::istream& is, Empty& e) { return is; } + + bool operator==(Empty& e2) { return true; } -namespace vflib -{ - - typedef uint32_t nodeID_t; /**::max)(); /**>(std::istream& is, Empty& e) - { - return is; - } - - bool operator== (Empty &e2) { - return true; - } - - friend inline bool operator< (const Empty & s1, const Empty & s2) - { - return false; - } - - }; - - /** - * @class EqualityComparator - * @brief Default Functors for Node/Edge Attributes Equality Test. - */ - template - class EqualityComparator - { - public: - bool operator()(T1& a, T2& b) - { - return a == b; - } - }; - - /** - * @class ARGLoader - * @brief Abstract class ARGLoader. Allows to construct an ARGraph. - * @note The abstract class, ARGLoader, is defined to allow the - * use of different file formats for loading the graphs.\n - * The loader is queried by the ARGraph to acquire the information - * needed for building the graph.\n - * A simple ARGLoader based on iostream.h is provided in argloader.hpp; - * @see argloader.hpp - */ - template - class ARGLoader - { - public: - virtual ~ARGLoader() {} - - /** - * @brief Counts the number of loaded nodes - * @returns Number of loaded nodes. - */ - virtual uint32_t NodeCount() const = 0; - /** - * @brief Returns the attribute of a given node. - * @param [in] node Node id. - * @returns Attribute of the node. - */ - virtual Node GetNodeAttr(nodeID_t node) = 0; - /** - * @brief Counts the number of edges out going from a given node. - * @param [in] node Node id. - * @returns Number of out going edges. - */ - virtual uint32_t OutEdgeCount(nodeID_t node) const = 0; - /** - * @brief Returns the End node of the i-th edge out going from a given node. - * @param [in] node Node id. - * @param [in] i Index of the edge. - * @param [out] pattr Attribute of the edge. - * @returns End node id. - */ - virtual nodeID_t GetOutEdge(nodeID_t node, uint32_t i, Edge *pattr) = 0; - }; - - /** - * @class ARGraph - * @brief This is the real representation of an ARG. - * @note The graphs, once created, are immutable, in the sense that - * graph-editing operations are not provided.\n - * This allows the use of an internal representation particularly - * suited for efficient graph matching, which is the primary target - * of this program. - * - * Edges and edge attributes (pointers) are stored into sorted - * vectors associated to each node, and are looked for - * using binary search. - * - * Nodes are identified using the type node_id, which is currently - * unsigned short; the special value NULL_NODE is used as null - * value for this type. - * - * Bound checks are performed using the assert macro. They can be - * disabled by ensuring the macro NDEBUG is defined during - * compilation. - * - * Differently from the previous versions of this library - * (before version 2.0), there is no more an adjacency matrix to - * check for the existence of a node. - * @see argloader.hpp - * @see argedit.hpp - */ - template - class ARGraph - { - public: - - typedef void *param_type; /** NodeVec; - typedef std::vector EdgeAttrVector; - typedef std::vector NodeAttrVector; - - uint32_t n; /** in_attr; /** out_attr; /** in; /** out; /** *loader); - - uint32_t NodeCount() const; - uint32_t EdgeCount() const; - uint32_t InEdgeCount() const; - uint32_t OutEdgeCount() const; - - Node& GetNodeAttr(nodeID_t i); - void SetNodeAttr(nodeID_t i, Node &attr); - - bool HasEdge(nodeID_t n1, nodeID_t n2) const; - bool HasEdge(nodeID_t n1, nodeID_t n2, Edge &pattr) const; - Edge& GetEdgeAttr(nodeID_t n1, nodeID_t n2); - void SetEdgeAttr(nodeID_t n1, nodeID_t n2, Edge &attr); - - uint32_t InEdgeCount(nodeID_t node) const; - uint32_t OutEdgeCount(nodeID_t node) const; - uint32_t EdgeCount(nodeID_t node) const; - nodeID_t GetInEdge(nodeID_t node, uint32_t i) const; - nodeID_t GetInEdge(nodeID_t node, uint32_t i, Edge& pattr) const; - nodeID_t GetOutEdge(nodeID_t node, uint32_t i) const; - nodeID_t GetOutEdge(nodeID_t node, uint32_t i, Edge& pattr) const; - nodeID_t* GetOutEdgeSet(nodeID_t node); - nodeID_t* GetInEdgeSet(nodeID_t node); - - /** - * @brief Maximum incoming degree in the graph - * @returns Maximum in degree - */ - uint32_t InMaxDegree() const { return max_deg_in; } - /** - * @brief Maximum out going degree in the graph - * @returns Maximum out degree - */ - uint32_t OutMaxDegree() const { return max_deg_out; } - /** - * @brief Maximum degree in the graph - * @returns Maximum degree - */ - uint32_t MaxDegree() const { return max_degree; } - - /** - * @brief Number of different node attibute in the graph - * @returns Number of different node attibute - */ - uint32_t NodeAttrCount() const { return n_attr_count; } - - /** - * @brief Number of different edge attibute in the graph - * @returns Number of different edge attibute - */ - uint32_t EdgeAttrCount() const { return e_attr_count; } - - void VisitInEdges(nodeID_t node, edge_visitor vis, param_type param); - void VisitOutEdges(nodeID_t node, edge_visitor vis, param_type param); - void VisitEdges(nodeID_t node, edge_visitor vis, param_type param); - }; - - /** - * @brief Returns the number of nodes in the graph - * @returns Number of nodes - */ - template - inline uint32_t ARGraph::NodeCount() const - { - return n; - } - - /** - * @brief Returns the number of edge in the graph - * @returns Number of edge - */ - template - inline uint32_t ARGraph::EdgeCount() const - { - return e_count; - } - - /** - * @brief Returns the number of in edges in the graph - * @returns Number of in edges - */ - template - inline uint32_t ARGraph::InEdgeCount() const - { - return e_in_count; - } - - /** - * @brief Returns the number of out edges in the graph - * @returns Number of out edges - */ - template - inline uint32_t ARGraph::OutEdgeCount() const - { - return e_out_count; - } - - /** - * @brief Return the attribute of a given node. - * @param [in] id Node id. - * @returns Attribute of the node. - */ - template - inline Node& ARGraph::GetNodeAttr(nodeID_t id) - { - assert(id < n); - return attr[id]; - } - - /** - * @brief Check the presence of an edge. - * @param [in] n1 Start node id. - * @param [in] n2 End node id. - * @retval TRUE If the edge exists. - * @retval FALSE If the edge doesn't exist. - */ - template - inline bool ARGraph::HasEdge(nodeID_t n1, nodeID_t n2) const - { - nodeID_t index; - return GetNodeIndex(n1, n2, index); - } - - /** - * @brief Gets the index of node n2 in the neighboors set of n1. - * @param [in] n1 First node id. - * @param [in] n2 Second node id. - * @param [out] index Index of the node n2 in the neighboors set of n1. - * @retval TRUE If the the nodes n2 is a neighboor of n1. - * @retval FALSE If the the nodes n2 isn't a neighboor of n1. - */ - template - inline bool ARGraph::GetNodeIndex(nodeID_t n1, nodeID_t n2, nodeID_t &index) const - { - unsigned long a, b, c; - //NodeVec id = out[n1]; - - assert(n1 < n); - assert(n2 < n); - - a = 0; - b = out[n1].size(); - while (a < b) - { - c = (unsigned)(a + b) >> 1; - if (out[n1][c] < n2) - a = c + 1; - else if (out[n1][c] > n2) - b = c; - else - { - index = c; - return true; - } - } - - return false; - } - - /** - * @brief Gets the attribute of an edge. - * @note The method assumes that the edge exists. - * @param [in] n1 Start node id. - * @param [in] n2 End node id. - * @returns the attribute of the edge. - */ - template - inline Edge& ARGraph::GetEdgeAttr(nodeID_t n1, nodeID_t n2) - { - nodeID_t index; - assert(GetNodeIndex(n1, n2, index) == true); - return out_attr[n1][index]; - } - - /** - * @brief Returns the number of edges going into a node. - * @param [in] node Node id. - * @returns Number of edges going into a node. - */ - template - inline uint32_t ARGraph::InEdgeCount(nodeID_t node) const - { - assert(node < n); - return (int)in[node].size(); - } - - - /** - * @brief Returns the number of edges departing from a node. - * @param [in] node Node id. - * @returns Number of edges departing from a node. - */ - template - inline uint32_t ARGraph::OutEdgeCount(nodeID_t node) const - { - assert(node < n); - return (int)out[node].size(); - } - - /** - * @brief Returns the full valence (in and out) of a node. - * @param [in] node Node id. - * @returns Number of edges of a node. - */ - template - inline uint32_t ARGraph::EdgeCount(nodeID_t node) const - { - assert(node < n); - return in[node].size() + out[node].size(); - } - - /** - * @brief Gets the other end of an edge entering a node. - * @param [in] node Node id. - * @param [in] i Index of the neighboor of the node. - * @returns Other end of the edge. - */ - template - inline nodeID_t ARGraph::GetInEdge(nodeID_t node, uint32_t i) const - { - assert(node < n); - assert(i < in[node].size()); - if (node == 2 && i == 0) - return in[node][i]; - return in[node][i]; - } - - /** - * @brief Gets the other end of an edge entering a node and its attribute. - * @param [in] node Node id. - * @param [in] i Index of the neighboor of the node. - * @param [out] pattr Attribute of the edge. - * @returns Other end of the edge. - */ - template - inline nodeID_t ARGraph::GetInEdge(nodeID_t node, uint32_t i, - Edge& pattr) const - { - assert(node < n); - assert(i < in[node].size()); - pattr = in_attr[node][i]; - return in[node][i]; - } - - /** - * @brief Gets the other end of an edge leaving a node. - * @param [in] node Node id. - * @param [in] i Index of the neighboor of the node. - * @returns Other end of the edge. - */ - template - inline nodeID_t ARGraph::GetOutEdge(nodeID_t node, uint32_t i) const - { - assert(node < n); - assert(i < out[node].size()); - return out[node][i]; - } - - /** - * @brief Gets the other end of an edge leaving a node and its attribute. - * @param [in] node Node id. - * @param [in] i Index of the neighboor of the node. - * @param [out] pattr Attribute of the edge. - * @returns Other end of the edge. - */ - template - inline nodeID_t ARGraph::GetOutEdge(nodeID_t node, uint32_t i, - Edge& pattr) const - { - assert(node < n); - assert(i < out[node].size()); - pattr = out_attr[node][i]; - return out[node][i]; - } - - /** - * @brief Change the attribute of a node. - * @param [in] i Node id. - * @param [int] new_attr Attribute of the node. - */ - template - void ARGraph::SetNodeAttr(nodeID_t i, Node &new_attr) - { - assert(i < n); - attr[i] = new_attr; - } - - /** - * @brief Gets the set of out edges - * @param [in] node Node id. - * @returns Set of out edges - */ - template - inline nodeID_t* ARGraph::GetOutEdgeSet(nodeID_t node) - { - return out[node].data(); - } - - /** - * @brief Gets the set of in edges - * @param [in] node Node id. - * @returns Set of in edges - */ - template - inline nodeID_t* ARGraph::GetInEdgeSet(nodeID_t node) - { - return in[node].data(); - } - - /*------------------------------------------------------------------- - * Checks the existence of an edge, and returns its attribute - * using the parameter pattr. - * Note: uses binary search. - * Implem. note: Uses the out/out_attr vectors; this fact is - * exploited in the constructor to generate the - * in_attr vector - ------------------------------------------------------------------*/ - /** - * @brief Checks the existence of an edge, and returns its attribute. - * @note The method uses binary search. \n - * Uses the out/out_attr vectors; this fact is exploited in the - * constructor to generate the in_attr vector. - * @param [in] n1 Start node id. - * @param [in] n2 End node id. - * @param [out] pattr Attribute of the edge. - * @retval TRUE If the edge exists. - * @retval FALSE If the edge doesn't exist. - */ - template - bool ARGraph::HasEdge(nodeID_t n1, nodeID_t n2, Edge &pattr) const - { - nodeID_t index; - if (GetNodeIndex(n1, n2, index)) { - pattr = out_attr[n1][index]; - return true; - } - return false; - } - - /** - * @brief Change the attribute of an edge. It is an error if the edge does not exist. - * @note The method uses binary search. - * @param [in] n1 Start node id. - * @param [in] n2 End node id. - * @param [in] pattr Attribute of the edge. - */ - template - void ARGraph::SetEdgeAttr(nodeID_t n1, nodeID_t n2, Edge& new_attr) - { - uint32_t c; - assert(n1 < n); - assert(n2 < n); - - if (GetNodeIndex(n1, n2, c)) - out_attr[n1][c] = new_attr; - - if (GetNodeIndex(n2, n1, c)) - in_attr[n2][c] = new_attr; - } - - /** - * @brief Applies the visitor to all the in edges of the node. - * @param [in] node Node id. - * @param [in] vis Edge Visitor. - * @param [in] param Generic param for the visitor. - */ - template - void ARGraph::VisitInEdges(nodeID_t node, edge_visitor vis, - param_type param) - { - assert(node < n); - size_t i; - for (i = 0; i < in[node].size(); i++) - vis(this, in[node][i], node, in_attr[node][i], param); - } - - /** - * @brief Applies the visitor to all the out edges of the node. - * @param [in] node Node id. - * @param [in] vis Edge Visitor. - * @param [in] param Generic param for the visitor. - */ - template - void ARGraph::VisitOutEdges(nodeID_t node, edge_visitor vis, - param_type param) - { - assert(node < n); - size_t i; - for (i = 0; i < out[node].size(); i++) - vis(this, node, out[node][i], out_attr[node][i], param); - } - - /** - * @brief Applies the visitor to all the edges of the node. - * @param [in] node Node id. - * @param [in] vis Edge Visitor. - * @param [in] param Generic param for the visitor. - */ - template - void ARGraph::VisitEdges(nodeID_t node, edge_visitor vis, param_type param) - { - VisitInEdges(node, vis, param); - VisitOutEdges(node, vis, param); - } - - /** - * @brief Constructs the graph form a loader. - * @param loader ARGLoader - */ - template - ARGraph::ARGraph(ARGLoader *loader) - { - n = loader->NodeCount(); - attr.resize(n); - in.resize(n); - in_attr.resize(n); - out.resize(n); - out_attr.resize(n); - - e_count = 0; - e_out_count = 0; - e_in_count = 0; - n_attr_count = 0; - e_attr_count = 0; - std::map attributemap; - std::map e_attributemap; - - max_deg_in = max_deg_out = max_degree = 0; - - std::vector< std::map< nodeID_t, Edge> > revmap; - typename std::map< nodeID_t, Edge>::iterator rvit; - revmap.resize(n); - - uint32_t i, j; - for (i = 0; i < n; i++) - { - Node attribute = loader->GetNodeAttr(i); - attr[i]=(attribute); - - if(!attributemap.count(attribute)) - { - attributemap[attribute]=true; - n_attr_count++; - } - } - - for (i = 0; i < n; i++) - { - uint32_t k = loader->OutEdgeCount(i); - e_out_count += k; - - if (k > max_deg_out) - max_deg_out = k; - out[i].resize(k); - out_attr[i].resize(k); - - for (j = 0; j < k; j++) - { - nodeID_t n2 = loader->GetOutEdge(i, j, - &out_attr[i][j]); - out[i][j]=n2; - revmap[n2][i]=out_attr[i][j]; - } - } - - for (i = 0; i < n; i++) - { - uint32_t k = revmap[i].size(); - e_in_count += k; - - if (k > max_deg_in) - max_deg_in = k; - - in[i].resize(k); - in_attr[i].resize(k); - - for (j = 0, rvit=revmap[i].begin(); j < k; j++, rvit++) - { in[i][j] = rvit->first; - Edge edge_attr=rvit->second; - in_attr[i][j]=edge_attr; - if(!e_attributemap.count(edge_attr)) { - e_attributemap[edge_attr]=true; - e_attr_count++; - } - } - - } - - for (i = 0; i < n; i++) { - uint32_t count = in[i].size() + out[i].size(); - e_count += count; - if (count > max_degree) { - max_degree = count; - } - } - - } + friend inline bool operator<(const Empty& s1, const Empty& s2) { + return false; + } +}; +/** + * @class EqualityComparator + * @brief Default Functors for Node/Edge Attributes Equality Test. + */ +template +class EqualityComparator { + public: + bool operator()(T1& a, T2& b) { return a == b; } +}; + +/** + * @class ARGLoader + * @brief Abstract class ARGLoader. Allows to construct an ARGraph. + * @note The abstract class, ARGLoader, is defined to allow the + * use of different file formats for loading the graphs.\n + * The loader is queried by the ARGraph to acquire the information + * needed for building the graph.\n + * A simple ARGLoader based on iostream.h is provided in argloader.hpp; + * @see argloader.hpp + */ +template +class ARGLoader { + public: + virtual ~ARGLoader() {} + + /** + * @brief Counts the number of loaded nodes + * @returns Number of loaded nodes. + */ + virtual uint32_t NodeCount() const = 0; + /** + * @brief Returns the attribute of a given node. + * @param [in] node Node id. + * @returns Attribute of the node. + */ + virtual Node GetNodeAttr(nodeID_t node) = 0; + /** + * @brief Counts the number of edges out going from a given node. + * @param [in] node Node id. + * @returns Number of out going edges. + */ + virtual uint32_t OutEdgeCount(nodeID_t node) const = 0; + /** + * @brief Returns the End node of the i-th edge out going from a given node. + * @param [in] node Node id. + * @param [in] i Index of the edge. + * @param [out] pattr Attribute of the edge. + * @returns End node id. + */ + virtual nodeID_t GetOutEdge(nodeID_t node, uint32_t i, Edge* pattr) = 0; +}; + +/** + * @class ARGraph + * @brief This is the real representation of an ARG. + * @note The graphs, once created, are immutable, in the sense that + * graph-editing operations are not provided.\n + * This allows the use of an internal representation particularly + * suited for efficient graph matching, which is the primary target + * of this program. + * + * Edges and edge attributes (pointers) are stored into sorted + * vectors associated to each node, and are looked for + * using binary search. + * + * Nodes are identified using the type node_id, which is currently + * unsigned short; the special value NULL_NODE is used as null + * value for this type. + * + * Bound checks are performed using the assert macro. They can be + * disabled by ensuring the macro NDEBUG is defined during + * compilation. + * + * Differently from the previous versions of this library + * (before version 2.0), there is no more an adjacency matrix to + * check for the existence of a node. + * @see argloader.hpp + * @see argedit.hpp + */ +template +class ARGraph { + public: + typedef void* param_type; /** NodeVec; + typedef std::vector EdgeAttrVector; + typedef std::vector NodeAttrVector; + + uint32_t n; /** in_attr; /** out_attr; /** in; /** out; /*** loader); + + uint32_t NodeCount() const; + uint32_t EdgeCount() const; + uint32_t InEdgeCount() const; + uint32_t OutEdgeCount() const; + + Node& GetNodeAttr(nodeID_t i); + void SetNodeAttr(nodeID_t i, Node& attr); + + bool HasEdge(nodeID_t n1, nodeID_t n2) const; + bool HasEdge(nodeID_t n1, nodeID_t n2, Edge& pattr) const; + Edge& GetEdgeAttr(nodeID_t n1, nodeID_t n2); + void SetEdgeAttr(nodeID_t n1, nodeID_t n2, Edge& attr); + + uint32_t InEdgeCount(nodeID_t node) const; + uint32_t OutEdgeCount(nodeID_t node) const; + uint32_t EdgeCount(nodeID_t node) const; + nodeID_t GetInEdge(nodeID_t node, uint32_t i) const; + nodeID_t GetInEdge(nodeID_t node, uint32_t i, Edge& pattr) const; + nodeID_t GetOutEdge(nodeID_t node, uint32_t i) const; + nodeID_t GetOutEdge(nodeID_t node, uint32_t i, Edge& pattr) const; + nodeID_t* GetOutEdgeSet(nodeID_t node); + nodeID_t* GetInEdgeSet(nodeID_t node); + + /** + * @brief Maximum incoming degree in the graph + * @returns Maximum in degree + */ + uint32_t InMaxDegree() const { return max_deg_in; } + /** + * @brief Maximum out going degree in the graph + * @returns Maximum out degree + */ + uint32_t OutMaxDegree() const { return max_deg_out; } + /** + * @brief Maximum degree in the graph + * @returns Maximum degree + */ + uint32_t MaxDegree() const { return max_degree; } + + /** + * @brief Number of different node attibute in the graph + * @returns Number of different node attibute + */ + uint32_t NodeAttrCount() const { return n_attr_count; } + + /** + * @brief Number of different edge attibute in the graph + * @returns Number of different edge attibute + */ + uint32_t EdgeAttrCount() const { return e_attr_count; } + + void VisitInEdges(nodeID_t node, edge_visitor vis, param_type param); + void VisitOutEdges(nodeID_t node, edge_visitor vis, param_type param); + void VisitEdges(nodeID_t node, edge_visitor vis, param_type param); +}; + +/** + * @brief Returns the number of nodes in the graph + * @returns Number of nodes + */ +template +inline uint32_t ARGraph::NodeCount() const { + return n; +} + +/** + * @brief Returns the number of edge in the graph + * @returns Number of edge + */ +template +inline uint32_t ARGraph::EdgeCount() const { + return e_count; +} + +/** + * @brief Returns the number of in edges in the graph + * @returns Number of in edges + */ +template +inline uint32_t ARGraph::InEdgeCount() const { + return e_in_count; +} + +/** + * @brief Returns the number of out edges in the graph + * @returns Number of out edges + */ +template +inline uint32_t ARGraph::OutEdgeCount() const { + return e_out_count; +} + +/** + * @brief Return the attribute of a given node. + * @param [in] id Node id. + * @returns Attribute of the node. + */ +template +inline Node& ARGraph::GetNodeAttr(nodeID_t id) { + assert(id < n); + return attr[id]; +} + +/** + * @brief Check the presence of an edge. + * @param [in] n1 Start node id. + * @param [in] n2 End node id. + * @retval TRUE If the edge exists. + * @retval FALSE If the edge doesn't exist. + */ +template +inline bool ARGraph::HasEdge(nodeID_t n1, nodeID_t n2) const { + nodeID_t index; + return GetNodeIndex(n1, n2, index); +} + +/** + * @brief Gets the index of node n2 in the neighboors set of n1. + * @param [in] n1 First node id. + * @param [in] n2 Second node id. + * @param [out] index Index of the node n2 in the neighboors set of n1. + * @retval TRUE If the the nodes n2 is a neighboor of n1. + * @retval FALSE If the the nodes n2 isn't a neighboor of n1. + */ +template +inline bool ARGraph::GetNodeIndex(nodeID_t n1, nodeID_t n2, + nodeID_t& index) const { + unsigned long a, b, c; + // NodeVec id = out[n1]; + + assert(n1 < n); + assert(n2 < n); + + a = 0; + b = out[n1].size(); + while (a < b) { + c = (unsigned)(a + b) >> 1; + if (out[n1][c] < n2) + a = c + 1; + else if (out[n1][c] > n2) + b = c; + else { + index = c; + return true; + } + } + + return false; +} + +/** + * @brief Gets the attribute of an edge. + * @note The method assumes that the edge exists. + * @param [in] n1 Start node id. + * @param [in] n2 End node id. + * @returns the attribute of the edge. + */ +template +inline Edge& ARGraph::GetEdgeAttr(nodeID_t n1, nodeID_t n2) { + nodeID_t index; + assert(GetNodeIndex(n1, n2, index) == true); + return out_attr[n1][index]; +} + +/** + * @brief Returns the number of edges going into a node. + * @param [in] node Node id. + * @returns Number of edges going into a node. + */ +template +inline uint32_t ARGraph::InEdgeCount(nodeID_t node) const { + assert(node < n); + return (int)in[node].size(); +} + +/** + * @brief Returns the number of edges departing from a node. + * @param [in] node Node id. + * @returns Number of edges departing from a node. + */ +template +inline uint32_t ARGraph::OutEdgeCount(nodeID_t node) const { + assert(node < n); + return (int)out[node].size(); +} + +/** + * @brief Returns the full valence (in and out) of a node. + * @param [in] node Node id. + * @returns Number of edges of a node. + */ +template +inline uint32_t ARGraph::EdgeCount(nodeID_t node) const { + assert(node < n); + return in[node].size() + out[node].size(); +} + +/** + * @brief Gets the other end of an edge entering a node. + * @param [in] node Node id. + * @param [in] i Index of the neighboor of the node. + * @returns Other end of the edge. + */ +template +inline nodeID_t ARGraph::GetInEdge(nodeID_t node, + uint32_t i) const { + assert(node < n); + assert(i < in[node].size()); + if (node == 2 && i == 0) return in[node][i]; + return in[node][i]; +} + +/** + * @brief Gets the other end of an edge entering a node and its attribute. + * @param [in] node Node id. + * @param [in] i Index of the neighboor of the node. + * @param [out] pattr Attribute of the edge. + * @returns Other end of the edge. + */ +template +inline nodeID_t ARGraph::GetInEdge(nodeID_t node, uint32_t i, + Edge& pattr) const { + assert(node < n); + assert(i < in[node].size()); + pattr = in_attr[node][i]; + return in[node][i]; +} + +/** + * @brief Gets the other end of an edge leaving a node. + * @param [in] node Node id. + * @param [in] i Index of the neighboor of the node. + * @returns Other end of the edge. + */ +template +inline nodeID_t ARGraph::GetOutEdge(nodeID_t node, + uint32_t i) const { + assert(node < n); + assert(i < out[node].size()); + return out[node][i]; +} + +/** + * @brief Gets the other end of an edge leaving a node and its attribute. + * @param [in] node Node id. + * @param [in] i Index of the neighboor of the node. + * @param [out] pattr Attribute of the edge. + * @returns Other end of the edge. + */ +template +inline nodeID_t ARGraph::GetOutEdge(nodeID_t node, uint32_t i, + Edge& pattr) const { + assert(node < n); + assert(i < out[node].size()); + pattr = out_attr[node][i]; + return out[node][i]; +} + +/** + * @brief Change the attribute of a node. + * @param [in] i Node id. + * @param [int] new_attr Attribute of the node. + */ +template +void ARGraph::SetNodeAttr(nodeID_t i, Node& new_attr) { + assert(i < n); + attr[i] = new_attr; +} + +/** + * @brief Gets the set of out edges + * @param [in] node Node id. + * @returns Set of out edges + */ +template +inline nodeID_t* ARGraph::GetOutEdgeSet(nodeID_t node) { + return out[node].data(); +} + +/** + * @brief Gets the set of in edges + * @param [in] node Node id. + * @returns Set of in edges + */ +template +inline nodeID_t* ARGraph::GetInEdgeSet(nodeID_t node) { + return in[node].data(); +} + +/*------------------------------------------------------------------- + * Checks the existence of an edge, and returns its attribute + * using the parameter pattr. + * Note: uses binary search. + * Implem. note: Uses the out/out_attr vectors; this fact is + * exploited in the constructor to generate the + * in_attr vector + ------------------------------------------------------------------*/ +/** + * @brief Checks the existence of an edge, and returns its attribute. + * @note The method uses binary search. \n + * Uses the out/out_attr vectors; this fact is exploited in the + * constructor to generate the in_attr vector. + * @param [in] n1 Start node id. + * @param [in] n2 End node id. + * @param [out] pattr Attribute of the edge. + * @retval TRUE If the edge exists. + * @retval FALSE If the edge doesn't exist. + */ +template +bool ARGraph::HasEdge(nodeID_t n1, nodeID_t n2, Edge& pattr) const { + nodeID_t index; + if (GetNodeIndex(n1, n2, index)) { + pattr = out_attr[n1][index]; + return true; + } + return false; } -#endif -/* defined ARGRAPH_H */ +/** + * @brief Change the attribute of an edge. It is an error if the edge does not + * exist. + * @note The method uses binary search. + * @param [in] n1 Start node id. + * @param [in] n2 End node id. + * @param [in] pattr Attribute of the edge. + */ +template +void ARGraph::SetEdgeAttr(nodeID_t n1, nodeID_t n2, + Edge& new_attr) { + uint32_t c; + assert(n1 < n); + assert(n2 < n); + + if (GetNodeIndex(n1, n2, c)) out_attr[n1][c] = new_attr; + + if (GetNodeIndex(n2, n1, c)) in_attr[n2][c] = new_attr; +} + +/** + * @brief Applies the visitor to all the in edges of the node. + * @param [in] node Node id. + * @param [in] vis Edge Visitor. + * @param [in] param Generic param for the visitor. + */ +template +void ARGraph::VisitInEdges(nodeID_t node, edge_visitor vis, + param_type param) { + assert(node < n); + size_t i; + for (i = 0; i < in[node].size(); i++) + vis(this, in[node][i], node, in_attr[node][i], param); +} +/** + * @brief Applies the visitor to all the out edges of the node. + * @param [in] node Node id. + * @param [in] vis Edge Visitor. + * @param [in] param Generic param for the visitor. + */ +template +void ARGraph::VisitOutEdges(nodeID_t node, edge_visitor vis, + param_type param) { + assert(node < n); + size_t i; + for (i = 0; i < out[node].size(); i++) + vis(this, node, out[node][i], out_attr[node][i], param); +} + +/** + * @brief Applies the visitor to all the edges of the node. + * @param [in] node Node id. + * @param [in] vis Edge Visitor. + * @param [in] param Generic param for the visitor. + */ +template +void ARGraph::VisitEdges(nodeID_t node, edge_visitor vis, + param_type param) { + VisitInEdges(node, vis, param); + VisitOutEdges(node, vis, param); +} + +/** + * @brief Constructs the graph form a loader. + * @param loader ARGLoader + */ +template +ARGraph::ARGraph(ARGLoader* loader) { + n = loader->NodeCount(); + attr.resize(n); + in.resize(n); + in_attr.resize(n); + out.resize(n); + out_attr.resize(n); + + e_count = 0; + e_out_count = 0; + e_in_count = 0; + n_attr_count = 0; + e_attr_count = 0; + std::map attributemap; + std::map e_attributemap; + + max_deg_in = max_deg_out = max_degree = 0; + + std::vector > revmap; + typename std::map::iterator rvit; + revmap.resize(n); + + uint32_t i, j; + for (i = 0; i < n; i++) { + Node attribute = loader->GetNodeAttr(i); + attr[i] = (attribute); + + if (!attributemap.count(attribute)) { + attributemap[attribute] = true; + n_attr_count++; + } + } + + for (i = 0; i < n; i++) { + uint32_t k = loader->OutEdgeCount(i); + e_out_count += k; + + if (k > max_deg_out) max_deg_out = k; + out[i].resize(k); + out_attr[i].resize(k); + + for (j = 0; j < k; j++) { + nodeID_t n2 = loader->GetOutEdge(i, j, &out_attr[i][j]); + out[i][j] = n2; + revmap[n2][i] = out_attr[i][j]; + } + } + + for (i = 0; i < n; i++) { + uint32_t k = revmap[i].size(); + e_in_count += k; + + if (k > max_deg_in) max_deg_in = k; + + in[i].resize(k); + in_attr[i].resize(k); + + for (j = 0, rvit = revmap[i].begin(); j < k; j++, rvit++) { + in[i][j] = rvit->first; + Edge edge_attr = rvit->second; + in_attr[i][j] = edge_attr; + if (!e_attributemap.count(edge_attr)) { + e_attributemap[edge_attr] = true; + e_attr_count++; + } + } + } + + for (i = 0; i < n; i++) { + uint32_t count = in[i].size() + out[i].size(); + e_count += count; + if (count > max_degree) { + max_degree = count; + } + } +} + +} // namespace vflib +#endif +/* defined ARGRAPH_H */ diff --git a/include/Options.hpp b/include/Options.hpp index 7d1b702..9f76bea 100644 --- a/include/Options.hpp +++ b/include/Options.hpp @@ -5,179 +5,169 @@ #include #endif -#include #include + +#include #include + #include "VFLib.h" -#define VF3PGSS (1) -#define VF3PWLS (2) +#define VF3PGSS (1) +#define VF3PWLS (2) -struct OptionStructure -{ - char *pattern; - char *target; - bool undirected; - bool storeSolutions; +struct OptionStructure { + char *pattern; + char *target; + bool undirected; + bool storeSolutions; #ifdef VF3P - int8_t algo; - int16_t cpu; - int16_t numOfThreads; - bool lockFree; - int16_t ssrHighLimit; - int16_t ssrLocalStackLimit; + int8_t algo; + int16_t cpu; + int16_t numOfThreads; + bool lockFree; + int16_t ssrHighLimit; + int16_t ssrLocalStackLimit; #endif - bool verbose; - std::string format; - float repetitionTimeLimit; - - OptionStructure(): - pattern(nullptr), - target(nullptr), - undirected(false), - storeSolutions(false), + bool verbose; + std::string format; + float repetitionTimeLimit; + + OptionStructure() + : pattern(nullptr), + target(nullptr), + undirected(false), + storeSolutions(false), #ifdef VF3P - algo(1), - cpu(-1), - numOfThreads(1), - lockFree(0), - ssrHighLimit(3), - ssrLocalStackLimit(10), + algo(1), + cpu(-1), + numOfThreads(1), + lockFree(0), + ssrHighLimit(3), + ssrLocalStackLimit(10), #endif - verbose(0), - format("vf"), - repetitionTimeLimit(1){} + verbose(0), + format("vf"), + repetitionTimeLimit(1) { + } }; typedef OptionStructure Options; - -void PrintUsage() -{ - std::string outstring = "vf3 [pattern] [target] "; +void PrintUsage() { + std::string outstring = "vf3 [pattern] [target] "; #ifdef VF3P - outstring += "-c [start cpu] -t [# of threads] -a [version id] -h [SSR high limit] -l [local stack limit] -k "; + outstring += + "-c [start cpu] -t [# of threads] -a [version id] -h [SSR high limit] -l " + "[local stack limit] -k "; #endif - outstring += "-u -s -f [graph format]"; - std::cout< -vflib::ARGLoader* CreateLoader(const Options& opt, std::istream &in) -{ - - if(opt.format == "vf") - { - return new vflib::FastStreamARGLoader(in, opt.undirected); +template +vflib::ARGLoader *CreateLoader(const Options &opt, + std::istream &in) { + if (opt.format == "vf") { + return new vflib::FastStreamARGLoader(in, opt.undirected); + } else if (opt.format == "edge") { + return new vflib::EdgeStreamARGLoader(in, opt.undirected); + } else { + return nullptr; } - else if(opt.format == "edge") - { - return new vflib::EdgeStreamARGLoader(in, opt.undirected); - } - else - { - return nullptr; - } } -vflib::MatchingEngine* CreateMatchingEngine(const Options& opt) -{ +vflib::MatchingEngine *CreateMatchingEngine(const Options &opt) { #ifdef VF3P - switch(opt.algo) - { - case VF3PGSS: - return new vflib::ParallelMatchingEngine(opt.numOfThreads, opt.storeSolutions, opt.lockFree, opt.cpu); - case VF3PWLS: - return new vflib::ParallelMatchingEngineWLS(opt.numOfThreads, opt.storeSolutions, opt.lockFree, - opt.cpu, opt.ssrHighLimit, opt.ssrLocalStackLimit); - default: - std::cout<<"Wrong Algorithm Selected\n"; - std::cout<<"1: VF3P with GSS Only\n"; - std::cout<<"2: VF3P with Local Stack and limited depth\n"; - return nullptr; - } + switch (opt.algo) { + case VF3PGSS: + return new vflib::ParallelMatchingEngine( + opt.numOfThreads, opt.storeSolutions, opt.lockFree, opt.cpu); + case VF3PWLS: + return new vflib::ParallelMatchingEngineWLS( + opt.numOfThreads, opt.storeSolutions, opt.lockFree, opt.cpu, + opt.ssrHighLimit, opt.ssrLocalStackLimit); + default: + std::cout << "Wrong Algorithm Selected\n"; + std::cout << "1: VF3P with GSS Only\n"; + std::cout << "2: VF3P with Local Stack and limited depth\n"; + return nullptr; + } #elif defined(VF3) || defined(VF3L) - return new vflib::MatchingEngine(opt.storeSolutions); + return new vflib::MatchingEngine(opt.storeSolutions); #endif } diff --git a/include/VFLib.h b/include/VFLib.h index d9078fa..c85dd50 100644 --- a/include/VFLib.h +++ b/include/VFLib.h @@ -1,19 +1,18 @@ #ifndef VFLIB_H #define VFLIB_H -#include "loaders/ARGLoader.hpp" -#include "loaders/FastStreamARGLoader.hpp" -#include "loaders/EdgeStreamARGLoader.hpp" #include "ARGraph.hpp" +#include "FastCheck.hpp" +#include "MatchingEngine.hpp" +#include "NodeClassifier.hpp" #include "NodeSorter.hpp" -#include "VF3NodeSorter.hpp" +#include "ProbabilityStrategy.hpp" #include "RINodeSorter.hpp" -#include "FastCheck.hpp" #include "State.hpp" -#include "ProbabilityStrategy.hpp" -#include "NodeClassifier.hpp" -#include "MatchingEngine.hpp" - +#include "VF3NodeSorter.hpp" +#include "loaders/ARGLoader.hpp" +#include "loaders/EdgeStreamARGLoader.hpp" +#include "loaders/FastStreamARGLoader.hpp" #ifndef VF3BIO typedef int32_t data_t; @@ -26,12 +25,15 @@ typedef std::string data_t; typedef vflib::VF3SubState state_t; #elif defined(VF3L) #include "VF3LightSubState.hpp" -typedef vflib::VF3LightSubState state_t; +typedef vflib::VF3LightSubState + state_t; #elif defined(VF3P) +#include "parallel/CloneableVF3ParallelSubState.hpp" #include "parallel/ParallelMatchingEngine.hpp" #include "parallel/ParallelMatchingEngineWLS.hpp" -#include "parallel/CloneableVF3ParallelSubState.hpp" -typedef vflib::CloneableVF3ParallelSubState state_t; +typedef vflib::CloneableVF3ParallelSubState + state_t; #endif #endif /* VFLIB_H*/ diff --git a/include/loaders/EdgeStreamARGLoader.hpp b/include/loaders/EdgeStreamARGLoader.hpp index 5629d1c..8ffb59d 100644 --- a/include/loaders/EdgeStreamARGLoader.hpp +++ b/include/loaders/EdgeStreamARGLoader.hpp @@ -12,162 +12,142 @@ #ifndef EDGESTREAMARGLOADER_HPP #define EDGESTREAMARGLOADER_HPP +#include #include -#include #include - -#include +#include #include "ARGraph.hpp" namespace vflib { template -class EdgeStreamARGLoader: public ARGLoader { - public: - /** - * @brief Reads the graph data from a text istream - * @param in The input stream - * @param undirected If true, the graph is undirected - * @param remove_isolated_nodes If true, the nodes that - * have no edges are removed from the graph - */ - EdgeStreamARGLoader(std::istream &in, bool undirected=false, - bool remove_isolated_nodes=true); - virtual uint32_t NodeCount() const; - virtual Node GetNodeAttr(nodeID_t node); - virtual uint32_t OutEdgeCount(nodeID_t node) const; - virtual nodeID_t GetOutEdge(nodeID_t node, uint32_t i, Edge *pattr); - void SetNodeAttribute(Node attr) { node_attribute=attr; } - void SetEdgeAttribute(Edge attr) { edge_attribute=attr; } - - private: - Node node_attribute; - Edge edge_attribute; - uint32_t node_count; - std::vector forward, backward; - std::vector< std::map > edges; - typename std::map::iterator edge_iterator; - nodeID_t last_edge_node; - uint32_t last_edge_index; - void skipHeading(std::istream &in); +class EdgeStreamARGLoader : public ARGLoader { + public: + /** + * @brief Reads the graph data from a text istream + * @param in The input stream + * @param undirected If true, the graph is undirected + * @param remove_isolated_nodes If true, the nodes that + * have no edges are removed from the graph + */ + EdgeStreamARGLoader(std::istream &in, bool undirected = false, + bool remove_isolated_nodes = true); + virtual uint32_t NodeCount() const; + virtual Node GetNodeAttr(nodeID_t node); + virtual uint32_t OutEdgeCount(nodeID_t node) const; + virtual nodeID_t GetOutEdge(nodeID_t node, uint32_t i, Edge *pattr); + void SetNodeAttribute(Node attr) { node_attribute = attr; } + void SetEdgeAttribute(Edge attr) { edge_attribute = attr; } + + private: + Node node_attribute; + Edge edge_attribute; + uint32_t node_count; + std::vector forward, backward; + std::vector > edges; + typename std::map::iterator edge_iterator; + nodeID_t last_edge_node; + uint32_t last_edge_index; + void skipHeading(std::istream &in); }; - - template -EdgeStreamARGLoader -::EdgeStreamARGLoader(std::istream &in, bool undirected, - bool remove_isolated_nodes) { - last_edge_node = NULL_NODE; - uint32_t count=0; - - if (!in.good()) - error("End of file or reading error"); - - skipHeading(in); - nodeID_t n1, n2; - while (true) { - in >> n1 >> n2; - n1--; - n2--; - if (!in.good()) - break; - if (n1 == n2) - error("File format error. Self edges are not allowed!", n1, n2); - if (n1>=count) - count = n1+1; - if (n2>=count) - count = n2+1; - edges.resize(count); - forward.resize(count, 0); - forward[n1]=1; - forward[n2]=1; - edges[n1][n2] = edge_attribute; - if (undirected) - edges[n2][n1] = edge_attribute; +EdgeStreamARGLoader::EdgeStreamARGLoader( + std::istream &in, bool undirected, bool remove_isolated_nodes) { + last_edge_node = NULL_NODE; + uint32_t count = 0; + + if (!in.good()) error("End of file or reading error"); + + skipHeading(in); + nodeID_t n1, n2; + while (true) { + in >> n1 >> n2; + n1--; + n2--; + if (!in.good()) break; + if (n1 == n2) + error("File format error. Self edges are not allowed!", n1, n2); + if (n1 >= count) count = n1 + 1; + if (n2 >= count) count = n2 + 1; + edges.resize(count); + forward.resize(count, 0); + forward[n1] = 1; + forward[n2] = 1; + edges[n1][n2] = edge_attribute; + if (undirected) edges[n2][n1] = edge_attribute; + } + + if (remove_isolated_nodes) { + backward.reserve(count); + node_count = 0; + for (uint32_t i = 0; i < count; i++) { + if (forward[i] > 0) { + forward[i] = node_count++; + backward.push_back(i); + } } - - if (remove_isolated_nodes) { - backward.reserve(count); - node_count=0; - for(uint32_t i=0; i0) { - forward[i]=node_count ++; - backward.push_back(i); - } - } - } else { - node_count=count; - backward.resize(count); - for(uint32_t i=0; i -uint32_t -EdgeStreamARGLoader -::NodeCount() const { - return node_count; +uint32_t EdgeStreamARGLoader::NodeCount() const { + return node_count; } template -Node -EdgeStreamARGLoader -::GetNodeAttr(nodeID_t node) { - return node_attribute; +Node EdgeStreamARGLoader::GetNodeAttr(nodeID_t node) { + return node_attribute; } template -uint32_t -EdgeStreamARGLoader -::OutEdgeCount(nodeID_t node) const { - return edges[backward[node]].size(); +uint32_t EdgeStreamARGLoader::OutEdgeCount(nodeID_t node) const { + return edges[backward[node]].size(); } template -nodeID_t -EdgeStreamARGLoader -::GetOutEdge(nodeID_t node, uint32_t i, Edge *pattr) { - assert (i i) { - edge_iterator --; - last_edge_index --; - } - - *pattr = edge_attribute; - return forward[edge_iterator->first]; +nodeID_t EdgeStreamARGLoader::GetOutEdge(nodeID_t node, uint32_t i, + Edge *pattr) { + assert(i < OutEdgeCount(node)); + + if (node != last_edge_node) { + last_edge_node = node; + edge_iterator = edges[backward[node]].begin(); + last_edge_index = 0; + } + while (last_edge_index < i) { + edge_iterator++; + last_edge_index++; + } + + while (last_edge_index > i) { + edge_iterator--; + last_edge_index--; + } + + *pattr = edge_attribute; + return forward[edge_iterator->first]; } - template -void -EdgeStreamARGLoader -::skipHeading(std::istream & in) { - const int maxline=256*1024; - int c=in.peek(); - while (c!=EOF && (isspace(c) || c=='#')) { - in.get(); - if (c=='#') - in.ignore(maxline, '\n'); - c=in.peek(); - } +void EdgeStreamARGLoader::skipHeading(std::istream &in) { + const int maxline = 256 * 1024; + int c = in.peek(); + while (c != EOF && (isspace(c) || c == '#')) { + in.get(); + if (c == '#') in.ignore(maxline, '\n'); + c = in.peek(); + } } -} // End namespace vflib +} // End namespace vflib #endif diff --git a/include/loaders/FastStreamARGLoader.hpp b/include/loaders/FastStreamARGLoader.hpp index a725185..8ba51c3 100644 --- a/include/loaders/FastStreamARGLoader.hpp +++ b/include/loaders/FastStreamARGLoader.hpp @@ -9,121 +9,106 @@ #ifndef FASTSTREAMARGLOADER_HPP #define FASTSTREAMARGLOADER_HPP +#include #include -#include #include - -#include +#include #include "ARGraph.hpp" namespace vflib { template -class FastStreamARGLoader: public ARGLoader { - public: - /** - * @brief Reads the graph data from a text istream - * @param in The input stream - * @param undirected If true, the graph is undirected - */ - FastStreamARGLoader(std::istream &in, bool undirected=false); - virtual uint32_t NodeCount() const; - virtual Node GetNodeAttr(nodeID_t node); - virtual uint32_t OutEdgeCount(nodeID_t node) const; - virtual nodeID_t GetOutEdge(nodeID_t node, uint32_t i, Edge *pattr); - - private: - uint32_t node_count; - std::vector nodes; - std::vector< std::map > edges; - typename std::map::iterator edge_iterator; - nodeID_t last_edge_node; - uint32_t last_edge_index; +class FastStreamARGLoader : public ARGLoader { + public: + /** + * @brief Reads the graph data from a text istream + * @param in The input stream + * @param undirected If true, the graph is undirected + */ + FastStreamARGLoader(std::istream &in, bool undirected = false); + virtual uint32_t NodeCount() const; + virtual Node GetNodeAttr(nodeID_t node); + virtual uint32_t OutEdgeCount(nodeID_t node) const; + virtual nodeID_t GetOutEdge(nodeID_t node, uint32_t i, Edge *pattr); + + private: + uint32_t node_count; + std::vector nodes; + std::vector > edges; + typename std::map::iterator edge_iterator; + nodeID_t last_edge_node; + uint32_t last_edge_index; }; - - template -FastStreamARGLoader -::FastStreamARGLoader(std::istream &in, bool undirected) { - last_edge_node = NULL_NODE; - - if (!in.good()) - error("End of file or reading error"); - - in >> node_count; - nodes.resize(node_count); - edges.resize(node_count); - uint32_t edge_count; - nodeID_t i, j, n1, n2; - for(i=0; i> n1 >> nodes[i]; - if (n1 != i) - error("Error in file format reading node", n1); - } - - for(i=0; i> edge_count; - for(j=0; j> n1 >> n2; - if (n1 != i || n2 >= node_count || n1==n2) - error("Error in file format reading edge", n1, n2); - in >> edges[n1][n2]; - if (undirected) - edges[n2][n1] = edges[n1][n2]; - } +FastStreamARGLoader::FastStreamARGLoader(std::istream &in, + bool undirected) { + last_edge_node = NULL_NODE; + + if (!in.good()) error("End of file or reading error"); + + in >> node_count; + nodes.resize(node_count); + edges.resize(node_count); + uint32_t edge_count; + nodeID_t i, j, n1, n2; + for (i = 0; i < node_count; i++) { + in >> n1 >> nodes[i]; + if (n1 != i) error("Error in file format reading node", n1); + } + + for (i = 0; i < node_count; i++) { + in >> edge_count; + for (j = 0; j < edge_count; j++) { + in >> n1 >> n2; + if (n1 != i || n2 >= node_count || n1 == n2) + error("Error in file format reading edge", n1, n2); + in >> edges[n1][n2]; + if (undirected) edges[n2][n1] = edges[n1][n2]; } + } } template -uint32_t -FastStreamARGLoader -::NodeCount() const { - return node_count; +uint32_t FastStreamARGLoader::NodeCount() const { + return node_count; } template -Node -FastStreamARGLoader -::GetNodeAttr(nodeID_t node) { - return nodes[node]; +Node FastStreamARGLoader::GetNodeAttr(nodeID_t node) { + return nodes[node]; } template -uint32_t -FastStreamARGLoader -::OutEdgeCount(nodeID_t node) const { - return edges[node].size(); +uint32_t FastStreamARGLoader::OutEdgeCount(nodeID_t node) const { + return edges[node].size(); } template -nodeID_t -FastStreamARGLoader -::GetOutEdge(nodeID_t node, uint32_t i, Edge *pattr) { - assert (i i) { - edge_iterator --; - last_edge_index --; - } - - *pattr = edge_iterator->second; - return edge_iterator->first; +nodeID_t FastStreamARGLoader::GetOutEdge(nodeID_t node, uint32_t i, + Edge *pattr) { + assert(i < OutEdgeCount(node)); + + if (node != last_edge_node) { + last_edge_node = node; + edge_iterator = edges[node].begin(); + last_edge_index = 0; + } + while (last_edge_index < i) { + edge_iterator++; + last_edge_index++; + } + + while (last_edge_index > i) { + edge_iterator--; + last_edge_index--; + } + + *pattr = edge_iterator->second; + return edge_iterator->first; } - - -} // End namespace vflib +} // End namespace vflib #endif diff --git a/main.cpp b/main.cpp index 2e7038d..fc7a87e 100644 --- a/main.cpp +++ b/main.cpp @@ -1,233 +1,227 @@ #include -#include -#include #include -#include #include + #include +#include +#include +#include #ifndef WIN32 -#include -#include -#include -#include #include +#include +#include +#include + +#include #else #include #include #endif -#include "WindowsTime.h" -#include "VFLib.h" #include "Options.hpp" +#include "VFLib.h" +#include "WindowsTime.h" using namespace vflib; #ifndef WIN32 void sig_handler(int sig) { - switch (sig) { - case SIGKILL: - std::cout << "Killed \n"; - exit(-1); - case SIGABRT: - std::cout << "Aborted \n"; - exit(-1); - case SIGTERM: - std::cout << "Terminated \n"; - exit(-1); - case SIGSEGV: - std::cout << "Segmentation fault \n"; - exit(-1); - case SIGSTOP: - std::cout << "Stopped \n"; - exit(-1); - case SIGCHLD: - std::cout << "Child stopped or terminated \n"; - exit(-1); - default: - std::cout << "Unexpected signal " << sig <<"\n"; - exit(-1); - } + switch (sig) { + case SIGKILL: + std::cout << "Killed \n"; + exit(-1); + case SIGABRT: + std::cout << "Aborted \n"; + exit(-1); + case SIGTERM: + std::cout << "Terminated \n"; + exit(-1); + case SIGSEGV: + std::cout << "Segmentation fault \n"; + exit(-1); + case SIGSTOP: + std::cout << "Stopped \n"; + exit(-1); + case SIGCHLD: + std::cout << "Child stopped or terminated \n"; + exit(-1); + default: + std::cout << "Unexpected signal " << sig << "\n"; + exit(-1); + } } #endif #ifdef TRACE std::string& remove_chars(std::string& s, const std::string& chars) { - s.erase(remove_if(s.begin(), s.end(), [&chars](const char& c) { - return chars.find(c) != std::string::npos; - }), s.end()); - return s; + s.erase(remove_if(s.begin(), s.end(), + [&chars](const char& c) { + return chars.find(c) != std::string::npos; + }), + s.end()); + return s; } #endif static long long state_counter = 0; -int32_t main(int32_t argc, char** argv) -{ - Options opt; - - uint32_t n1, n2; - double timeAll = 0; - double totalExecTime= 0; - double timeFirst = 0; - double timeLast = 0; - double timeLoad = 0; - int rep = 0; - struct timeval start, loading, fastcheck, classification, iter, end; - std::vector solutions; - std::vector class_patt; - std::vector class_targ; - uint32_t classes_count; - - state_counter = 0; - size_t sols = 0; +int32_t main(int32_t argc, char** argv) { + Options opt; + + uint32_t n1, n2; + double timeAll = 0; + double totalExecTime = 0; + double timeFirst = 0; + double timeLast = 0; + double timeLoad = 0; + int rep = 0; + struct timeval start, loading, fastcheck, classification, iter, end; + std::vector solutions; + std::vector class_patt; + std::vector class_targ; + uint32_t classes_count; + + state_counter = 0; + size_t sols = 0; #ifndef WIN32 - std::signal(SIGKILL, sig_handler); - std::signal(SIGABRT, sig_handler); - std::signal(SIGTERM, sig_handler); - std::signal(SIGSEGV, sig_handler); - std::signal(SIGSTOP, sig_handler); - std::signal(SIGCHLD, sig_handler); + std::signal(SIGKILL, sig_handler); + std::signal(SIGABRT, sig_handler); + std::signal(SIGTERM, sig_handler); + std::signal(SIGSEGV, sig_handler); + std::signal(SIGSTOP, sig_handler); + std::signal(SIGCHLD, sig_handler); #endif - if(!GetOptions(opt, argc, argv)) - { - exit(-1); - } + if (!GetOptions(opt, argc, argv)) { + exit(-1); + } #ifdef TRACE - int status; - std::string pattern_name(opt.pattern); - std::string target_name(opt.target); + int status; + std::string pattern_name(opt.pattern); + std::string target_name(opt.target); + + pattern_name = pattern_name.substr(pattern_name.find_last_of("/\\") + 1); + target_name = target_name.substr(target_name.find_last_of("/\\") + 1); + + pattern_name = remove_chars(pattern_name, "./"); + target_name = remove_chars(target_name, "./"); - pattern_name = pattern_name.substr(pattern_name.find_last_of("/\\") + 1); - target_name = target_name.substr(target_name.find_last_of("/\\") + 1); + std::string outpath(argv[3]); - pattern_name = remove_chars(pattern_name, "./"); - target_name = remove_chars(target_name, "./"); + // mkdir -p foo/bar/zoo/andsoforth + status = mkdir(outpath.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); + // std::cout<* pattloader = + CreateLoader(opt, graphInPat); + ARGLoader* targloader = + CreateLoader(opt, graphInTarg); + + ARGraph patt_graph(pattloader); + ARGraph targ_graph(targloader); + + if (opt.verbose) { + gettimeofday(&loading, NULL); + timeLoad = GetElapsedTime(start, loading); + std::cout << "Loaded in: " << timeLoad << std::endl; + } + + n1 = patt_graph.NodeCount(); + n2 = targ_graph.NodeCount(); + + MatchingEngine* me = CreateMatchingEngine(opt); + + if (!me) { + exit(-1); + } + + gettimeofday(&start, NULL); + FastCheck check(&patt_graph, &targ_graph); + if (check.CheckSubgraphIsomorphism()) { + if (opt.verbose) { + gettimeofday(&fastcheck, NULL); + timeLoad = GetElapsedTime(start, fastcheck); + std::cout << "FastCheck in: " << timeLoad << std::endl; + } + + gettimeofday(&start, NULL); + NodeClassifier classifier(&targ_graph); + NodeClassifier classifier2(&patt_graph, classifier); + class_patt = classifier2.GetClasses(); + class_targ = classifier.GetClasses(); + classes_count = classifier.CountClasses(); + + if (opt.verbose) { + gettimeofday(&classification, NULL); + timeLoad = GetElapsedTime(start, classification); + std::cout << "Classification in: " << timeLoad << std::endl; + } + } + +#ifndef TRACE + do { + rep++; + me->ResetSolutionCounter(); + + gettimeofday(&iter, NULL); +#endif + if (check.CheckSubgraphIsomorphism()) { + VF3NodeSorter > + sorter(&targ_graph); + std::vector sorted = sorter.SortNodes(&patt_graph); - //mkdir -p foo/bar/zoo/andsoforth - status = mkdir(outpath.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); - //std::cout<InitTrace(outfilename); #endif - gettimeofday(&start, NULL); - - std::ifstream graphInPat(opt.pattern); - std::ifstream graphInTarg(opt.target); - - ARGLoader* pattloader = CreateLoader(opt, graphInPat); - ARGLoader* targloader = CreateLoader(opt, graphInTarg); - - ARGraph patt_graph(pattloader); - ARGraph targ_graph(targloader); - - if(opt.verbose) - { - gettimeofday(&loading, NULL); - timeLoad = GetElapsedTime(start, loading); - std::cout<<"Loaded in: "<* me = CreateMatchingEngine(opt); - - if(!me) - { - exit(-1); - } - - gettimeofday(&start, NULL); - FastCheck check(&patt_graph, &targ_graph); - if(check.CheckSubgraphIsomorphism()) - { - if(opt.verbose) - { - gettimeofday(&fastcheck, NULL); - timeLoad = GetElapsedTime(start, fastcheck); - std::cout<<"FastCheck in: "< classifier(&targ_graph); - NodeClassifier classifier2(&patt_graph, classifier); - class_patt = classifier2.GetClasses(); - class_targ = classifier.GetClasses(); - classes_count = classifier.CountClasses(); - - if(opt.verbose) - { - gettimeofday(&classification, NULL); - timeLoad = GetElapsedTime(start, classification); - std::cout<<"Classification in: "<ResetSolutionCounter(); - - gettimeofday(&iter, NULL); - #endif - if(check.CheckSubgraphIsomorphism()) - { - VF3NodeSorter > sorter(&targ_graph); - std::vector sorted = sorter.SortNodes(&patt_graph); - - #ifdef TRACE - me->InitTrace(outfilename); - #endif - - state_t s0(&patt_graph, &targ_graph, class_patt.data(), class_targ.data(), classes_count, sorted.data()); - me->FindAllMatchings(s0); - #ifdef TRACE - me->FlushTrace(); - #endif - - } - - #ifndef TRACE - gettimeofday(&end,NULL); - - totalExecTime += GetElapsedTime(iter, end); - end = me->GetFirstSolutionTime(); - timeFirst += GetElapsedTime(iter, end); - } while (totalExecTime < opt.repetitionTimeLimit); - timeAll = totalExecTime/rep; - timeFirst /= rep; - - if(opt.storeSolutions) - { - me->GetSolutions(solutions); - std::cout << "Solution Found" << std::endl; - std::vector::iterator it; - for(it = solutions.begin(); it != solutions.end(); it++) - { - std::cout<< me->SolutionToString(*it) << std::endl; - } - } - - #endif - sols = me->GetSolutionsCount(); - if(opt.verbose) - { - std::cout<<"First Solution in: "<FindAllMatchings(s0); +#ifdef TRACE + me->FlushTrace(); +#endif + } + +#ifndef TRACE + gettimeofday(&end, NULL); + + totalExecTime += GetElapsedTime(iter, end); + end = me->GetFirstSolutionTime(); + timeFirst += GetElapsedTime(iter, end); + } while (totalExecTime < opt.repetitionTimeLimit); + timeAll = totalExecTime / rep; + timeFirst /= rep; + + if (opt.storeSolutions) { + me->GetSolutions(solutions); + std::cout << "Solution Found" << std::endl; + std::vector::iterator it; + for (it = solutions.begin(); it != solutions.end(); it++) { + std::cout << me->SolutionToString(*it) << std::endl; + } + } + +#endif + sols = me->GetSolutionsCount(); + if (opt.verbose) { + std::cout << "First Solution in: " << timeFirst << std::endl; + std::cout << "Matching Finished in: " << timeAll << std::endl; + std::cout << "Solutions: " << sols << std::endl; + } else { + std::cout << sols << " " << timeFirst << " " << timeAll << std::endl; + } + delete me; + delete pattloader; + delete targloader; + return 0; } From 89ef4490af399cf1d4a5f252d721be2317ec6bf1 Mon Sep 17 00:00:00 2001 From: Harsh Agrawal Date: Thu, 13 Oct 2022 17:49:10 +0530 Subject: [PATCH 2/3] Add support for edge labels - Created fresh template instances for Integer label types - Abstract out a solve template function to handle any data type for labels and states - Added an option `vfe` to parse the input file in VF format with integer edge labels. - Fix hardcoded datatypes in dataloaders. - Add command for compiling as a shared library in Makefile --- include/Options.hpp | 11 ++- include/VFLib.h | 11 ++- include/loaders/EdgeStreamARGLoader.hpp | 4 +- main.cpp | 124 +++++++++++++----------- 4 files changed, 85 insertions(+), 65 deletions(-) diff --git a/include/Options.hpp b/include/Options.hpp index 9f76bea..c0a57b4 100644 --- a/include/Options.hpp +++ b/include/Options.hpp @@ -141,7 +141,7 @@ bool GetOptions(Options &opt, int argc, char **argv) { template vflib::ARGLoader *CreateLoader(const Options &opt, std::istream &in) { - if (opt.format == "vf") { + if (opt.format == "vf" || opt.format == "vfe") { return new vflib::FastStreamARGLoader(in, opt.undirected); } else if (opt.format == "edge") { return new vflib::EdgeStreamARGLoader(in, opt.undirected); @@ -150,14 +150,15 @@ vflib::ARGLoader *CreateLoader(const Options &opt, } } -vflib::MatchingEngine *CreateMatchingEngine(const Options &opt) { +template +vflib::MatchingEngine *CreateMatchingEngine(const Options &opt) { #ifdef VF3P switch (opt.algo) { case VF3PGSS: - return new vflib::ParallelMatchingEngine( + return new vflib::ParallelMatchingEngine( opt.numOfThreads, opt.storeSolutions, opt.lockFree, opt.cpu); case VF3PWLS: - return new vflib::ParallelMatchingEngineWLS( + return new vflib::ParallelMatchingEngineWLS( opt.numOfThreads, opt.storeSolutions, opt.lockFree, opt.cpu, opt.ssrHighLimit, opt.ssrLocalStackLimit); default: @@ -167,7 +168,7 @@ vflib::MatchingEngine *CreateMatchingEngine(const Options &opt) { return nullptr; } #elif defined(VF3) || defined(VF3L) - return new vflib::MatchingEngine(opt.storeSolutions); + return new vflib::MatchingEngine(opt.storeSolutions); #endif } diff --git a/include/VFLib.h b/include/VFLib.h index c85dd50..8fcf396 100644 --- a/include/VFLib.h +++ b/include/VFLib.h @@ -22,17 +22,24 @@ typedef std::string data_t; #ifdef VF3 #include "VF3SubState.hpp" -typedef vflib::VF3SubState state_t; + +typedef vflib::VF3SubState + noedgelabel_state_t; +typedef vflib::VF3SubState state_t; #elif defined(VF3L) #include "VF3LightSubState.hpp" typedef vflib::VF3LightSubState - state_t; + noedgelabel_state_t; +typedef vflib::VF3LightSubState state_t; #elif defined(VF3P) #include "parallel/CloneableVF3ParallelSubState.hpp" #include "parallel/ParallelMatchingEngine.hpp" #include "parallel/ParallelMatchingEngineWLS.hpp" + typedef vflib::CloneableVF3ParallelSubState + noedgelabel_state_t; +typedef vflib::CloneableVF3ParallelSubState state_t; #endif diff --git a/include/loaders/EdgeStreamARGLoader.hpp b/include/loaders/EdgeStreamARGLoader.hpp index 8ffb59d..f917b8c 100644 --- a/include/loaders/EdgeStreamARGLoader.hpp +++ b/include/loaders/EdgeStreamARGLoader.hpp @@ -45,8 +45,8 @@ class EdgeStreamARGLoader : public ARGLoader { Edge edge_attribute; uint32_t node_count; std::vector forward, backward; - std::vector > edges; - typename std::map::iterator edge_iterator; + std::vector > edges; + typename std::map::iterator edge_iterator; nodeID_t last_edge_node; uint32_t last_edge_index; void skipHeading(std::istream &in); diff --git a/main.cpp b/main.cpp index fc7a87e..b96c8c7 100644 --- a/main.cpp +++ b/main.cpp @@ -65,9 +65,10 @@ std::string& remove_chars(std::string& s, const std::string& chars) { static long long state_counter = 0; -int32_t main(int32_t argc, char** argv) { - Options opt; - +template +void solve(Options& opt, std::istream& graphInPat, std::istream& graphInTarg, + struct timeval& start) { + struct timeval loading, fastcheck, classification, iter, end; uint32_t n1, n2; double timeAll = 0; double totalExecTime = 0; @@ -75,7 +76,6 @@ int32_t main(int32_t argc, char** argv) { double timeLast = 0; double timeLoad = 0; int rep = 0; - struct timeval start, loading, fastcheck, classification, iter, end; std::vector solutions; std::vector class_patt; std::vector class_targ; @@ -84,51 +84,12 @@ int32_t main(int32_t argc, char** argv) { state_counter = 0; size_t sols = 0; -#ifndef WIN32 - std::signal(SIGKILL, sig_handler); - std::signal(SIGABRT, sig_handler); - std::signal(SIGTERM, sig_handler); - std::signal(SIGSEGV, sig_handler); - std::signal(SIGSTOP, sig_handler); - std::signal(SIGCHLD, sig_handler); -#endif - - if (!GetOptions(opt, argc, argv)) { - exit(-1); - } - -#ifdef TRACE - int status; - std::string pattern_name(opt.pattern); - std::string target_name(opt.target); - - pattern_name = pattern_name.substr(pattern_name.find_last_of("/\\") + 1); - target_name = target_name.substr(target_name.find_last_of("/\\") + 1); - - pattern_name = remove_chars(pattern_name, "./"); - target_name = remove_chars(target_name, "./"); - - std::string outpath(argv[3]); - - // mkdir -p foo/bar/zoo/andsoforth - status = mkdir(outpath.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); - // std::cout<* pattloader = CreateLoader(opt, graphInPat); + ARGLoader* targloader = + CreateLoader(opt, graphInTarg); - std::ifstream graphInPat(opt.pattern); - std::ifstream graphInTarg(opt.target); - - ARGLoader* pattloader = - CreateLoader(opt, graphInPat); - ARGLoader* targloader = - CreateLoader(opt, graphInTarg); - - ARGraph patt_graph(pattloader); - ARGraph targ_graph(targloader); + ARGraph patt_graph(pattloader); + ARGraph targ_graph(targloader); if (opt.verbose) { gettimeofday(&loading, NULL); @@ -139,14 +100,14 @@ int32_t main(int32_t argc, char** argv) { n1 = patt_graph.NodeCount(); n2 = targ_graph.NodeCount(); - MatchingEngine* me = CreateMatchingEngine(opt); + MatchingEngine* me = CreateMatchingEngine(opt); if (!me) { exit(-1); } gettimeofday(&start, NULL); - FastCheck check(&patt_graph, &targ_graph); + FastCheck check(&patt_graph, &targ_graph); if (check.CheckSubgraphIsomorphism()) { if (opt.verbose) { gettimeofday(&fastcheck, NULL); @@ -155,8 +116,8 @@ int32_t main(int32_t argc, char** argv) { } gettimeofday(&start, NULL); - NodeClassifier classifier(&targ_graph); - NodeClassifier classifier2(&patt_graph, classifier); + NodeClassifier classifier(&targ_graph); + NodeClassifier classifier2(&patt_graph, classifier); class_patt = classifier2.GetClasses(); class_targ = classifier.GetClasses(); classes_count = classifier.CountClasses(); @@ -176,16 +137,16 @@ int32_t main(int32_t argc, char** argv) { gettimeofday(&iter, NULL); #endif if (check.CheckSubgraphIsomorphism()) { - VF3NodeSorter > - sorter(&targ_graph); + VF3NodeSorter > sorter( + &targ_graph); std::vector sorted = sorter.SortNodes(&patt_graph); #ifdef TRACE me->InitTrace(outfilename); #endif - state_t s0(&patt_graph, &targ_graph, class_patt.data(), class_targ.data(), - classes_count, sorted.data()); + StateType s0(&patt_graph, &targ_graph, class_patt.data(), + class_targ.data(), classes_count, sorted.data()); me->FindAllMatchings(s0); #ifdef TRACE me->FlushTrace(); @@ -217,11 +178,62 @@ int32_t main(int32_t argc, char** argv) { std::cout << "First Solution in: " << timeFirst << std::endl; std::cout << "Matching Finished in: " << timeAll << std::endl; std::cout << "Solutions: " << sols << std::endl; + } else { std::cout << sols << " " << timeFirst << " " << timeAll << std::endl; } delete me; delete pattloader; delete targloader; +} + +int32_t main(int32_t argc, char** argv) { + Options opt; + struct timeval start; + +#ifndef WIN32 + std::signal(SIGKILL, sig_handler); + std::signal(SIGABRT, sig_handler); + std::signal(SIGTERM, sig_handler); + std::signal(SIGSEGV, sig_handler); + std::signal(SIGSTOP, sig_handler); + std::signal(SIGCHLD, sig_handler); +#endif + + if (!GetOptions(opt, argc, argv)) { + exit(-1); + } + +#ifdef TRACE + int status; + std::string pattern_name(opt.pattern); + std::string target_name(opt.target); + + pattern_name = pattern_name.substr(pattern_name.find_last_of("/\\") + 1); + target_name = target_name.substr(target_name.find_last_of("/\\") + 1); + + pattern_name = remove_chars(pattern_name, "./"); + target_name = remove_chars(target_name, "./"); + + std::string outpath(argv[3]); + + // mkdir -p foo/bar/zoo/andsoforth + status = mkdir(outpath.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); + // std::cout<(opt, graphInPat, graphInTarg, start); + } else { + solve(opt, graphInPat, graphInTarg, + start); + } + return 0; } From d045dbe7774a233e5c1f1350a6412280ff040ec2 Mon Sep 17 00:00:00 2001 From: Harsh Agrawal Date: Thu, 13 Oct 2022 17:55:09 +0530 Subject: [PATCH 3/3] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 75394c2..4eb4d7c 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,7 @@ The following additional parameters can be added to the commandline: * -s Print all the solutions (not only the number of solutions found) (Default: false) * -f Loader file format. Using this parameter you can specify the format of the graphs to be loaded: (Default: vf) * vf: stanard VF file format. Commonl used by the MIVIA Graph datasets + * vfe: Same as VF but also supports edge labels * edge: Edge file format commonly used on VLDB datasets such as (Patents, WebGoogle, etc...) ### VF3P additional parameters