BB-Graph: A Subgraph Isomorphism Algorithm for Efficiently Querying Big Graph Databases
Extracted source text ยท arXiv 1706.06654
\documentclass[conference]{IEEEtran}
\usepackage{subfigure}
\usepackage{pgf}
\usepackage{tikz}
\usepackage{tabularx}
\newcolumntype{P}[1]{>{\centering\arraybackslash}b{#1}}
\usetikzlibrary{arrows,automata, positioning, shapes, decorations.pathreplacing}
\usepackage{array}
\usepackage{pbox}
\usepackage{amsmath}
\usepackage[ruled]{algorithm2e}
\usepackage{algcompatible}
\usepackage{floatrow}
% matching relationship principle (m.r.p.)
\newcommand\mrp{\mathrel{\overset{\makebox[0pt]{\mbox{\normalfont\tiny\sffamily m.r.p.}}}{\equiv}}}
% matching node principle (m.n.p.)
\newcommand\mnp{\mathrel{\overset{\makebox[0pt]{\mbox{\normalfont\tiny\sffamily m.n.p.}}}{\equiv}}}
\hyphenation{op-tical net-works semi-conduc-tor}
\begin{document}
\title{BB-Graph: A New Subgraph Isomorphism Algorithm for Efficiently Querying \\ Big Graph Databases}
\author{\IEEEauthorblockN{ Merve Asiler\IEEEauthorrefmark{1},
Adnan Yaz{\i}c{\i}\IEEEauthorrefmark{2}}
\IEEEauthorblockA{ Department of Computer Engineering\\
Middle East Technical University, Ankara, Turkey\\
\{\IEEEauthorrefmark{1}asiler, \IEEEauthorrefmark{2}yazici\}@ceng.metu.edu.tr}}
\maketitle
\begin{abstract}
With the emergence of the big data concept, the big graph database model has become very popular since it provides strong modeling for complex applications and fast querying, especially for the cases that require costly join operations in RDBMs. However, it is a big challenge to find all exact matches of a query graph in a big graph database, which is known as the subgraph isomorphism problem. Although a number of related studies exist in literature, there is need for a better algorithm that works efficiently for all types of queries since the subgraph isomorphism problem is NP-hard. The current subgraph isomorphism approaches have been built on Ullmann's idea of focusing on the strategy of pruning out the irrelevant candidates. Nevertheless, for some graph databases and queries, the existing pruning techniques are not adequate to handle some of the complex queries. Moreover, many of those existing algorithms need large indices that cause extra memory consumption. Motivated by these, we introduce a new subgraph isomorphism algorithm, namely BB-Graph, for querying big graph databases in an efficient manner without requiring a large data structure to be stored in main memory. We test and compare our proposed BB-Graph algorithm with two popular existing ones, GraphQL and Cypher of Neo4j. Our experiments are done on a very big graph database application (Population Database) and the publicly available World Cup graph database application. We show that our algorithm performs better than those that we use for comparison in this study, for most of the query types.
\end{abstract}
\IEEEpeerreviewmaketitle
\input{Sections/introduction.tex}
\input{Sections/literature.tex}
\input{Sections/algorithm.tex}
\input{Sections/experiments.tex}
\input{Sections/conclusion.tex}
% use section* for acknowledgment
\section*{Acknowledgment}
We like to present our thanks to KALE YAZILIM for sharing their resources, especially the real-world database, and giving the opportunity to work with them.
\bibliographystyle{IEEEtran}
\bibliography{references}
%\begin{thebibliography}{1}
%
%\bibitem{IEEEhowto:kopka}
%H.~Kopka and P.~W. Daly, \emph{A Guide to \LaTeX}, 3rd~ed.\hskip 1em plus
% 0.5em minus 0.4em\relax Harlow, England: Addison-Wesley, 1999.
%
%\end{thebibliography}
% that's all folks
\end{document}
% INTRODUCTION
\section{INTRODUCTION}
In the last decade, the big graph database models have widespreaded in a large variety of industry areas such as communications, logistics, Web/ISV, network management, social networks, mobile communication applications, data center management, bioinformatics, etc. The graph database model has recently been preferred to the other database models because it better fits into structure of complex and big data and provides higher performance than the others, especially RDBMs, for most cases \cite{vojtechkolomicenko2013}, \cite{batra2012comparative}, \cite{vicknair2010comparison}, \cite{bitninecompany2014}.
On the other hand, the subgraph isomorphism problem is one of the most frequently encountered challenges in big graph database applications. Subgraph isomorphism can be defined as follows: Given a query graph $Q$ and a database graph $G$, find all matching instances of $Q$ in $G$. To illustrate, in Figure \ref{fig:sample_query_database} there exist two instances of $Q$ in $G$, one is the subgraph consisting of the nodes $\nu_{0}$, $\nu_{1}$, $\nu_{3}$, $\nu_{4}$ and the relationships $_{\nu_{0}}e_{\nu_{1}}$, $_{\nu_{0}}e_{\nu_{3}}$, $_{\nu_{1}}e_{\nu_{3}}$, $_{\nu_{3}}e_{\nu_{4}}$ and the other one is the subgraph consisting of the nodes $\nu_{1}$, $\nu_{2}$, $\nu_{3}$, $\nu_{4}$ and the relationships $_{\nu_{1}}e_{\nu_{3}}$, $_{\nu_{2}}e_{\nu_{1}}$, $_{\nu_{2}}e_{\nu_{3}}$, $_{\nu_{3}}e_{\nu_{4}}$. The subgraph isomorphism problem is known as an NP-hard problem \cite{abboud2015subtree}. In almost all big graph database applications, there frequently occur queries directly or indirectly related to subgraph isomorphism problem; therefore, it is important to find an efficient solution for the subgraph isomorphism problem.
\input{Figures/sample_query_database.tex}
Most of the subgraph isomorphism algorithms in the literature are based on one of the following two types of strategies: Feature indexing by using \textit{filtering-and-verification} technique or candidate node checking by using \textit{branch-and-bound} technique. Algorithms of the first type create an index of small graphs (features) and filter the database pieces which do not have some (or all) of the features included by the query graph. They mark the ones which succesfully passed the filtering to include an exact match(es) of the query, and try to verify them with respect to whether they really do or not. GraphGrep \cite{giugno2002graphgrep}, GIndex \cite{yan2004graph}, Labeled Walk Index (LWI) \cite{srinivasa2005lwi}, Closure-Tree \cite{he2006closure}, Graph Decomposition Indexing \cite{williams2007graph}, TreePi \cite{zhang2007treepi}, TreeDelta \cite{zhao2007graph} are examples to this type of algorithms. Although those algorithms are good for decreasing the number of candidate data sets, they cannot deduce all the isomorphisms of query graph. Moreover, they are applicable only for the databases consisting of many disconnected graph pieces. On the other hand, algorithms of the second type aim to find all the exact matches of a query graph without making an issue that the database is connected or disconnected. Starting off from Ullmann's idea \cite{ullmann1976algorithm}, they extract all the candidates for each node in query and, incrementally, they match a query node with one of its candidates. In that way, they try to reach an exact match of query by branching the previous matches. VF2 \cite{cordella2004sub}, QuickSI \cite{shang2008taming}, GADDI \cite{zhang2009gaddi}, GraphQL \cite{he2008graphs}, SPath \cite{zhao2010graph} belong to this type of algorithms. The mentioned algorithms are good in terms of finding all the exact matches of query graph; nevertheless, since they search the candidates globally along the database, most of their tryouts to find a relationship between the nodes are redundant due to the fact that the nodes are irrelevant. Therefore, they have low computational performance. Additionally, in order to prune the nodes which cannot be a candidate, some of those algorithms need large data structures, which results in an extra amount of memory consumption.
Motivated by all of these mentioned above, we introduce a new \textit{branch-and-bound} algorithm combined with backtracking strategy for graph isomorphism problem, called BB-Graph. Our algorithm removes the drawbacks mentioned above by conducting the search of candidates for other query nodes locally in the close neighbourhood of the firstly-matched database node. The main contributions of this paper are as follows:
\begin{enumerate}
\item A new subgraph isomorphism algorithm, BB-Graph, is introduced. Contrary to the other existing algorithms, BB-Graph follows a more efficient search strategy while matching graph elements (nodes and relationships) by using \textit{branch-and-bound} technique combined with backtracking: It selects starting node candidates from all across the graph database and then, for each candidate isomorphism region potentially created by the starting node match, it selects the candidates of the other nodes locally by traversing every neighbour node and relationship. Later, it backtracks to check possible relationships and node combinations not handled previously.
\item BB-Graph uses the built-in data structures supplied by Neo4j. It does not consume extra memory for large indexing or data storing.
\item While many of other algorithms are experimented only on undirected graphs with hundreds of thousands of nodes by reading the input from a BLOB file, BB-Graph is tested and evaluated on a very big connected directed graph with almost 70 millions of nodes in addition to a directed graph with 45 thousands of nodes.
\item A number of experiments done for comparing our algorithm (BB-Graph) with Cypher and GraphQL show that BB-Graph has a better performance than these existing solutions for most of query types.
\end{enumerate}
Organization of the rest of this paper is as follows: Section \ref{sec:algorithm} introduces our BB-Graph approach and the main algorithms along with the pseudocodes of proposed solutions. Section \ref{sec:experimental.work} shows the experimental results and comparison of BB-Graph with Cypher and GraphQL. Lastly, the conclusion and feature work are given in Section \ref{sec:conclusion}.
\begin{figure} [!h]
\centering
\resizebox{0.8\textwidth}{!}{
\subfigure[query graph: $Q$]{
\begin{tikzpicture}
[->,>=stealth',shorten >=1pt,auto,node distance=1.5cm, semithick]
\tikzset{vertex/.style = {shape=circle,draw,minimum size=1.5em}}
\tikzset{edge/.style = {->}}
\node[vertex, label=right:$u_{2}$] (2) {$B$};
\node[vertex, label=$u_{0}$, above left of=2] (0) {$A$};
\node[vertex, label=$u_{1}$, above right of=2] (1) {$B$};
\node[vertex, label=right:$u_{3}$, below of=2] (3) {$D$};
\path
(0) edge (2)
(1) edge (0)
edge (2)
(2) edge (3);
\end{tikzpicture}}
\hfill
\subfigure[graph database: $G$]{
\begin{tikzpicture}
[->,>=stealth',shorten >=1pt,auto,node distance=1.5cm, semithick]
\tikzset{vertex/.style = {shape=circle,draw,minimum size=1.5em}}
\tikzset{edge/.style = {->}}
\node[vertex, label=$\nu_{0}$] (0) {$B$};
\node[vertex, label=$\nu_{3}$, below left of=0] (3) {$B$};
\node[vertex, label=$\nu_{1}$, above left of=3] (1) {$A$};
\node[vertex, label=below:$\nu_{2}$, below left of=3] at (-1.5,-0.5) (2) {$B$};
\node[vertex, label=left:$\nu_{4}$, below of=3] (4) {$D$};
\node[vertex, label=below:$\nu_{5}$, below of=0] (5) {$C$};
\node[vertex, label=$\nu_{7}$, below right of=0] (7) {$B$};
\node[vertex, label=$\nu_{6}$, above right of=7] (6) {$A$};
\node[vertex, label=right:$\nu_{8}$, below of=7] (8) {$D$};
\node[vertex, label=below:$\nu_{9}$, below right of=7] at (1.5, -0.5) (9) {$A$};
\path
(0) edge (1)
edge (3)
edge (5)
(1) edge (3)
(2) edge (1)
edge (3)
(3) edge (4)
(6) edge (0)
(7) edge (0)
edge (6)
edge (8)
edge (9);
\end{tikzpicture}}
\caption{An example query and a graph database with unlabeled relationships}}
\label{fig:sample_query_database}
\end{figure}
% LITERATURE SEARCH
\section{Related Work}
\label{sec:related.work}
GraphQL \cite{he2008graphs}, an algorithm for subgraph isomorphism problem, focuses on neigbourhood relations to filter candidates for a query node. If a query node $u$ can be matched with a database node $u'$, then for each query node $u_{k}$ in $k$-neighbourhood of $u$, there must be a candidate node $u_{k}'$ in $k$-neighbourhood of $u'$. Thus, GraphQL uses this fact to prune out false candidates of a query node, by scanning their $k$-neighbourhood upto a refinement level $L$, incrementally for each $k$ where $1 \leq k \leq L$. Also, GraphQL follows an optimized node matching strategy by selecting the query node which is estimated to decrease the cost at each intermediate step and adjacent to set of already matched nodes. GraphQL compares neighbourhoods of query nodes with their candidates' neighbourhoods and tries to find a semi-perfect bipartite matching between the nodes in corresponding neighbouhoods but our experiments showed that this is already an exhaustive computation even when the refinement level is set to 1 and not very effective for reducing the candidate set size of some query nodes.
In their study, Lee et al. \cite{lee2012depth} compare five subgraph isomorphism algorithms; VF2, QuickSI, GADDI, GraphQL, and SPath on some real-world data sets on iGraph framework \cite{han2010igraph}. They work on small and large undirected graphs consisting of one or many pieces by testing with subgraph, clique and path queries. The experiments that they conduct show that there is not a perfect algorithm which works for all types of database queries efficiently. For instance, while QuickSI shows a good performance in many cases, it fails to return the answer in a reasonable time for NASA dataset. According to the experimental results that they have obtained, GraphQL is the only algorithm succeeding to respond in a reasonable time for all tests. They state that these start-of-the-art algorithms may perform poorly because of their ineffective matching order and the imbalance between efficiency and overhead of their pruning methods.
Although each of five algorithms, VF2, QuickSI, GADDI, GraphQL, and SPath, has its own defect, there is a common point that causes all of these algorithms to perform poorly. All start searching by trying to find and filter candidate nodes for each query vertex. The pruning rules that they use are generally effective for eliminating the nodes that can never be a representative of the query node for which it is selected as a candidate in a real exact match. However, since they don't apply the prunings by regarding each isomorphism as an independent one, the nodes belonging to different isomorphisms cannot be discriminated until their relationships are checked in matching phase. Therefore, the database nodes which are candidate for different query vertices and members of distinct isomorphisms seem available for being members of the same isomorphism at first sight. Hence, the main time loss occurs at this point while searching for an actually non-existing reasonable connection between those irrelevant nodes. In order to remove this kind of possible cases, after the start node candidates are taken from all across the database, candidate nodes for the rest of the query vertices should be selected depending on the start node match. In other words, each start node candidate potentially creates a distinct isomorphism region; therefore, the representatives for the other query vertices should be locally chosen from the close neighbourhood of the start node for each distinct exact match.
% ALGORITHM
\section{BB-GRAPH ALGORITHM}
\label{sec:algorithm}
In this paper, the notation $G$ : $(V, E)$ represents the graph $G$ with the vertex set $V$ and edge set $E$. For vertex $\nu$; $L_{\nu}$ denotes the label set of $\nu$. Similarly, for edge $e$, $L_{e}$ denotes the label set of $e$. The notation $_{u}e_{\nu}$ is used for the edge $e$ starting from vertex $u$ (outgoing w.r.t. $u$) and ending at vertex $\nu$ (incoming w.r.t. $\nu$) when we need to state the end points of $e$. Otherwise, we just denote it as $e$.
For two graphs $G_{1}:(V_{1}, E_{1})$ and $G_{2}:(V_{2}, E_{2})$, $G_{1}$ is said to be \textit{subisomorphic} to $G_{2}$, if there is a one-to-one and onto function $f: V_{1} \longrightarrow V_{2}$ such that; $\forall \nu \in V_{1}$ $L_{\nu} \subseteq L_{f(\nu)}$ and for any $_{u}e_{\nu}$ $\in$ $E_{1}$ $_{f(u)}e_{f(\nu)}$ $\in$ $E_{2}$ satisfying that $L_{_{u}e_{\nu}} \subseteq L_{_{f(u)}e_{f(\nu)}}$. Given a query graph $Q$ and a data graph $G$, the problem of finding all distinct subisomorphisms of $Q$ in $G$ is called as \textit{Subgraph Isomorphism Problem}.
For two graphs $G_{1}:(V_{1}, E_{1})$ and $G_{2}:(V_{2}, E_{2})$, where $G_{1}$ is subisomorphic to $G_{2}$ under some isomorphism $f$, let $u \in V_{1}$ be matched with $u':=f(u) \in V_{2}$. Since each edge $e$ adjacent to $u$ must be matched with some edge $e'$ adjacent to $u'$, it follows that the degree of $u$ must be less than or equal to the degree of $u'$. Moreover, since the matched edges must have the same label and direction, for each group of edges having the same label and direction degree of $u$ must be also less than or equal to the degree of $u'$. As a result, the matching vertices in a subisomorphism must satisfy both label and degree rules deduced from the definition. In this paper, we call this as \textit{matching node principal} for the vertices to be matched \label{def:matchingnodeprincipal}. We denote $u \mnp u'$ when matching node principle holds for $u$ and $u'$. Similarly, if $e$ is matched with $e'$ under $f$, then it means $L{e} \subseteq L{e'}$ and direction of $e$ with respect to $u$ must be the same with direction of $e'$ with respect to $u'$. We call this as \textit{matching relationship principal} for the relationships to be matched and denote $e \mrp e'$\label{def:matchingrelationshipprincipal}.
Throughout the paper, we use the word \textit{relationship} instead of the \textit{edge} concept and the word \textit{node} instead of \textit{vertex} concept to make the contextual narrating compatible with Neo4j environment. Moreover, we denote the matching of query node $u$ with database node $u'$ by $<u, u'>$; similarly, the matching of query relationship $r$ with the database relationship $r'$ by $<r, r'>$.
\subsection{Algorithm Overview}
\label{subsec:overview}
BB-Graph first chooses a query node to start matching, which we call it the \textit{starting node}. Next, BB-Graph filters the database nodes to find candidates for the starting node. It does the filtering according to the \textit{matching node principal} previously mentioned in this Section. After getting the candidate nodes, BB-Graph puts them into a list to match the starting node with one candidate at a time and search for query graph isomorphisms rooting from that match. In order to achieve this, the whole candidate list is walked through a loop such that at each time of iteration the next candidate node is picked from the list, matched with the starting node and the recursive isomorphism search begins from that point, Algorithm \ref{alg:BB-Graph}, lines 1-12.
\input{Pseudocodes/bb_graph.tex}
In isomorphism search, BB-Graph uses the previously obtained node matches. Let $V_{matched}$ be the set of previously matched couples of nodes. Similarly, let $E_{matched}$ be the set of previously matched couples of relationships. For each node matching $<u,u'> \in V_{matched}$, where $u \in V_{Q}$ and $u' \in V_{G}$, BB-Graph applies the \textit{reciprocal node branching process}, that is, the process of expanding partially matched graph piece in order to complete to an exact match by following the adjacent relationships of $u$ and $u'$ simultaneously. In order to decide which node matching is used in reciprocal node branching process at that moment, all the node matchings are kept in a stack which we denote by $S$. When BB-Graph pops a node matching $<u,u'>$ from $S$, it applies the reciprocal node branching as follows: Firstly, it detects the non-matched relationships adjacent to query node $u$. Next, for each of those relationships, it tries to find candidates among the relationships adjacent to $u'$. While determining the candidates, it checks whether the \textit{matching relationship principal} (previously mentioned in this Section) holds or not. After filtering, there may appear more than one candidate for a relationship. BB-Graph collects all the candidates in a separate list for each non-matched relationship adjacent to $u$, Algorithm \ref{alg:branch_nodes}, lines 2-4. A case that there is no candidate for a relationship never occurs because we always match a query node $u$ with a database node $u'$ provided that $u'$ has a degree at least as $u$ has for each different group of relationships.
\input{Pseudocodes/branch_nodes.tex}
Assume that $r_{1}$, $r_{2}$, ...., and $r_{k}$ are the non-matched relationships adjacent to $u$ and $C_{r_{1}}$, $C_{r_{2}}$, .... and $C_{r_{k}}$ are the lists which contain corresponding candidate relationships adjacent to $u'$. In the next stage, BB-Graph picks a candidate relationship $r'_{i} \in C_{r_{i}}$ to match with $r_{i}$ iteratively for each $i$. At each step of iteration, it is checked whether the prospective match $<r_{i},r'_{i}>$ causes a conflict related with the relationship end points, or not. It can easily be seen that if two relationships are matched with each other, then their corresponding end points must also be matched with each other. Here, it is already known that $u$ and $u'$ had been matched before. Thus, BB-Graph has to check whether the other end points of $r_{i}$ and $r'_{i}$, say $\nu$ and $\nu'$, match, Algorithm \ref{alg:check}. It can be one of the following three cases: First, if $\nu$ and $\nu'$ are already matched with each other, then there is not any conflict. Second, if $\nu$ is matched with some node other than $\nu'$, or vice versa, it is reported as a conflict. Third, it may be the case that both $\nu$ and $\nu'$ are not-yet-matched nodes. At this point, it is checked whether the nodes satisfy the \textit{matching node principal}, or not. If they satisfy, then they are matched with each other and the new match $<v,v'>$ is added into $V_{matched}$ and pushed into $S$ to apply \textit{reciprocal node branching process} for them later. Otherwise, it is reported as a conflict. As a result, we guarantee that there does not occur an empty candidate list for any relationship in candidate filtering part. After checking the end points of relationships, if there does not exist any reported conflict, then the match $<r_{i}, r'_{i}>$ is approved and added into $E_{matched}$, and BB-Graph goes on the relationship matching procedure from the next iteration for $r_{i+1}$. During the checks, if there is a reported conflict, then the next candidate in $C_{r_{i}}$ is picked and the end point checks are repeated for the prospective matching of $r_{i}$ with its new candidate this time. Nevertheless, it may happen that all the candidate relationships for $r_{i}$ are tried but resulted in a problem. If such a case occurs, then it is understood that there are wrong decisions in the previous matchings, in fact. At this point, BB-Graph backtracks to the former relationship matching, say $<r_{i-1}, r'_{i-1}>$, and until getting a non-conflicting match it tries the next candidates for $r_{i-1}$ this time. If one is obtained, then BB-Graph continues to its normal schedule from the next stage as usual. Otherwise, it backtracks again and applies the same procedure, and goes on in this way, Algorithm \ref{alg:branch_nodes}, lines 9-25.
\input{Pseudocodes/check.tex}
When BB-Graph backtracks from stage $i$ to $i-1$, all the global data structures are returned to their old version at stage $i-1$; that is, the last relationship and node matchings are cancelled and removed from $V_{matched}$ and $E_{matched}$. Also $S$ is stored with its old content by doing the opposites of push and pop operations done at stage $i$, Algorithm \ref{alg:branch_nodes}, lines 21-22.
Since our aim is to find all exact matches of the query graph, backtracking is needed not only when a contradiction occurs, but it is also necessary to try all candidate options for each query graph node and relationship with all possible combinations. For that reason, when an isomorphism of the query is found, instead of terminating or restarting, BB-Graph continues its schedule with backtracking.
When BB-Graph completes the iterative relationship matching part successfully, all the relationships adjacent to $u$ are matched with some relationship adjacent to $u'$. This finishes the reciprocal branching process of two nodes $u$ and $u'$. The rest of algorithm maintains the isomorphism search by recursively repeating the \textit{reciprocal node branching process} for the newly obtained node matchings, Algorithm \ref{alg:BB-Graph}, lines 14-29.
In order to illustrate how BB-Graph works, a sample running schedule is given in Figure \ref{fig:sample_execution}. The whole recursive process of reciprocal node branching, relationship matching and backtracking are shown step-by-step for the sample query and the graph database given in Figure \ref{fig:sample_query_database}.
\input{Figures/sample_execution.tex}
\subsection{Algorithm Complexity}
\label{subsec:complexity}
In this part, we give running time complexity (computational complexity) analysis and space complexity analysis of BB-Graph for the worst case scenarios. In the analyses, we denote the number of nodes (vertices) in query graph $Q$ by $|V_{Q}|$, number of nodes (vertices) in graph database $G$ by $|V_{G}|$ and number of relationships (edges) in query graph $Q$ by $|E_{Q}|$. Also, we use $deg_{Q}^{max}$ and $deg_{G}^{max}$ to denote maximum node degree in query graph and maximum node degree in database graph, respectively.
\;\;
\textit{Time Complexity:}
\label{title:time.complexity}
\;
BB-Graph starts with the filtering part. It tries to find candidates for the starting node by filtering the database nodes depending on the \textit{matching node principal} given in Section \ref{def:matchingnodeprincipal}. In other words, to find all the candidates, label and degree properties of each database node must be checked. Since we work in Neo4j, which holds the information of database nodes grouped by label, filtering with respect to node labels takes $\mathcal{O}(1)$. In the worst case, all database nodes may have labels of the starting node, which means that there exist $|V_{G}|$ number of candidate nodes that are going to be filtered with respect to their adjacent relationships. Since Neo4j directly gives the information about adjacent reationships of each type for every node, it just remains to ask for this information for every candidate node regarding each relationship of different type adjacent to starting node. Therefore, this part takes $\mathcal{O}(|V_{G}| \times deg_{Q}^{max})$, which also gives the worst case complexity of total filtering stage. In the end of it, there may be $|V_{G}|$ number of candidates for the starting node in the worst case.
For each candidate of the starting node isomorphism search is conducted. For that reason, the complexity of this part is going to be $|V_{G}| \times \mathcal{O}(\textsc{Search()})$. Because the function \textsc{Search()} and the function \textsc{BranchNodes()} work in a mutual recursive manner, the cost of \textsc{Search()} actually equals to the cost of \textsc{BranchNodes()}. To be able to calculate the complexity of \textsc{BranchNodes}, we should analyse the computational cost of the operations done in one recursive depth of branching procedure.
In the branching procedure (Algorithm \ref{alg:branch_nodes}), initially, all non-matched relationships of the current query node are detected and for each of them candidate relationship sets are constructed. If we assume that there are $x_{i}$ many number of non-matched relationships for the current node in the depth $i$ of the recursive process, complexity of candidate relationship set construction becomes $\mathcal{O}(x_{i})$. For each non-matched relationship, there can be at most $deg_{G}^{max}$ many number of candidate relationships (If there are more than one different type of non-matched relationships adjacent to the current node, then it is certain that the candidate set size is less than $deg_{G}^{max}$. Nevertheless, we take $deg_{G}^{max}$ as an upper bound for the candidate set size of each non-matched query relationship). This means, there occurs at most $(deg_{G}^{max})^{(x_{i})}$ many number of different combinations of relationship matching for a query node. Since a query node can have at most $deg_{Q}^{max}$ non-matched relationships, the upper bound for number of combinations of relationship matching becomes $(deg_{G}^{max})^{(deg_{Q}^{max})}$. At each candidate relationship selection, it is checked whether there occurs any conflict with the match through \textsc{Check()} function (Algorithm \ref{alg:check}). In \textsc{Check()}, it is checked whether the end nodes of both relationships given by the function argument exist among the already matched query and database nodes. Since we use hash tables to understand which nodes are matched, the only thing that costs in this function is checking \textit{matching node principle} between nodes (line 10). For that reason, complexity of this function becomes $\mathcal{O}(deg_{Q}^{max})$. Since \textit{Check} function is called $x_{i}$, namely $deg_{Q}^{max}$ at most, many times for each combination of relationship matching, at each depth of recursive branching process the cost becomes $\mathcal{O}( (deg_{G}^{max})^{(deg_{Q}^{max})} \times deg_{Q}^{max} \times deg_{Q}^{max})$. Since the maximum depth of the recursive branching can equal to the number of query nodes, $|V_{Q}|$, the overall complexity of branching procedure becomes
$\mathcal{O}( |V_{Q}| \times (deg_{G}^{max})^{(deg_{Q}^{max})} \times (deg_{Q}^{max})^{2} )$.
To conclude, the computational cost of BB-Graph equals to the summation of cost of filtering part and cost of searching part, which is, $\mathcal{O}(|V_{G}| \times deg_{Q}^{max}) + \mathcal{O}( |V_{G}| \times |V_{Q}| \times (deg_{G}^{max})^{(deg_{Q}^{max})} \times (deg_{Q}^{max})^{2})$. However, the cost of filtering part is negligible when it is compared to the cost of searching part. As a result, the running time complexity of BB-Graph becomes \boldmath{$\mathcal{O}( |V_{G}| \times |V_{Q}| \times (deg_{G}^{max})^{(deg_{Q}^{max})} \times (deg_{Q}^{max})^{2})$}\unboldmath.
\;\;
\textit{Space Complexity:}
\label{title:space.complexity}
\;
For the filtering part, BB-Graph uses a list to hold the candidate database nodes for the starting node. Since there can be maximum $|V_{G}|$ number of candidates for the starting node (in other words all the database nodes), there is a need for a list of size $|V_{G}|$ in the worst case. Also, for each query relationship, there is constructed a set of candidate relationships. Since there can be maximum $deg_{G}^{max}$ number of candidates for a query relationship, size of a set of candidate relationships becomes $deg_{G}^{max}$. The case in which the recursive computation reaches to the deepest value is the worst case requiring the largest storage for the sets of candidate relationships. Since all of the query relationships are in the process in the highest depth of the recursion, sets of candidate relationships consume $|E_{Q}| \times deg_{G}^{max}$ units of space at most. When the algorithm backtracks to the previous depth of recursion, the space reserved for containing sets of candidate relationships constructed at that depth is released. Therefore $|E_{Q}| \times deg_{G}^{max}$ is the maximum value of storage needed by them. Additionally, there exists global variables consuming some memory. There are two global hashing maps used to hold already matched query graph and database graph items; one map for already matched nodes and one map for already matched relationships. These two maps include information of the fact that which query node or relationship was matched with which database node or relationship, respectively. For that reason, they can consume at most $2 \times |V_{Q}|$ and $ 2 \times |E_{Q}|$ units of storage, respectively. Lastly, the stack which is used to hold node matchings which are not yet sent to \textit{reciprocal node branching process} needs $2 \times |V_{Q}|$ units of storage, that is the space required in the case that starting node is adjacent to all the remaining query nodes. Throughout the whole execution of BB-Graph, all the other variables consume quite little space and can be neglected. Consequently, the space complexity of BB-Graph equals to summation of all the mentioned values appeared in the worst case, which is \boldmath{$\mathcal{O}(|V_{G}| + |V_{Q}| + |E_{Q}| \times deg_{G}^{max})$}\unboldmath.
\begin{algorithm}[h]
\SetKwInput{Input}{Input}
\SetKwInput{Output}{Output}
\LinesNumbered
\DontPrintSemicolon
\BlankLine
\Input {$\it{Q:}$ Query graph with $n$ vertices\;\qquad \quad
$\it{G:}$ Database graph}
\Output{$\it{M:}$ Set of all exact matches of $Q$ in $G$}
\Begin
{
$M := \emptyset$ \;
Choose the first node in the input as $u_{start}$ \;
$C_{u_{start}} := \{u' \; | \; u' \in V_{G} \text{ and } u' \mnp u_{start} \}$ \;
\ForEach{$u' \in C_{u_{start}}$}
{
$V_{matched} := \emptyset, E_{matched} := \emptyset, S := \emptyset$ \tcp{Reset the temporary storage}
Push $<u_{start}, u'>$ into $S$ \;
Add $<u_{start}, u'>$ into $V_{matched}$ \;
\textsc{Search()}
}
return $M$
}
\textbf{void} \textsc{Search()} \;
\Begin
{
\If{$S \neq \emptyset$}
{
$<u, u'> :=$ Pop $S$ \;
\If{$u$ \upshape{has non-matched adjacent relationship}}
{
\textsc{BranchNodes}($<u, u'>$)
}
\Else
{
\textsc{Search()}
}
}
\Else
{
Add the tuple $(V_{matched}, E_{matched})$ into $M$ \tcp{An exact match found}
}
return
}
\caption{\textsc{BB-Graph Search Algorithm}}
\label{alg:BB-Graph}
\end{algorithm}
\begin{algorithm}[h]
\SetKwInput{Input}{Input}
\SetKwInput{Output}{Output}
\LinesNumbered
\DontPrintSemicolon
\BlankLine
\Input{global variables $S$, $V_{matched}$, $E_{matched}$ \; \qquad \quad
$<u, u'>$: The node match currently being branched}
\Output{It affects the global variables $S$, $V_{matched}$, $E_{matched}$}
\Begin
{
\ForEach{\upshape{non-matched relationship $r_{i}$ adjacent to $u$}}
{
$C_{r_{i}} := \{r'_{i} \; | \; r'_{i} \text{ is adjacent to } u' \text{ and } \; r'_{i} \mrp r_{i} \} $
}
$k := $ number of non-matched relationships adj. to $u$ \;
\textsc{MatchRelationship($1$)} \;
}
\textbf{void} \textsc{MatchRelationship($i$)} \;
\Begin
{
\ForEach{$r'_{i} \in C_{r_{i}}$, $r'_{i}$ \upshape{is not matched}}
{
\If{ \textsc{Check($<r_{i}, r'_{i}>$, $<u, u'>$)} }
{
Add $<r_{i}, r'_{i}>$ into $E_{matched}$ \;
$S^{*} := S$, $V^{*}_{matched} := V_{matched}$ \;
\If{$i \le k$}
{
\textsc{MatchRelationship($i$++)}
}
\Else
{
\textsc{Search}()
}
Remove $<r_{i}, r'_{i}>$ from $E_{matched}$ \tcp{Backtracking}
$S := S^{*}$, $V_{matched} := V^{*}_{matched}$
}
}
}
\caption{\textsc{BranchNodes}}
\label{alg:branch_nodes}
\end{algorithm}
\begin{algorithm}[h]
\SetKwInput{Input}{Input}
\SetKwInput{Output}{Output}
\LinesNumbered
\DontPrintSemicolon
\BlankLine
\Input{global variables $S$, $V_{matched}$, $E_{matched}$ \; \qquad \quad
$<r_{i}, r'_{i}>$: The relationship match to be checked \; \qquad \quad
$<u, u'>$: The node match currently being branched}
\Output{Boolean, depending on the existence of any contradictory situation}
\Begin
{
$\nu_{i} :=$ The end point of $r_{i}$ other than $u_{i}$ \;
$\nu'_{i} :=$ The end point of $r'_{i}$ other than $u'_{i}$ \;
\If{$\exists v_{x} \neq \nu_{i}$ \upshape{ s.t. } $<\nu_{x}, \nu'_{i}> \in V_{matched}$}
{
return \space $false$
}
\If{$\exists \nu'_{x} \neq \nu'_{i}$ \upshape{ s.t. } $<\nu_{i}, \nu'_{x}> \in V_{matched}$}
{
return \space $false$
}
\If{$<\nu_{i}, \nu'_{i}> \notin V_{matched}$}
{
\If{$\nu_{i} \mnp \nu'_{i}$}
{
Push $<\nu_{i}, \nu'_{i}>$ into $S$ \;
Add $<\nu_{i}, \nu'_{i}>$ into $V_{matched}$
}
\Else
{
return \space $false$
}
}
return \space $true$
}
\caption{\textsc{Check}}
\label{alg:check}
\end{algorithm}
\begin{figure*} [!h]
\centering
\resizebox{1\textwidth}{!}{
\begin{tikzpicture}
[->,>=stealth',shorten >=1pt,auto,node distance=1.5cm, semithick]
\tikzset{vertex/.style = {shape=circle,draw,minimum size=1.5em},
edge/.style = {->},
brace/.style = { decorate, decoration={brace, amplitude=5pt} },
mbrace/.style = { decorate, gray, line width=1mm, -, decoration={brace, amplitude=10pt, mirror} },
toplabel/.style = { label, anchor=south },
leftlabel/.style = { label,rotate=-90, left=1em,anchor=north },
bottomlabel/.style = { label, below=.5em, anchor=north },
rightlabel/.style = { label, rotate=90, right=1em, anchor=north },
stackbox/.style = { vertex, shape=rectangle, rounded corners, fill=black, minimum size=0.5em}}
%%%%%%%%%%%%%%%%%%%%%% (1) %%%%%%%%%%%%%%%%%%%%%%%%
\node[vertex,shape=rectangle, rounded corners, minimum width=10em, minimum height=8em] (root) {};
\node[vertex, draw=none] at (root.north) (up) {};
\node[vertex, draw=none] at (root.south) (down) {};
\node[vertex, blue, label=$u_{0}$] at ([xshift=2.5em]root.west) (u0) {$A$};
\node[vertex, blue, label=$u'_{1}$] at ([xshift=-3em,yshift=1em]root.east) (v1) {$A$};
\node[vertex, blue, label=$u'_{6}$] at ([xshift=-1.5em,yshift=-2em]root.east) (v6) {$A$};
\path
(up) edge[-, dashed] (down);
%%%%%%%%%%%%%%%%%%%%%% (2) %%%%%%%%%%%%%%%%%%%%%%%%
\node[vertex, shape=rectangle, rounded corners, minimum width=16em, minimum height=8em, below left of=root, xshift=-15em, yshift=-8em] (lchild) {};
\node[vertex, draw=none] at ([xshift=-1em]lchild.north) (lchild_up) {};
\node[vertex, draw=none] at ([xshift=-1em]lchild.south) (lchild_down) {};
% query part
\node[vertex, draw=none, minimum size=10em] at ([xshift=4.5em, yshift=1em]lchild.west) (lchild_q) {};
\node[vertex, label=$u_{0}$] at (lchild_q.center) (lchild_u0) {$A$};
\node[vertex, blue, label=$u_{1}$, below left of=lchild_u0] (lchild_u1) {$B$};
% database part
\node[vertex, draw=none, minimum size=10em] at ([xshift=-4.5em, yshift=1em]lchild.east) (lchild_g) {};
\node[vertex, label=$u'_{1}$] at (lchild_g.center) (lchild_v1) {$A$};
\node[vertex, blue, label=$u'_{0}$, below left of=lchild_v1] (lchild_v0) {$B$};
\node[vertex, blue, label=$u'_{2}$, below right of=lchild_v1] (lchild_v2) {$B$};
\path
(lchild_up) edge[-, dashed] (lchild_down)
(lchild_u1) edge[blue] (lchild_u0)
(lchild_v0) edge[blue] (lchild_v1)
(lchild_v2) edge[blue] (lchild_v1);
%%%%%%%%%%%%%%%%%%%%%% (3) %%%%%%%%%%%%%%%%%%%%%%%%
\node[vertex, shape=rectangle, rounded corners, minimum width=18em, minimum height=8em, below left of=lchild, xshift=-6em, yshift=-8em] (lchild_lchild) {};
\node[vertex, draw=none] at (lchild_lchild.north) (lchild_lchild_up) {};
\node[vertex, draw=none] at (lchild_lchild.south) (lchild_lchild_down) {};
% query part
\node[vertex, draw=none, minimum size=10em] at ([xshift=4.5em,yshift=1em]lchild_lchild.west) (lchild_lchild_q) {};
\node[vertex, label=$u_{0}$] at (lchild_lchild_q.center) (lchild_lchild_u0) {$A$};
\node[vertex, label=$u_{1}$, below left of=lchild_lchild_u0] (lchild_lchild_u1) {$B$};
\node[vertex, blue, label=$u_{2}$, below right of=lchild_lchild_u0] (lchild_lchild_u2) {$B$};
% database part
\node[vertex, draw=none, minimum size=10em] at ([xshift=-4.5em,yshift=1em]lchild_lchild.east) (lchild_lchild_g) {};
\node[vertex, label=$u'_{1}$] at (lchild_lchild_g.center) (lchild_lchild_v1) {$A$};
\node[vertex, label=$u'_{0}$, below left of=lchild_lchild_v1] (lchild_lchild_v0) {$B$};
\node[vertex, blue, label=$u'_{3}$, below right of=lchild_lchild_v1] (lchild_lchild_v3) {$B$};
\path
(lchild_lchild_up) edge[-, dashed] (lchild_lchild_down)
(lchild_lchild_u0) edge[blue] (lchild_lchild_u2)
(lchild_lchild_u1) edge (lchild_lchild_u0)
(lchild_lchild_v0) edge (lchild_lchild_v1)
(lchild_lchild_v1) edge[blue] (lchild_lchild_v3);
%%%%%%%%%%%%%%%%%%%%%% (4) %%%%%%%%%%%%%%%%%%%%%%%%
\node[vertex, shape=rectangle, rounded corners, minimum width=18em, minimum height=12em, below of=lchild_lchild, yshift=-10em] (lchild_lchild_child) {};
\node[vertex, draw=none] at (lchild_lchild_child.north) (lchild_lchild_child_up) {};
\node[vertex, draw=none] at (lchild_lchild_child.south) (lchild_lchild_child_down) {};
% query part
\node[vertex, draw=none, minimum size=10em] at ([xshift=4.5em,yshift=3em]lchild_lchild_child.west) (lchild_lchild_child_q) {};
\node[vertex, label=$u_{0}$] at (lchild_lchild_child_q.center) (lchild_lchild_child_u0) {$A$};
\node[vertex, label=$u_{1}$, below left of=lchild_lchild_child_u0] (lchild_lchild_child_u1) {$B$};
\node[vertex, label=$u_{2}$, below right of=lchild_lchild_child_u0] (lchild_lchild_child_u2) {$B$};
\node[vertex, blue, label=left:$u_{3}$, below of=lchild_lchild_child_u2] (lchild_lchild_child_u3) {$D$};
% database part
\node[vertex, draw=none, minimum size=10em] at ([xshift=-4.5em,yshift=3em]lchild_lchild_child.east) (lchild_lchild_child_g) {};
\node[vertex, label=$u'_{1}$] at (lchild_lchild_child_g.center) (lchild_lchild_child_v1) {$A$};
\node[vertex, label=$u'_{0}$, below left of=lchild_lchild_child_v1] (lchild_lchild_child_v0) {$B$};
\node[vertex, label=$u'_{3}$, below right of=lchild_lchild_child_v1] (lchild_lchild_child_v3) {$B$};
\node[vertex, blue, label=left:$u'_{4}$, below of=lchild_lchild_child_v3] (lchild_lchild_child_v4) {$D$};
\path
(lchild_lchild_child_up) edge[-, dashed] (lchild_lchild_child_down)
(lchild_lchild_child_u0) edge (lchild_lchild_child_u2)
(lchild_lchild_child_u1) edge (lchild_lchild_child_u0)
(lchild_lchild_child_u2) edge[blue] (lchild_lchild_child_u3)
(lchild_lchild_child_v0) edge (lchild_lchild_child_v1)
(lchild_lchild_child_v1) edge (lchild_lchild_child_v3)
(lchild_lchild_child_v3) edge[blue] (lchild_lchild_child_v4);
%%%%%%%%%%%%%%%%%%%%%% (5) %%%%%%%%%%%%%%%%%%%%%%%%
\node[vertex, shape=rectangle, rounded corners, minimum width=18em, minimum height=12em, below of=lchild_lchild_child, yshift=-15em] (lchild_lchild_child_child) {};
\node[vertex, draw=none] at (lchild_lchild_child_child.north) (lchild_lchild_child_child_up) {};
\node[vertex, draw=none] at (lchild_lchild_child_child.south) (lchild_lchild_child_child_down) {};
% query part
\node[vertex, draw=none, minimum size=10em] at ([xshift=4.5em,yshift=3em]lchild_lchild_child_child.west) (lchild_lchild_child_child_q) {};
\node[vertex, label=$u_{0}$] at (lchild_lchild_child_child_q.center) (lchild_lchild_child_child_u0) {$A$};
\node[vertex, label=$u_{1}$, below left of=lchild_lchild_child_child_u0] (lchild_lchild_child_child_u1) {$B$};
\node[vertex, label=$u_{2}$, below right of=lchild_lchild_child_child_u0] (lchild_lchild_child_child_u2) {$B$};
\node[vertex, label=left:$u_{3}$, below of=lchild_lchild_child_child_u2] (lchild_lchild_child_child_u3) {$D$};
% database part
\node[vertex, draw=none, minimum size=10em] at ([xshift=-4.5em,yshift=3em]lchild_lchild_child_child.east) (lchild_lchild_child_child_g) {};
\node[vertex, label=$u'_{1}$] at (lchild_lchild_child_child_g.center) (lchild_lchild_child_child_v1) {$A$};
\node[vertex, label=$u'_{0}$, below left of=lchild_lchild_child_child_v1] (lchild_lchild_child_child_v0) {$B$};
\node[vertex, label=$u'_{3}$, below right of=lchild_lchild_child_child_v1] (lchild_lchild_child_child_v3) {$B$};
\node[vertex, label=left:$u'_{4}$, below of=lchild_lchild_child_child_v3] (lchild_lchild_child_child_v4) {$D$};
\path
(lchild_lchild_child_child_up) edge[-, dashed] (lchild_lchild_child_child_down)
(lchild_lchild_child_child_u0) edge (lchild_lchild_child_child_u2)
(lchild_lchild_child_child_u1) edge (lchild_lchild_child_child_u0)
edge[blue] (lchild_lchild_child_child_u2)
(lchild_lchild_child_child_u2) edge (lchild_lchild_child_child_u3)
(lchild_lchild_child_child_v0) edge (lchild_lchild_child_child_v1)
edge[blue] (lchild_lchild_child_child_v3)
(lchild_lchild_child_child_v1) edge (lchild_lchild_child_child_v3)
(lchild_lchild_child_child_v3) edge (lchild_lchild_child_child_v4);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%% (6) %%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\node[vertex, shape=rectangle, rounded corners, minimum width=18em, minimum height=8em, below left of=root, xshift=-2em, yshift=-19em] (lchild_rchild) {};
\node[vertex, draw=none] at (lchild_rchild.north) (lchild_rchild_up) {};
\node[vertex, draw=none] at (lchild_rchild.south) (lchild_rchild_down) {};
% query part
\node[vertex, draw=none, minimum size=10em] at ([xshift=4.5em, yshift=1em]lchild_rchild.west) (lchild_rchild_q) {};
\node[vertex, label=$u_{0}$] at (lchild_rchild_q.center) (lchild_rchild_u0) {$A$};
\node[vertex, label=$u_{1}$, below left of=lchild_rchild_u0] (lchild_rchild_u1) {$B$};
\node[vertex, blue, label=$u_{2}$, below right of=lchild_rchild_u0] (lchild_rchild_u2) {$B$};
% database part
\node[vertex, draw=none, minimum size=10em] at ([xshift=-4.5em, yshift=1em]lchild_rchild.east) (lchild_rchild_g) {};
\node[vertex, label=$u'_{1}$] at (lchild_rchild_g.center) (lchild_rchild_v1) {$A$};
\node[vertex, label=$u'_{2}$, below left of=lchild_rchild_v1] (lchild_rchild_v2) {$B$};
\node[vertex, blue, label=$u'_{3}$, below right of=lchild_rchild_v1] (lchild_rchild_v3) {$B$};
\path
(lchild_rchild_up) edge[-, dashed] (lchild_rchild_down)
(lchild_rchild_u0) edge[blue] (lchild_rchild_u2)
(lchild_rchild_u1) edge (lchild_rchild_u0)
(lchild_rchild_v1) edge[blue] (lchild_rchild_v3)
(lchild_rchild_v2) edge (lchild_rchild_v1);
%%%%%%%%%%%%%%%%%%%%%% (7) %%%%%%%%%%%%%%%%%%%%%%%%
\node[vertex, shape=rectangle, rounded corners, minimum width=18em, minimum height=12em, below of=lchild_rchild, yshift=-10em] (lchild_rchild_child) {};
\node[vertex, draw=none] at (lchild_rchild_child.north) (lchild_rchild_child_up) {};
\node[vertex, draw=none] at (lchild_rchild_child.south) (lchild_rchild_child_down) {};
% query part
\node[vertex, draw=none, minimum size=10em] at ([xshift=4.5em,yshift=3em]lchild_rchild_child.west) (lchild_rchild_child_q) {};
\node[vertex, label=$u_{0}$] at (lchild_rchild_child_q.center) (lchild_rchild_child_u0) {$A$};
\node[vertex, label=$u_{1}$, below left of=lchild_rchild_child_u0] (lchild_rchild_child_u1) {$B$};
\node[vertex, label=$u_{2}$, below right of=lchild_rchild_child_u0] (lchild_rchild_child_u2) {$B$};
\node[vertex, blue, label=left:$u_{3}$, below of=lchild_rchild_child_u2] (lchild_rchild_child_u3) {$D$};
% database part
\node[vertex, draw=none, minimum size=10em] at ([xshift=-4.5em,yshift=3em]lchild_rchild_child.east) (lchild_rchild_child_g) {};
\node[vertex, label=$u'_{1}$] at (lchild_rchild_child_g.center) (lchild_rchild_child_v1) {$A$};
\node[vertex, label=$u'_{2}$, below left of=lchild_rchild_child_v1] (lchild_rchild_child_v2) {$B$};
\node[vertex, label=$u'_{3}$, below right of=lchild_rchild_child_v1] (lchild_rchild_child_v3) {$B$};
\node[vertex, blue, label=left:$u'_{4}$, below of=lchild_rchild_child_v3] (lchild_rchild_child_v4) {$D$};
\path
(lchild_rchild_child_up) edge[-, dashed] (lchild_rchild_child_down)
(lchild_rchild_child_u0) edge (lchild_rchild_child_u2)
(lchild_rchild_child_u1) edge (lchild_rchild_child_u0)
(lchild_rchild_child_u2) edge[blue] (lchild_rchild_child_u3)
(lchild_rchild_child_v1) edge (lchild_rchild_child_v3)
(lchild_rchild_child_v2) edge (lchild_rchild_child_v1)
(lchild_rchild_child_v3) edge[blue] (lchild_rchild_child_v4);
%%%%%%%%%%%%%%%%%%%%%% (8) %%%%%%%%%%%%%%%%%%%%%%%%
\node[vertex, shape=rectangle, rounded corners, minimum width=18em, minimum height=12em, below of=lchild_rchild_child, yshift=-15em] (lchild_rchild_child_child) {};
\node[vertex, draw=none] at (lchild_rchild_child_child.north) (lchild_rchild_child_child_up) {};
\node[vertex, draw=none] at (lchild_rchild_child_child.south) (lchild_rchild_child_child_down) {};
% query part
\node[vertex, draw=none, minimum size=10em] at ([xshift=4.5em,yshift=3em]lchild_rchild_child_child.west) (lchild_rchild_child_child_q) {};
\node[vertex, label=$u_{0}$] at (lchild_rchild_child_child_q.center) (lchild_rchild_child_child_u0) {$A$};
\node[vertex, label=$u_{1}$, below left of=lchild_rchild_child_child_u0] (lchild_rchild_child_child_u1) {$B$};
\node[vertex, label=$u_{2}$, below right of=lchild_rchild_child_child_u0] (lchild_rchild_child_child_u2) {$B$};
\node[vertex, label=left:$u_{3}$, below of=lchild_rchild_child_child_u2] (lchild_rchild_child_child_u3) {$D$};
% database part
\node[vertex, draw=none, minimum size=10em] at ([xshift=-4.5em,yshift=3em]lchild_rchild_child_child.east) (lchild_rchild_child_child_g) {};
\node[vertex, label=$u'_{1}$] at (lchild_rchild_child_child_g.center) (lchild_rchild_child_child_v1) {$A$};
\node[vertex, label=$u'_{2}$, below left of=lchild_rchild_child_child_v1] (lchild_rchild_child_child_v2) {$B$};
\node[vertex, label=$u'_{3}$, below right of=lchild_rchild_child_child_v1] (lchild_rchild_child_child_v3) {$B$};
\node[vertex, label=left:$u'_{4}$, below of=lchild_rchild_child_child_v3] (lchild_rchild_child_child_v4) {$D$};
\path
(lchild_rchild_child_child_up) edge[-, dashed] (lchild_rchild_child_child_down)
(lchild_rchild_child_child_u0) edge (lchild_rchild_child_child_u2)
(lchild_rchild_child_child_u1) edge (lchild_rchild_child_child_u0)
edge[blue] (lchild_rchild_child_child_u2)
(lchild_rchild_child_child_u2) edge (lchild_rchild_child_child_u3)
(lchild_rchild_child_child_v1) edge (lchild_rchild_child_child_v3)
(lchild_rchild_child_child_v2) edge (lchild_rchild_child_child_v1)
edge[blue] (lchild_rchild_child_child_v3)
(lchild_rchild_child_child_v3) edge (lchild_rchild_child_child_v4);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%% (9) %%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\node[vertex, shape=rectangle, rounded corners, minimum width=14em, minimum height=8em, below right of=root, xshift=15em, yshift=-8em] (rchild) {};
\node[vertex, draw=none] at (rchild.north) (rchild_up) {};
\node[vertex, draw=none] at (rchild.south) (rchild_down) {};
% query part
\node[vertex, draw=none, minimum size=10em] at ([xshift=4.5em, yshift=1em]rchild.west) (rchild_q) {};
\node[vertex, label=$u_{0}$] at (rchild_q.center) (rchild_u0) {$A$};
\node[vertex, blue, label=$u_{1}$, below left of=rchild_u0] (rchild_u1) {$B$};
% database part
\node[vertex, draw=none, minimum size=10em] at ([xshift=-2em, yshift=1em]rchild.east) (rchild_g) {};
\node[vertex, label=$u'_{6}$] at (rchild_g.center) (rchild_v6) {$A$};
\node[vertex, blue, label=$u'_{7}$, below left of=rchild_v6] (rchild_v7) {$B$};
\path
(rchild_up) edge[-, dashed] (rchild_down)
(rchild_u1) edge[blue] (rchild_u0)
(rchild_v7) edge[blue] (rchild_v6);
%%%%%%%%%%%%%%%%%%%%%% (10) %%%%%%%%%%%%%%%%%%%%%%%%
\node[vertex, shape=rectangle, rounded corners, minimum width=18em, minimum height=8em, below right of=rchild, xshift=4em, yshift=-8em] (rchild_child) {};
\node[vertex, draw=none] at (rchild_child.north) (rchild_child_up) {};
\node[vertex, draw=none] at (rchild_child.south) (rchild_child_down) {};
% query part
\node[vertex, draw=none, minimum size=10em] at ([xshift=4.5em, yshift=1em]rchild_child.west) (rchild_child_q) {};
\node[vertex, label=$u_{0}$] at (rchild_child_q.center) (rchild_child_u0) {$A$};
\node[vertex, label=$u_{1}$, below left of=rchild_child_u0] (rchild_child_u1) {$B$};
\node[vertex, blue, label=$u_{2}$, below right of=rchild_child_u0] (rchild_child_u2) {$B$};
% Crossings
\node[vertex, draw=none, below left of=rchild_child_u2, xshift=1em, yshift=1em] (c1) {};
\node[vertex, draw=none, above right of=rchild_child_u2, xshift=-1em, yshift=-1em] (c2) {};
\node[vertex, draw=none, above left of=rchild_child_u2, xshift=1em, yshift=-1em] (c3) {};
\node[vertex, draw=none, below right of=rchild_child_u2, xshift=-1em, yshift=1em] (c4) {};
% database part
\node[vertex, draw=none, minimum size=10em] at ([xshift=-4.5em, yshift=1em]rchild_child.east) (rchild_child_g) {};
\node[vertex, label=$u'_{6}$] at (rchild_child_g.center) (rchild_child_v6) {$A$};
\node[vertex, label=$u'_{7}$, below left of=rchild_child_v6] (rchild_child_v7) {$B$};
\node[vertex, blue, label=$u'_{0}$, below right of=rchild_child_v6] (rchild_child_v0) {$B$};
% Crossings
\node[vertex, draw=none, below left of=rchild_child_v0, xshift=1em, yshift=1em] (c5) {};
\node[vertex, draw=none, above right of=rchild_child_v0, xshift=-1em, yshift=-1em] (c6) {};
\node[vertex, draw=none, above left of=rchild_child_v0, xshift=1em, yshift=-1em] (c7) {};
\node[vertex, draw=none, below right of=rchild_child_v0, xshift=-1em, yshift=1em] (c8) {};
\path
(rchild_child_up) edge[-, dashed] (rchild_child_down)
(rchild_child_u0) edge[blue, dashed] (rchild_child_u2)
(rchild_child_u1) edge (rchild_child_u0)
(rchild_child_v6) edge[blue, dashed] (rchild_child_v0)
(rchild_child_v7) edge (rchild_child_v6)
(c1) edge[red, -, line width=0.5mm] (c2)
(c3) edge[red, -, line width=0.5mm] (c4)
(c5) edge[red, -, line width=0.5mm] (c6)
(c7) edge[red, -, line width=0.5mm] (c8);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%% (Explanations) %%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%% (Stack Operations) %%%%%%%%%%%%%%%
\node[stackbox, below left of=root, xshift=-20, yshift=-10] (push1) {};
\node[stackbox, above right of=lchild, xshift=-40, yshift=10] (pop1) {};
\node[stackbox, below left of=lchild, xshift=-5, yshift=-10] (push2) {};
\node[stackbox, below of=lchild_lchild] (push3) {};
\node[stackbox, above of=lchild_lchild_child, yshift=18] (pop2) {};
\node[stackbox, below of=lchild_lchild_child, yshift=-18] (push4) {};
\node[stackbox, below of=lchild_lchild_child, yshift=-52] (pop3) {};
\node[stackbox, above of=lchild_lchild_child_child, yshift=18] (pop4) {};
\node[stackbox, below right of=lchild, xshift=17, yshift=-10] (push5) {};
\node[stackbox, below of=lchild_rchild] (push6) {};
\node[stackbox, above of=lchild_rchild_child, yshift=18] (pop5) {};
\node[stackbox, below of=lchild_rchild_child, yshift=-18] (push7) {};
\node[stackbox, below of=lchild_rchild_child, yshift=-52] (pop6) {};
\node[stackbox, above of=lchild_rchild_child_child, yshift=18] (pop7) {};
\node[stackbox, below right of=root, xshift=20, yshift=-10] (push8) {};
\node[stackbox, above left of=rchild, xshift=40, yshift=10] (pop8) {};
\node[stackbox, below right of=rchild, xshift=-25, yshift=-10] (push9) {};
\path
(push1) edge[-] (pop1)
(push2) edge[-] (lchild_lchild)
(push3) edge[-] (pop2)
(push4) edge[-] (pop4)
(push5) edge[-] (lchild_rchild)
(push6) edge[-] (pop5)
(push7) edge[-] (pop7)
(push8) edge[-] (pop8)
(push9) edge[-] (rchild_child);
\node[draw=none, left of=push1, xshift=-2em, yshift=1em] (spush1) {Push $<u_{0}, u'_{1}>$ into $S$};
\node[draw=none, left of=pop1, xshift=1em, yshift=1em] (spop1) {Pop $<u_{0}, u'_{1}>$ from $S$};
\node[draw=none, left of=push2, xshift=-2em, yshift=-1em] (spush2) {Push $<u_{1}, u'_{0}>$ into $S$};
\node[draw=none, left of=push3, xshift=-2em, yshift=-1em] (spush3) {Push $<u_{2}, u'_{3}>$ into $S$};
\node[draw=none, left of=pop2, xshift=-2em, yshift=1em] (spop2) {Pop $<u_{2}, u'_{3}>$ from $S$};
\node[draw=none, left of=push4, xshift=-2em, yshift=-1em] (spush4) {Push $<u_{3}, u'_{4}>$ into $S$};
\node[draw=none, right of=pop3, xshift=0.6em] (spop3) {Pop $<u_{3}, u'_{4}>$ from $S$};
\node[draw=none, left of=pop4, xshift=-2em, yshift=1em] (spop4) {Pop $<u_{1}, u'_{0}>$ from $S$};
\node[draw=none, right of=push5, xshift=3em, yshift=-1em] (spush5) {Push $<u_{1}, u'_{2}>$ into $S$};
\node[draw=none, left of=push6, xshift=-0.6em, yshift=-1em] (spush6) {Push $<u_{2}, u'_{3}>$ into $S$};
\node[draw=none, left of=pop5, xshift=-0.6em, yshift=1em] (spop5) {Pop $<u_{2}, u'_{3}>$ from $S$};
\node[draw=none, left of=push7, xshift=-0.6em, yshift=-1em] (spush7) {Push $<u_{3}, u'_{4}>$ into $S$};
\node[draw=none, right of=pop6, xshift=0.6em] (spop6) {Pop $<u_{3}, u'_{4}>$ from $S$};
\node[draw=none, left of=pop7, xshift=-0.6em, yshift=1em] (spop7) {Pop $<u_{1}, u'_{2}>$ from $S$};
\node[draw=none, right of=push8, xshift=2em, yshift=1em] (spush8) {Push $<u_{0}, u'_{6}>$ into $S$};
\node[draw=none, right of=pop8, xshift=1em, yshift=1em] (spop8) {Pop $<u_{1}, u'_{7}>$ from $S$};
\node[draw=none, right of=push9, xshift=3em, yshift=-1em] (spush9) {Push $<u_{2}, u'_{0}>$ into $S$};
%%%%%%%%%%%%%%%%%% (Curly Braces) %%%%%%%%%%%%%%%%%%
\draw [mbrace] (-16,1.45) -- (-16,-1.45) node[bottomlabel, text width=3cm, black, left of=root] at (-16.5,0) {\Large Starting node: $u_{0}$ \\ Filtering for $u_{0}$};
\draw [mbrace] (-16,-2.45) -- (-16,-5.3) node[bottomlabel, text width=3cm, black, left of=lchild] at (-16.5,-3.9) {\Large Candidate search for $_{u_{1}}e_{u_{0}}$};
\draw [mbrace] (-16,-6.35) -- (-16,-9.15) node[bottomlabel, text width=3cm, black, left of=lchild_lchild] at (-16.5,-7.75) {\Large Candidate search for $_{u_{0}}e_{u_{2}}$};
\draw [mbrace] (-16,-10.65) -- (-16,-14.85) node[bottomlabel, text width=3cm, black, left of=lchild_lchild_lchild] at (-16.5,-12.9) {\Large Candidate search for $_{u_{2}}e_{u_{3}}$};
\draw [mbrace] (-16,-17.4) -- (-16,-21.6) node[bottomlabel, text width=3cm, black, left of=lchild_lchild_lchild] at (-16.5,-19.5) {\Large Candidate search for $_{u_{1}}e_{u_{2}}$};
%%%%%%%%%%%%%%%%%%%%%%% (Snake) %%%%%%%%%%%%%%%%%%%%%%
\node[ black] at (-3,1.5) (start) {START};
\draw[gray!50, line width=5, dashed] (-3,1) -- (-8.5,-0.75);
\draw[gray!50, line width=5, dashed] (-8.5,-0.75) -- (-14,-2.45);
\draw[-, gray!20, line width=30] (-14,-2.45) -- (-14,-9.15) node[rightlabel, text width=5cm, black] at(-15.35,-5) {\Large Branching Process \\ for $<u_{0}, u'_{1}>$};
\draw[gray!50, line width=5, dashed] (-14,-9.15) -- (-14,-10.65);
\draw[-, gray!20, line width=30] (-14,-10.65) -- (-14,-16) node[rightlabel, text width=5cm, black] at(-15.35,-12.5) {\Large Branching Process \\ for $<u_{2}, u'_{3}>$};
\draw[gray!50, line width=5, dashed] (-14,-16) -- (-14,-17.4);
\draw[-, gray!20, line width=30] (-14,-17.4) -- (-14,-21.6) node[rightlabel, text width=5cm, black] at(-15.35,-18.8) {\Large Branching Process \\ for $<u_{1}, u'_{0}>$};
\draw[gray!50, line width=5, dashed] (-14,-21.6) -- (-13,-23) -- (-5.5,-23) -- (-5.5,-14);
\draw[gray!50, line width=5, dashed, draw=none] (-5.5,-14) -- (-5.5,-11.5) node[rightlabel, black, fill=gray!20] at (-6.2,-12.7) { Backtrack };
\draw[gray!50, line width=5, dashed] (-5.5,-11.5) -- (-5.5,-5.5);
\draw[gray!50, line width=5, dashed] (-3.5,-2.45) -- (2.5,-2.45);
\draw[-, gray!20, line width=30] (2.8,-2.45) -- (2.8,-9.15) node[leftlabel, text width=5cm, black] at(4.3,-6) {\Large Branching Process \\ for $<u_{0}, u'_{1}>$};
\draw[gray!50, line width=5, dashed] (2.8,-9.15) -- (2.8,-10.65);
\draw[-, gray!20, line width=30] (2.8,-10.65) -- (2.8,-16) node[leftlabel, text width=5cm, black] at(4.3,-14) {\Large Branching Process \\ for $<u_{2}, u'_{3}>$};
\draw[gray!50, line width=5, dashed] (2.8,-16) -- (2.8,-17.4);
\draw[-, gray!20, line width=30] (2.8,-17.4) -- (2.8,-21.6) node[leftlabel, text width=5cm, black] at(4.3,-20) {\Large Branching Process \\ for $<u_{1}, u'_{2}>$};
\draw[gray!50, line width=5, dashed] (2.8,-21.6) -- (3.8,-23) -- (4,-23) -- (4,-14);
\draw[gray!50, line width=5, dashed, draw=none] (4,-14) -- (4,-11.5) node[rightlabel, black, fill=gray!20] at (3.3,-12.7) { Backtrack };
\draw[gray!50, line width=5, dashed] (4,-11.5) -- (4,-5.5);
\draw[gray!50, line width=5, dashed] (9,-2.45) -- (12.7,-2.45);
\draw[-, gray!20, line width=30] (13,-2.45) -- (13,-9.15) node[leftlabel, text width=5cm, black] at(14.5,-6) {\Large Branching Process for $<u_{0}, u'_{6}>$};
\draw[gray!50, line width=5, dashed] (13,-9.15) -- (14,-11) -- (14.5,-11) -- (14.5,-6.5);
\draw[gray!50, line width=5, dashed, draw=none] (14.5,-6.5) -- (14.5,-4) node[rightlabel, black, fill=gray!20] at (13.8,-5.2) { Backtrack };
\draw[gray!50, line width=5, dashed] (14.5,-4) -- (14.5,1);
\node[black] at (14.5,1.5) (finish) {FINISH};
\end{tikzpicture}}
\caption{A sample execution for the query graph and graph database given in Figure \ref{fig:sample_query_database}. Each level of the diagram represents the candidate relationship search for edge matching. At the rectangle boxes of each level the found candidates are shown in blue whereas the already matched nodes and relationships are shown in black. At each rectangle box, operations in query part and database part of the reciprocal node branching process are shown in left and right parts of the box, respectively. The execution flows in the arrow direction.}
\label{fig:sample_execution}
\end{figure*}
% EXPERIMENTAL WORK
\section{EXPERIMENTS and EVALUATION}
\label{sec:experimental.work}
We compare the performances of BB-Graph, Cypher and GraphQL on Population Database supplied by Kale Yaz{\i}l{\i}m which consists of a directed graph with 70 millions of nodes, and WorldCup Database supplied public by Neo4j Team which consists of a directed graph with 45 thousands of nodes. In Table \ref{table:databaseFeatures}, features of Population Database and WorldCup Database are given in a detailed way. We should note that Population Database is much bigger than the ones used in \cite{lee2012depth}, as shown in Table \ref{table:databaseFeatures}.
For the experiments, we use 10 real-world queries for Population Database and 5 real-world queries for WorldCup Database where each query has different number of nodes and relationships and also has different types of node labels and relationships. For each query, BB-Graph and Cypher experiments have been repeated 10 times, and the averages of the elapsed times are used. For all GraphQL experiments refinement-level was adjusted to 1 and the refining process has been repeated as many times as the number of nodes in a query graph. In the experiments of these three algorithms, all the exact matches are found in a continuous time interval without any break. The total elapsed time is calculated in order to compare the performances of the algorithms.
\input{Tables/databaseFeatures.tex}
\subsection{Setup}
\label{subsec:setup}
All the experiments were conducted on the same server with Intel Octa Core 2.27GHz, 8 GB of main memory, and 100 GB hard disk, running Debian GNU, Linux 7.8 (wheezy). The Neo4j version used is 2.3.1. BB-Graph and GraphQL were implemented in Java on Eclipse and Cypher queries were called in Java.
\subsection{Experiments}
We group the experimental results according to the type of query graphs used in BB-Graph. For a query which include cyclic paths on it, we call that as a \textit{complex query}, and for a query which is itself a single path, we simply call that as a \textit{path query}. In Figures \ref{fig:complex.query} and \ref{fig:path.query}, a sample complex query and a sample path query are shown, respectively.
\;\;\;\;\;
\textit{Complex Queries:}
\label{title:complex.queries}
\;\;\;\;
Table \ref{table:complex_queries} shows the experimental results obtained for distinct complex-type query graphs executed over Worldcup and Population Databases.
\input{Tables/complexQueries.tex}
As it can be clearly seen from Table \ref{table:complex_queries}, BB-Graph performs so much better than Cypher and GraphQL for a large majority of complex-type queries. Generally, BB-Graph has higher performance than Cypher for the queries that we have tested, except the two, Q-6 and Q-9, which performs as nearly good as Cypher
for those although it falls a little behind Cypher. For the complex queries executed in WorldCup Database which are Q-1, Q-2 and Q-3 consisting of 4 nodes and 4 relationships with 1 cycle, 7 nodes and 8 relationships with 2 cycles and 10 nodes and 12 relationships with 3 cycles, respectively, BB-Graph has the best performance among all the algorithms. Although GraphQL has the worst performance for Q-1 and Q-2, it achieves a very close performance to BB-Graph for Q-2. We think that it is probably caused by the fact that the existence of a very unique node label in Q-2 made the number of candidate nodes very small. Therefore, the entire search does not take a long time. On the other hand, GraphQL could not terminate under 30 minutes for any of complex queries executed over Population Database. From those queries, for Q-4, Q-5, Q-7, Q-8, Q-10 and Q-11 consisting of 6 nodes and 12 relationships with 7 cycles, 5 nodes and 7 relationships with 4 cycles, 6 nodes and 6 relationships with 1 cycle, 7 nodes and 11 relationships with 5 cycles, 13 nodes and 25 relationships with 13 cycles and 10 nodes and 14 relationships with 3 cycles, respectively, BB-Graph performs much better than Cypher. For Q-10, which is the most complex and the largest query among all in the experiments, Cypher could not complete its running in a reasonable time. Interestingly, although Q-8 and Q-9 have the same number of nodes, relationships, cycles and even the node labels, the performance of BB-Graph changes. The reason for that, while both of those queries have the same number of items, they have different structuring such as the neighbourhoods and degrees of the node which also specializes a graph. For that reason, performance of BB-Graph changes accodingly with the number of false candidates that depends on how much a query graph is specialized with its characteristics.
\input{Figures/complex_query.tex}
\;\;\;\;
\textit{Path Queries:}
\label{title:path.queries}
\;\;\;\;
Table \ref{table:path_queries} shows the experimental results obtained for distinct path-type query graphs executed over Worldcup and Population Databases.
\input{Tables/pathQueries.tex}
From Table \ref{table:path_queries}, it can be seen that BB-Graph has the best performance for 2 path-type queries out of 3. The first path query, Q-12, consists of 5 nodes and 4 relationships executed over WorldCup Database. For this query, BB-Graph shows 4 times better performance than Cypher. For Q-12, GraphQL shows rather low performance when compared to BB-Graph's and Cypher's performances. On the other hand, this is the only path query that GraphQL could complete its execution under 30 minutes. Since Population Database is many times more complex, dense and bigger than WorldCup Database, GraphQL exceeds our reasonable time limit, which is 30 minutes, for the other two path queries. The second path query, Q-13, consists of 8 nodes and 7 relationships executed over Population Database. This query is a recursive query, with the depth of 4. For Q-13, again BB-Graph shows much better performance than Cypher. On the other hand, for Q-14, which is the third path query consisting of 4 nodes and 3 relationships, Cypher peforms a little better than BB-Graph.
\input{Figures/path_query.tex}
\begin{table} [!h]
\begin{center}
\resizebox{0.8\textwidth}{!}{
\begin{tabular}{ | l | l | p{1.8cm} |}
\hline
& \textbf{WorldCup} & \textbf{Population} \\ \hline
Size & 20 MiB & 10.32 GiB \\ \hline
\# of graphs & 1 & 1 \\ \hline
\# of nodes & 45348 & 70422787 \\ \hline
\# of relationships & 86577 & 77163109 \\ \hline
\# of distinct node labels & 12 & 14 \\ \hline
\# of distinct relationship types & 17 & 18 \\ \hline
Avg. \# of labels per node & 1 & 1 \\ \hline
\end{tabular}
}
\caption{General Features of Population and WorldCup Databases}
\label{table:databaseFeatures}
\end{center}
\end{table}
\begin{table*} [!h]
\begin{center}
\resizebox{1\textwidth}{!}{
\begin{tabular}{ | c | c | c | c | c | c | c | p{6cm} |}
\hline
\textbf{Query} & \textbf{Database}
& \textbf{\pbox{50cm}{Number of \\ Nodes}}
& \textbf{\pbox{50cm}{Number of \\ Relationships}}
& \textbf{\pbox{50cm}{Peformance of \\ GraphQL (sec.)}}
& \textbf{\pbox{50cm}{Performance of \\ Cypher (sec.)}}
& \textbf{\pbox{50cm}{Performance of \\ BB-Graph (sec.)}} \\ \hline
\textbf{Q-1} & WorldCup & 4 & 4 & 1112.5 & 10.1 & 1.9 \\ \hline
\textbf{Q-2} & WorldCup & 7 & 8 & 17.9 & 7.8 & 3.9 \\ \hline
\textbf{Q-3} & WorldCup & 10 & 12 & 8.1 & 26.7 & 7.9 \\ \hline
\textbf{Q-4} & Population & 6 & 12 & $>$ 1800.0 & 189.9 & 138.1 \\ \hline
\textbf{Q-5} & Population & 5 & 7 & $>$ 1800.0 & 24.2 & 22.3 \\ \hline
\textbf{Q-6} & Population & 5 & 5 & $>$ 1800.0 & 14.8 & 17.3 \\ \hline
\textbf{Q-7} & Population & 6 & 6 & $>$ 1800.0 & 92.4 & 54.5 \\ \hline
\textbf{Q-8} & Population & 7 & 11 & $>$ 1800.0 & 14.4 & 8.5 \\ \hline
\textbf{Q-9} & Population & 7 & 11 & $>$ 1800.0 & 13.7 & 14.0 \\ \hline
\textbf{Q-10} & Population & 13 & 25 & $>$ 1800.0 & $>$ 1800.0 & 502.7 \\ \hline
\textbf{Q-11} & Population & 10 & 14 & $>$ 1800.0 & 226.7 & 73.4 \\ \hline
\end{tabular}}
\caption{Query Response Times for Complex Queries}
\label{table:complex_queries}
\end{center}
\end{table*}
\begin{figure} [!h]
\centering
\begin{tikzpicture}
[->,>=stealth',shorten >=1pt,auto,node distance=1cm, semithick]
\tikzset{vertex/.style = {shape=ellipse,draw,minimum size=1.5em}}
\tikzset{edge/.style = {->}}
\node[vertex, label=$u_{0}$] (0) at (0,0) {$Person$};
\node[vertex, label=$u_{1}$, below left of=0] (1) at (-2.5,0) {$Person$};
\node[vertex, label=$u_{2}$, below right of=0] (2) at (2.5,0) {$Person$};
\node[vertex, label=above right:$u_{3}$, below right of=1] (3) at (-2,-2) {$Person$};
\node[vertex, label=right:$u_{4}$, below left of=2] (4) at (2,-2) {$Person$};
\node[vertex, label=right:$u_{5}$, below of=0] (5) at (0,-4) {$Flat$};
\node[vertex, draw=none, below of=0] (7) at (0,-4.2) {};
\node[vertex, label=$u_{6}$, below of=2] (6) at (4,-2) {$Flat$};
\path
(0) edge node[above, draw, fill=gray!20] {$S$} (1)
edge node[draw, fill=gray!20] {$O\_S$} (2)
edge node[above, near start, draw, fill=gray!20] {$L\_I$} (5)
(1) edge [bend right] node[left, draw, fill=gray!20] {$L\_I$} (5)
(2) edge node[above, draw, fill=gray!20] {$L\_I$} (6)
(3) edge [bend left] node[left, draw, fill=gray!20] {$F$} (0)
edge node[above, draw, fill=gray!20] {$M$} (1)
edge node[above left, draw, fill=gray!20] {$L\_I$} (5)
(4) edge [bend right] node[right, draw, fill=gray!20] {$F$} (0)
edge node[above right, draw, fill=gray!20] {$M$} (2)
edge node[above right, draw, fill=gray!20] {$L\_I$} (5);
\end{tikzpicture}
\caption{An example for a complex query: \textit{"Find the families (a man, a wife, at least two children, one from an ex-wife), who live at the same address in Population Database"}}
\label{fig:complex.query}
\end{figure}
\begin{table*} [!h]
\begin{center}
\resizebox{1\textwidth}{!}{
\begin{tabular}{ | c | c | c | c | c | c | c | p{6cm} |}
\hline
\textbf{Query} & \textbf{Database}
& \textbf{\pbox{50cm}{Number of \\ Nodes}}
& \textbf{\pbox{50cm}{Number of \\ Relationships}}
& \textbf{\pbox{50cm}{Peformance of \\ GraphQL (sec.)}}
& \textbf{\pbox{50cm}{Performance of \\ Cypher (sec.)}}
& \textbf{\pbox{50cm}{Performance of \\ BB-Graph (sec.)}} \\ \hline
\textbf{Q-12} & WorldCup & 5 & 4 & 28.5 & 1.6 & 0.4 \\ \hline
\textbf{Q-13} & Population & 8 & 7 & $>$ 1800.0 & 26.2 & 2.2 \\ \hline
\textbf{Q-14} & Population & 4 & 3 & $>$ 1800.0 & 12.5 & 18.9 \\ \hline
\end{tabular}}
\caption{Query Response Times for Path Queries}
\label{table:path_queries}
\end{center}
\end{table*}
\begin{figure} [!h]
\centering
\begin{tikzpicture}
[->,>=stealth',shorten >=1pt,auto,node distance=1.5cm, semithick]
\tikzset{vertex/.style = {shape=ellipse,draw,minimum size=1.5em}}
\tikzset{edge/.style = {->}}
\node[vertex, label=$u_{0}$] (0) at (0,0) {$Country$};
\node[vertex, label=$u_{1}$, below right of=0, xshift=50] (1) {$Squad$};
\node[vertex, label=$u_{2}$, below left of=1, xshift=-50] (2) {$Player$};
\node[vertex, label=$u_{3}$, below right of=2, xshift=50] (3) {$Squad$};
\node[vertex, label=$u_{4}$, below left of=3, xshift=-50] (4) {$Country$};
\node[vertex, draw=none, below of=4, yshift=25] (5) {};
\path
(0) edge node[draw, fill=gray!20] {$N\_S$} (1)
(2) edge node[draw, fill=gray!20] {$I\_S$} (1)
edge node[draw, fill=gray!20] {$I\_S$} (3)
(4) edge node[draw, fill=gray!20] {$N\_S$} (3);
\end{tikzpicture}
\caption{An example for a path query: \textit{"Find the players who join the squad of different countries in WorldCup Database"}}
\label{fig:path.query}
\end{figure}
% CONCLUSION
\section{CONCLUSION}
\label{sec:conclusion}
In this paper, a new algorithm, BB-Graph, for Subgraph Isomorphism Problem is introduced. BB-Graph uses branch-and-bound technique to match each node and relationship of query graph with its candidate and uses backtracking approach for the other possible candidates. Different from the current algorithms, BB-Graph does not find candidates of each query graph node all across the graph database. After matching the first query node, BB-Graph searches candidates for the other query graph nodes and relationships in local region of the first-matched database node. Our experiments are conducted with different types of queries on two different real-world databases, namely Population Database and WorldCup Database. According to our experimental results, GraphQL is not scalable enough for querying in very large databases like Population Database. Although GraphQL shows close performance to BB-Graph for one of the queries in WorldCup Database, generally GraphQL performs worse than Cypher and BB-Graph due to its strategy of getting the candidates from the whole database and trying to match even some irrelevant ones. On comparing BB-Graph with Cypher, our experimental results show that BB-Graph has better performance than Cypher for most of the query types, for both large and small databases.
According to our experimental results, we observe that the performance of BB-Graph algorithm does not depend on just one factor like the number of nodes or relationships. Actually, many other features, such as frequency of query node labels and query relationship types in the database graph, number of cycles in query graph, structure of query graph (whether it is a path or something more complex) and also the semantic design of relationships like $1-N$ or $N-N$, affect the computation time. As a future work, it may inspire the researchers to improve the performance of BB-Graph by taking all the query and graph database features mentioned above into consideration.
% Generated by IEEEtran.bst, version: 1.14 (2015/08/26)
\begin{thebibliography}{10}
\providecommand{\url}[1]{#1}
\csname url@samestyle\endcsname
\providecommand{\newblock}{\relax}
\providecommand{\bibinfo}[2]{#2}
\providecommand{\BIBentrySTDinterwordspacing}{\spaceskip=0pt\relax}
\providecommand{\BIBentryALTinterwordstretchfactor}{4}
\providecommand{\BIBentryALTinterwordspacing}{\spaceskip=\fontdimen2\font plus
\BIBentryALTinterwordstretchfactor\fontdimen3\font minus
\fontdimen4\font\relax}
\providecommand{\BIBforeignlanguage}[2]{{%
\expandafter\ifx\csname l@#1\endcsname\relax
\typeout{** WARNING: IEEEtran.bst: No hyphenation pattern has been}%
\typeout{** loaded for the language `#1'. Using the pattern for}%
\typeout{** the default language instead.}%
\else
\language=\csname l@#1\endcsname
\fi
#2}}
\providecommand{\BIBdecl}{\relax}
\BIBdecl
\bibitem{vojtechkolomicenko2013}
V.~Kolomi\v{c}enko, ``Analysis and experimental comparison of graph
databases,'' Master Thesis, Charles University Department of Software
Engineering, Prague, 2013.
\bibitem{batra2012comparative}
S.~Batra and C.~Tyagi, ``Comparative analysis of relational and graph
databases,'' \emph{International Journal of Soft Computing and Engineering
(IJSCE)}, vol.~2, no.~2, pp. 509--512, 2012.
\bibitem{vicknair2010comparison}
C.~Vicknair, M.~Macias, Z.~Zhao, X.~Nan, Y.~Chen, and D.~Wilkins, ``A
comparison of a graph database and a relational database: a data provenance
perspective,'' in \emph{Proceedings of the 48th Annual Southeast Regional
Conference}.\hskip 1em plus 0.5em minus 0.4em\relax ACM, 2010, p.~42.
\bibitem{bitninecompany2014}
``{Bitnine Company Website, Relational Database vs Graph Database},''
\url{http://bitnine.net/rdbms-vs-graph-db/}, accessed: Oct. 2016.
\bibitem{abboud2015subtree}
A.~Abboud, A.~Backurs, T.~D. Hansen, V.~V. Williams, and O.~Zamir, ``Subtree
isomorphism revisited,'' pp. 1256--1271, 2016.
\bibitem{giugno2002graphgrep}
R.~Giugno and D.~Shasha, ``Graphgrep: A fast and universal method for querying
graphs,'' in \emph{Proceedings of the IEEE 16th International Conference on
Pattern Recognition (ICPR)}, vol.~2.\hskip 1em plus 0.5em minus 0.4em\relax
IEEE, 2002, pp. 112--115.
\bibitem{yan2004graph}
X.~Yan, P.~S. Yu, and J.~Han, ``Graph indexing: a frequent structure-based
approach,'' in \emph{Proceedings of the 2004 ACM SIGMOD, International
Conference on Management of Data}.\hskip 1em plus 0.5em minus 0.4em\relax
ACM, 2004, pp. 335--346.
\bibitem{srinivasa2005lwi}
S.~Srinivasa, M.~Maier, M.~R. Mutalikdesai, K.~Gowrishankar, and P.~Gopinath,
``Lwi and safari: A new index structure and query model for graph
databases.'' in \emph{COMAD}, 2005, pp. 138--147.
\bibitem{he2006closure}
H.~He and A.~K. Singh, ``Closure-tree: An index structure for graph queries,''
in \emph{Proceedings of the 22nd International Conference on Data Engineering
(ICDE'06)}.\hskip 1em plus 0.5em minus 0.4em\relax IEEE, 2006, pp. 38--38.
\bibitem{williams2007graph}
D.~W. Williams, J.~Huan, and W.~Wang, ``Graph database indexing using
structured graph decomposition,'' in \emph{IEEE 23rd International Conference
on Data Engineering (ICDE 2007)}.\hskip 1em plus 0.5em minus 0.4em\relax
IEEE, 2007, pp. 976--985.
\bibitem{zhang2007treepi}
S.~Zhang, M.~Hu, and J.~Yang, ``Treepi: A novel graph indexing method,'' in
\emph{IEEE 23rd International Conference on Data Engineering (ICDE)}.\hskip
1em plus 0.5em minus 0.4em\relax IEEE, 2007, pp. 966--975.
\bibitem{zhao2007graph}
P.~Zhao, J.~X. Yu, and P.~S. Yu, ``Graph indexing: tree+ delta<= graph,'' in
\emph{Proceedings of the 33rd International Conference on Very Large Data
Bases}.\hskip 1em plus 0.5em minus 0.4em\relax VLDB Endowment, 2007, pp.
938--949.
\bibitem{ullmann1976algorithm}
J.~R. Ullmann, ``An algorithm for subgraph isomorphism,'' \emph{Journal of the
ACM (JACM)}, vol.~23, no.~1, pp. 31--42, 1976.
\bibitem{cordella2004sub}
L.~P. Cordella, P.~Foggia, C.~Sansone, and M.~Vento, ``A (sub) graph
isomorphism algorithm for matching large graphs,'' \emph{IEEE Transactions on
Pattern Analysis and Machine Intelligence}, vol.~26, no.~10, pp. 1367--1372,
2004.
\bibitem{shang2008taming}
H.~Shang, Y.~Zhang, X.~Lin, and J.~X. Yu, ``Taming verification hardness: an
efficient algorithm for testing subgraph isomorphism,'' \emph{Proceedings of
the VLDB Endowment}, vol.~1, no.~1, pp. 364--375, 2008.
\bibitem{zhang2009gaddi}
S.~Zhang, S.~Li, and J.~Yang, ``Gaddi: distance index based subgraph matching
in biological networks,'' in \emph{Proceedings of the 12th International
Conference on Extending Database Technology: Advances in Database
Technology}.\hskip 1em plus 0.5em minus 0.4em\relax ACM, 2009, pp. 192--203.
\bibitem{he2008graphs}
H.~He and A.~K. Singh, ``Graphs-at-a-time: query language and access methods
for graph databases,'' in \emph{Proceedings of the 2008 ACM SIGMOD
International Conference on Management of Data}.\hskip 1em plus 0.5em minus
0.4em\relax ACM, 2008, pp. 405--418.
\bibitem{zhao2010graph}
P.~Zhao and J.~Han, ``On graph query optimization in large networks,''
\emph{Proceedings of the VLDB Endowment}, vol.~3, no. 1-2, pp. 340--351,
2010.
\bibitem{lee2012depth}
J.~Lee, W.-S. Han, R.~Kasperovics, and J.-H. Lee, ``An in-depth comparison of
subgraph isomorphism algorithms in graph databases,'' in \emph{Proceedings of
the VLDB Endowment}, vol.~6, no.~2.\hskip 1em plus 0.5em minus 0.4em\relax
VLDB Endowment, 2012, pp. 133--144.
\bibitem{han2010igraph}
W.-S. Han, J.~Lee, M.-D. Pham, and J.~X. Yu, ``igraph: a framework for
comparisons of disk-based graph indexing techniques,'' \emph{Proceedings of
the VLDB Endowment}, vol.~3, no. 1-2, pp. 449--459, 2010.
\end{thebibliography}