//public List<Tuple<IndexedGraph, int>> Mine(int minSupp, int maxSize, int[] constraintVSet)
        //{
        //    DateTime begin = DateTime.Now;

        //    //FrequentPathMining fpm = new FrequentPathMiningDepth();
        //    FrequentPathMining fpm = new FrequentPathMiningBreadth();

        //    fpm.Init(_g, minSupp, maxSize, constraintVSet);
        //    //fpm.Init(_g, minSupp, maxSize);

        //    Console.WriteLine("{0} seconds. {1} path results.",
        //        (DateTime.Now - begin).TotalSeconds,
        //        fpm._resultCache.Count);

        //    List<Tuple<IndexedGraph, int>> ret = new List<Tuple<IndexedGraph, int>>();

        //    Console.WriteLine("Adding {0} paths.", fpm.GetPath(1).Count);
        //    List<IndexedGraph> lastResults = fpm.GetPath(1);

        //    ret.AddRange(fpm.GetPathAndSupp(1));

        //    for (int size = 2; size <= maxSize; size++)
        //    {
        //        begin = DateTime.Now;
        //        Console.WriteLine("Computing Size-{0} Candidate Patterns.", size);
        //        List<IndexedGraph> tempResults = new List<IndexedGraph>();
        //        for (int i = 0; i < lastResults.Count; i++)
        //        {
        //            for (int j = i; j < lastResults.Count; j++)
        //            {
        //                List<IndexedGraph> newPatterns = null;
        //                if (j == i)
        //                {
        //                    Graph tempG = lastResults[i].ShallowCopy();
        //                    newPatterns = JoinGraphPair(tempG, lastResults[i]);
        //                }
        //                else
        //                    newPatterns = JoinGraphPair(lastResults[i], lastResults[j]);
        //                foreach (IndexedGraph pattern in newPatterns)
        //                {
        //                    bool hasDup = false;
        //                    foreach (IndexedGraph pattern1 in tempResults)
        //                        if (_subGTester.MatchNeighborhood(pattern, pattern1, 0))
        //                        {
        //                            hasDup = true;
        //                            break;
        //                        }
        //                    if (!hasDup)
        //                        tempResults.Add(pattern);
        //                }
        //            }
        //        }
        //        Console.WriteLine("{0} seconds. {1} candidates.",
        //            (DateTime.Now - begin).TotalSeconds,
        //            tempResults.Count);
        //        begin = DateTime.Now;
        //        Console.WriteLine("Validating Size-{0} Candidate Patterns.", size);

        //        lastResults.Clear();
        //        foreach (IndexedGraph pattern in tempResults)
        //        {
        //            int supp = 0;

        //            List<List<int>> ccands = _niindex.GetCandidatesForeachVertex(pattern);

        //            if (ccands.Exists(e => e != null && e.Count == 0))
        //                continue;

        //            if (ccands[0].Count < minSupp)
        //                continue;

        //            _subGTester._cands = ccands;

        //            foreach (int i in constraintVSet)
        //                if (_subGTester.MatchNeighborhood(pattern, _g, i))
        //                    supp++;

        //            _subGTester._cands = null;

        //            if (supp >= minSupp)
        //            {
        //                ret.Add(new Tuple<IndexedGraph, int>(pattern, supp));

        //                //pattern.Print();
        //                //Console.WriteLine(supp+"\n");

        //                lastResults.Add(pattern);
        //            }
        //        }
        //        Console.WriteLine("{0} seconds. {1} results.",
        //            (DateTime.Now - begin).TotalSeconds,
        //            lastResults.Count);
        //        begin = DateTime.Now;
        //        lastResults.AddRange(fpm.GetPath(size));
        //        Console.WriteLine("Adding {0} paths.", fpm.GetPath(size).Count);
        //        //lastResults.Sort((x, y) => x._vertexes.Length - y._vertexes.Length);
        //        ret.AddRange(fpm.GetPathAndSupp(size));
        //        if (lastResults.Count == 0)
        //            break;
        //    }
        //    return ret;
        //}

        public List <Tuple <IndexedGraph, int> > Mine(int minSupp, int maxSize, int[] constraintVSet)
        {
            bool useVIDList = true;

            List <int> constraintVSetList = constraintVSet.ToList();

            DateTime begin = DateTime.Now;

            //FrequentPathMining fpm = new FrequentPathMiningDepth();
            FrequentPathMining fpm = new FrequentPathMiningBreadth();

            fpm.Init(_g, minSupp, maxSize, constraintVSet, useVIDList);
            //fpm.Init(_g, minSupp, maxSize);

            Console.WriteLine("{0} seconds. {1} path results.",
                              (DateTime.Now - begin).TotalSeconds,
                              fpm._resultCache.Count);

            List <Tuple <IndexedGraph, int> > ret = new List <Tuple <IndexedGraph, int> >();

            Console.WriteLine("Adding {0} paths.", fpm.GetPathAndInfo(1).Count);
            List <Tuple <IndexedGraph, List <int> > > lastResults = fpm.GetPathAndVID(1);

            ret.AddRange(fpm.GetPathAndCount(1));

            for (int size = 2; size <= maxSize; size++)
            {
                begin = DateTime.Now;
                Console.WriteLine("Computing Size-{0} Candidate Patterns.", size);
                List <Tuple <IndexedGraph, List <int> > > tempResults = new List <Tuple <IndexedGraph, List <int> > >();
                for (int i = 0; i < lastResults.Count; i++)
                {
                    for (int j = i; j < lastResults.Count; j++)
                    {
                        List <IndexedGraph> newPatterns = null;
                        List <int>          vids        = null;
                        if (j == i)
                        {
                            Graph tempG = lastResults[i].Item1.ShallowCopy();
                            newPatterns = JoinGraphPair(tempG, lastResults[i].Item1);
                            vids        = lastResults[i].Item2;
                        }
                        else
                        {
                            if (useVIDList)
                            {
                                vids = Tools.MergeSortedArray(lastResults[i].Item2, lastResults[j].Item2);
                                if (vids.Count < minSupp)
                                {
                                    continue;
                                }
                            }
                            newPatterns = JoinGraphPair(lastResults[i].Item1, lastResults[j].Item1);
                        }
                        foreach (IndexedGraph pattern in newPatterns)
                        {
                            bool hasDup = false;
                            foreach (var pair in tempResults)
                            {
                                if (_subGTester.MatchNeighborhood(pattern, pair.Item1, 0))
                                {
                                    hasDup = true;
                                    break;
                                }
                            }
                            if (!hasDup)
                            {
                                tempResults.Add(new Tuple <IndexedGraph, List <int> >(pattern, vids));
                            }
                        }
                    }
                }
                Console.WriteLine("{0} seconds. {1} candidates.",
                                  (DateTime.Now - begin).TotalSeconds,
                                  tempResults.Count);
                begin = DateTime.Now;
                Console.WriteLine("Validating Size-{0} Candidate Patterns.", size);

                lastResults.Clear();
                foreach (var pair in tempResults)
                {
                    int supp = 0;

                    List <List <int> > ccands = _niindex.GetCandidatesForeachVertex(pair.Item1);

                    if (ccands.Exists(e => e != null && e.Count == 0))
                    {
                        continue;
                    }

                    if (ccands[0].Count < minSupp)
                    {
                        continue;
                    }

                    _subGTester._cands = ccands;

                    List <int> vids = null, filteredVids = null;
                    if (useVIDList)
                    {
                        filteredVids = new List <int>();
                        vids         = pair.Item2;
                    }
                    else
                    {
                        vids = constraintVSetList;
                    }

                    foreach (int i in vids)
                    {
                        if (_subGTester.MatchNeighborhood(pair.Item1, _g, i))
                        {
                            supp++;
                            if (useVIDList)
                            {
                                filteredVids.Add(i);
                            }
                        }
                    }

                    _subGTester._cands = null;

                    if (supp >= minSupp)
                    {
                        ret.Add(new Tuple <IndexedGraph, int>(pair.Item1, supp));

                        //pattern.Print();
                        //Console.WriteLine(supp+"\n");

                        lastResults.Add(new Tuple <IndexedGraph, List <int> >(pair.Item1, filteredVids));
                    }
                }
                Console.WriteLine("{0} seconds. {1} results.",
                                  (DateTime.Now - begin).TotalSeconds,
                                  lastResults.Count);
                begin = DateTime.Now;

                var addpath = fpm.GetPathAndVID(size);
                lastResults.AddRange(addpath);

                Console.WriteLine("Adding {0} paths.", addpath.Count);
                //lastResults.Sort((x, y) => x._vertexes.Length - y._vertexes.Length);
                ret.AddRange(fpm.GetPathAndCount(size));
                if (lastResults.Count == 0)
                {
                    break;
                }
            }
            return(ret);
        }
        public List <Tuple <IndexedGraph, List <int> > > MineEgonet(int minSupp, int maxSize, int maxRadius, int[] constraintVSet)
        {
            //bool useVIDList = false;

            List <int> constraintVSetList = constraintVSet.ToList();

            DateTime begin = DateTime.Now;

            //FrequentPathMining fpm = new FrequentPathMiningDepth();
            FrequentPathMining fpm = new FrequentPathMiningBreadth();

            fpm.Init(_g, minSupp, maxSize, constraintVSet, true, maxRadius);
            //fpm.Init(_g, minSupp, maxSize);

            Console.WriteLine("{0} seconds. {1} path results.",
                              (DateTime.Now - begin).TotalSeconds,
                              fpm._resultCache.Count);


            List <Tuple <IndexedGraph, List <int> > > ret = new List <Tuple <IndexedGraph, List <int> > >();

            Console.WriteLine("Adding {0} paths.", fpm.GetPathAndVID(1).Count);
            List <Tuple <IndexedGraph, List <int> > > lastResults = fpm.GetPathAndVID(1);

            ret.AddRange(fpm.GetPathAndVID(1));

            //IndexedGraph z = new IndexedGraph();
            //z.Read(@"E:\RkNPQ\1.txt");
            //SubGraphTest sgt1 = new SubGraphTest();

            for (int size = 2; size <= maxSize; size++)
            {
                begin = DateTime.Now;
                Console.WriteLine("Computing Size-{0} Candidate Patterns.", size);
                List <Tuple <IndexedGraph, List <int> > > tempResults = new List <Tuple <IndexedGraph, List <int> > >();

                for (int i = 0; i < lastResults.Count; i++)
                {
                    for (int j = i; j < lastResults.Count; j++)
                    {
                        List <IndexedGraph> newPatterns = null;
                        List <int>          vids        = null;
                        if (j == i)
                        {
                            Graph tempG = lastResults[i].Item1.ShallowCopy();
                            newPatterns = JoinGraphPair(tempG, lastResults[i].Item1);
                            vids        = lastResults[i].Item2;
                        }
                        else
                        {
                            vids = Tools.MergeSortedArray(lastResults[i].Item2, lastResults[j].Item2);
                            if (vids.Count < minSupp)
                            {
                                continue;
                            }
                            newPatterns = JoinGraphPair(lastResults[i].Item1, lastResults[j].Item1);
                        }
                        foreach (IndexedGraph pattern in newPatterns)
                        {
                            //if (sgt1.MatchNeighborhood(z, pattern, 0))
                            //{
                            //    Console.WriteLine();
                            //}
                            bool hasDup = false;
                            foreach (var pair in tempResults)
                            {
                                if (_subGTester.MatchNeighborhood(pattern, pair.Item1, 0))
                                {
                                    hasDup = true;
                                    break;
                                }
                            }
                            if (!hasDup)
                            {
                                tempResults.Add(new Tuple <IndexedGraph, List <int> >(pattern, vids));
                            }
                        }
                    }
                }
                Console.WriteLine("{0} seconds. {1} candidates.",
                                  (DateTime.Now - begin).TotalSeconds,
                                  tempResults.Count);
                begin = DateTime.Now;
                Console.WriteLine("Validating Size-{0} Candidate Patterns.", size);

                //Compute Zipper Patterns
                List <Tuple <IndexedGraph, List <int> > > zipperPatterns = new List <Tuple <IndexedGraph, List <int> > >();
                if (size > maxRadius + 1 && size <= 2 * maxRadius + 1)
                {
                    SubGraphTest sgt = new SubGraphTest(true, MapOperationInstances.GetZipperHeads);
                    foreach (var tup in lastResults)
                    {
                        //if(sgt1.MatchNeighborhood(z,tup.Item1,0))
                        //    tup.Item1.Print();
                        var headPosList = ZipperHandler.DetectPotentialZipper(tup.Item1, maxRadius);
                        if (headPosList == null)
                        {
                            continue;
                        }
                        List <int> vids = null;
                        Dictionary <Tuple <int, int>, List <int> > mapELabel2Vids = new Dictionary <Tuple <int, int>, List <int> >();
                        vids = tup.Item2;
                        foreach (int i in vids)
                        {
                            sgt.MatchNeighborhood(tup.Item1, _g, i, headPosList);
                            HashSet <Tuple <int, int> > eLabels = new HashSet <Tuple <int, int> >();
                            sgt._rets.ForEach(e => eLabels.Add((Tuple <int, int>)e));
                            foreach (var pair in eLabels)
                            {
                                if (!mapELabel2Vids.ContainsKey(pair))
                                {
                                    mapELabel2Vids[pair] = new List <int>();
                                }
                                mapELabel2Vids[pair].Add(i);
                            }
                        }
                        foreach (var pair in mapELabel2Vids)
                        {
                            if (pair.Value.Count >= minSupp)
                            {
                                Edge newEdge = new Edge();

                                newEdge._from = headPosList[pair.Key.Item2].Item1;
                                newEdge._to   = headPosList[pair.Key.Item2].Item2;

                                newEdge._eLabel = pair.Key.Item1;
                                IndexedGraph g           = tup.Item1.ShallowCopy();
                                Edge[]       newEdgeList = new Edge[g._edges.Length + 1];
                                g._edges.CopyTo(newEdgeList, 0);
                                newEdgeList[newEdgeList.Length - 1] = newEdge;
                                g._edges = newEdgeList;

                                Vertex v1             = g._vertexes[newEdge._from];
                                int[]  newOutEdgeList = new int[v1._outEdge.Length + 1];
                                v1._outEdge.CopyTo(newOutEdgeList, 0);
                                newOutEdgeList[newOutEdgeList.Length - 1] = newEdgeList.Length - 1;
                                v1._outEdge = newOutEdgeList;

                                Vertex v2            = g._vertexes[newEdge._to];
                                int[]  newInEdgeList = new int[v2._inEdge.Length + 1];
                                v2._inEdge.CopyTo(newInEdgeList, 0);
                                newInEdgeList[newInEdgeList.Length - 1] = newEdgeList.Length - 1;
                                v2._inEdge = newInEdgeList;
                                g.GenIndex();

                                zipperPatterns.Add(new Tuple <IndexedGraph, List <int> >(g, pair.Value));
                            }
                        }
                    }
                }
                lastResults.Clear();
                foreach (var pair in tempResults)
                {
                    int supp = 0;

                    List <List <int> > ccands = _niindex.GetCandidatesForeachVertex(pair.Item1);

                    if (ccands.Exists(e => e != null && e.Count == 0))
                    {
                        continue;
                    }

                    //if (ccands[0].Count < minSupp)
                    //continue;

                    _subGTester._cands = ccands;

                    List <int> vids = null, filteredVids = null;
                    filteredVids = new List <int>();
                    vids         = pair.Item2;

                    foreach (int i in vids)
                    {
                        if (_subGTester.MatchNeighborhood(pair.Item1, _g, i))
                        {
                            supp++;
                            filteredVids.Add(i);
                        }
                    }

                    _subGTester._cands = null;

                    if (supp >= minSupp)
                    {
                        ret.Add(new Tuple <IndexedGraph, List <int> >(pair.Item1, filteredVids));

                        //pattern.Print();
                        //Console.WriteLine(supp+"\n");

                        lastResults.Add(new Tuple <IndexedGraph, List <int> >(pair.Item1, filteredVids));
                    }
                }
                Console.WriteLine("{0} seconds. {1} results.",
                                  (DateTime.Now - begin).TotalSeconds,
                                  lastResults.Count);
                begin = DateTime.Now;

                if (size <= maxRadius + 1)
                {
                    var addpath = fpm.GetPathAndVID(size);
                    lastResults.AddRange(addpath);

                    Console.WriteLine("Adding {0} paths.", addpath.Count);
                    //lastResults.Sort((x, y) => x._vertexes.Length - y._vertexes.Length);
                    ret.AddRange(fpm.GetPathAndVID(size));
                }
                else
                {
                    //add Zipper Patterns
                    Console.WriteLine("Adding {0} Zippers.", zipperPatterns.Count);
                    lastResults.AddRange(zipperPatterns);
                    ret.AddRange(zipperPatterns);
                }
                if (lastResults.Count == 0)
                {
                    break;
                }
            }
            return(ret);
        }