/// <summary>
        /// returns graph sample from super graph whith k size
        /// </summary>
        /// <param name="super"></param>
        /// <param name="k"></param>
        /// <returns></returns>
        public Graph GetRandomSubgraphESU(Graph super, int k)
        {
            if (k <= 2)
                throw new ArgumentOutOfRangeException();

            Graph sub = new Graph();
            Random rand = new Random();
            int nonNeighborCount = 0;
            sub.AddVertice(super.Vertices[rand.Next(super.Vertices.Count)]);
            while (sub.Vertices.Count < k)
            {
                Vertice vert = sub.Vertices[rand.Next(sub.Vertices.Count)];
                System.Threading.Thread.Sleep(2);
                List<Vertice> nhood = Graph.GetVerticesNeighborhood(super, sub, vert);
                if (nhood.Count != 0)
                {
                    Vertice vertice = nhood[rand.Next(nhood.Count)];
               //         if (vert.index < vertice.index)
               //         {
                        nonNeighborCount = 0;
                        Edge edge = new Edge(vertice.index, vert.index);
                        sub.AddVertice(vertice);
                        sub.AddEdge(edge);
              //          }
              //          else
              //          {
              //              nonNeighborCount++;
              //              if (nonNeighborCount == 5)
             //                   return null;
             //           }

                }
                else
                {
                    nonNeighborCount++;
                    if (nonNeighborCount == 5)
                        return null;
                }

            }
            int verticeIndex = 0;
            Dictionary<int, int> edges = new Dictionary<int, int>();
            foreach (Vertice vertice in sub.Vertices)
            {
                edges[vertice.index] = verticeIndex;
                vertice.index = verticeIndex;
                verticeIndex++;
            }
            sub.changeEdeVerticeIndex(edges);
            if (sub.Edges.Count == 1)
            {
                int edg = sub.Edges.Count;
            }
            return sub;
        }
 /// <summary>
 /// returns true if givens graphs are isomorph false otherwise
 /// </summary>
 /// <param name="A"></param>
 /// <param name="B"></param>
 /// <returns></returns>
 public static bool AreIsomorph(Graph A, Graph B)
 {
     int mismatchCount = 0;
     Sign[,] ASignMatrix = GetSignMatrix(A);
     Sign[,] BSignMatrix = GetSignMatrix(B);
     int[,] AFrequencyMatrix = GetFrequencyMatrix(ASignMatrix);
     int[,] BFrequencyMatrix = GetFrequencyMatrix(BSignMatrix);
     if (AFrequencyMatrix.Length != BFrequencyMatrix.Length)
         return false;
     bool breakFor = false;
     for (int i = 0; i < AFrequencyMatrix.GetLength(0); i++)
     {
         for (int j = 0; j < AFrequencyMatrix.GetLength(1); j++)
         {
             if (AFrequencyMatrix[i,j] != BFrequencyMatrix[i,j])
             {
                 mismatchCount++;
                 breakFor = false;
                 for (int i1 = i; i1 < AFrequencyMatrix.GetLength(0); i1++)
                 {
                     for (int j1 = j + 1; j1 < AFrequencyMatrix.GetLength(1); j1++)
                         if (AFrequencyMatrix[i,j] == BFrequencyMatrix[i1,j1])
                         {
                             SwitchRowsInFrequencyMatrix(ref BFrequencyMatrix, i, i1);
                             SwitchColumnsInFrequencyMatrix(ref BFrequencyMatrix, j1, j);
                             mismatchCount--;
                             breakFor = true;
                             break;
                         }
                     if (breakFor)
                     {
                         break;
                     }
                 }
             }
         }
     }
     if (mismatchCount == 0)
     {
         return true;
     }
     return false;
 }
        //public static XmlDocument createDocument(int motifSize)
        //{
        //    SortedDictionary<int, float> results = MotifFinder.dictionaryIdsValues();
        //    ICollection<int> graphs = results.Keys;
        //    List<int> keys = graphs.ToList();
        //    var document = new XmlDocument();
        //    XmlElement root = document.CreateElement("motifs" + motifSize);
        //    document.AppendChild(root);
        //    for (int i = 0; i < keys.Count; i++)
        //    {
        //        XmlElement node = document.CreateElement("m" + keys[i]);
        //        node.SetAttribute("count", Convert.ToString(results[keys[i]]));
        //        root.AppendChild(node);
        //    }
        //    return document;
        //}
        //public static XmlDocument createDocument(int motifSize)
        //{
        //    Dictionary<int, float> results = MotifFinder.dictionaryIdsValues();
        //    ICollection<int> graphs = results.Keys;
        //    List<int> keys = graphs.ToList();
        //    var document = new XmlDocument();
        //    XmlElement root = document.CreateElement("motifs" + motifSize);
        //    document.AppendChild(root);
        //    for (int i = 0; i < keys.Count; i++)
        //    {
        //        XmlElement node = document.CreateElement("m" + keys[i]);
        //        node.SetAttribute("count", Convert.ToString(results[keys[i]]));
        //        root.AppendChild(node);
        //    }
        //    return document;
        //}
        /// <summary>
        /// prinnt graph edges indexes in console
        /// </summary>
        /// <param name="graph"></param>
        public static void PrintGraphToConsole(Graph graph, StreamWriter outfile)
        {
            //Console.WriteLine();
            outfile.WriteLine();
            // Console.WriteLine("Vertice count: " + graph.Vertices.Count);
            outfile.WriteLine("Vertice count: " + graph.Vertices.Count);
            outfile.WriteLine("Edges: ");
            //  Console.Write("Edges: ");
            foreach (Edge e in graph.Edges)
            {

                outfile.WriteLine(e.v1 + "-" + e.v2);

                // Console.Write(e.v1 + "-" + e.v2);
            }

            // Console.WriteLine();
            outfile.WriteLine();
        }
        /// <summary>
        /// returns graph sample from super graph whith k size
        /// </summary>
        /// <param name="super"></param>
        /// <param name="k"></param>
        /// <returns></returns>
        public Graph GetRandomSubgraphESA(Graph super, int k)
        {
            if (k <= 2)
                throw new ArgumentOutOfRangeException();

            Graph sub = new Graph();
            Random rand = new Random();

            sub.AddEdge(super.Edges[rand.Next(super.Edges.Count)]);
            int nonNeighborCount = 0;
            while (sub.Vertices.Count < k)
            {
                System.Threading.Thread.Sleep(2);
                List<Edge> nhood = Graph.GetEdgesNeighborhood(super, sub);
                if (nhood.Count != 0)
                {
                    nonNeighborCount = 0;
                    sub.AddEdge(nhood[rand.Next(nhood.Count)]);
                }
                else
                {
                    nonNeighborCount++;
                    if (nonNeighborCount == 5)
                        return null;
                }

            }
            int verticeIndex = 0;
            Dictionary<int, int> edges = new Dictionary<int, int>();
            foreach(Vertice vertice in sub.Vertices)
            {
                edges[vertice.index] = verticeIndex;
                vertice.index = verticeIndex;
                verticeIndex++;
            }
            sub.changeEdeVerticeIndex(edges);
            if (sub.Edges.Count == 1)
            {
                int edg = sub.Edges.Count;
            }
            return sub;
        }
 /// <summary>
 /// returns sub graph neighbors edges in super graph
 /// </summary>
 /// <param name="super"></param>
 /// <param name="sub"></param>
 /// <returns></returns>
 public static List<Edge> GetEdgesNeighborhood(Graph super, Graph sub)
 {
     List<Edge> nhood = new List<Edge>();
     foreach (Vertice v in sub.Vertices)
         foreach (Edge e in super.Edges)
             if (e.v1 == v.index || e.v2 == v.index && !sub.Contains(e))
                 nhood.Add(e);
     return nhood;
 }
        public static Graph createGraphFromFile()
        {
            //Protein-Protein Network
            Graph graph = new Graph();

            for (int i = 0; i < 2114; i++)
            {
                graph.AddVertice(new Vertice(i));
            }

            StreamReader reader = new StreamReader("NDYeast.net");
            string line = reader.ReadLine();
            while (line != null)
            {
                if (line[0] == '*')
                {
                    line = reader.ReadLine();
                    continue;
                }

                string[] tokens = line.Split(' ');
                int edge1Index = Convert.ToInt32(tokens[0]);
                for (int i = 1; i < tokens.Length; i++)
                {
                    graph.AddEdge(new Edge(edge1Index - 1, Convert.ToInt32(tokens[i]) - 1));
                }
                line = reader.ReadLine();
            }
            reader.Close();
            return graph;
        }
 private static int GetTentativeDistance(Graph graph, Vertice v1, Vertice v2)
 {
     if (v1 == v2)
         return 0;
     if (graph.Contains(new Edge(v1.index, v2.index)))
         return 1;
     return int.MaxValue;
 }
        private static Graph GetPairGraph(Graph graph, Vertice u, Vertice v)
        {
            List<List<Vertice>> paths = GetDijkstraShortestPaths(graph, u);
            List<Vertice> shortestPathUV = paths[v.index];

            Graph pairUV = new Graph();
            if (shortestPathUV != null)
            {
                foreach (Vertice current in shortestPathUV)
                {
                    pairUV.Vertices.Add(current);
                    foreach (Edge edge in graph.Edges)
                    {
                        if (edge.v1 == current.index || edge.v2 == current.index)
                        {
                            pairUV.AddEdge(edge);
                        }
                    }
                }
            }

            return pairUV;
        }
 private static int GetCollaterialSign(Graph graph, Edge e)
 {
     if (graph.Contains(e))
         return 1;
     return -1;
 }
        //Collaterial and Pair graphs
        private static Graph GetCollaterialGraph(Graph graph, Edge e)
        {
            if (!graph.Contains(e))
                return graph;

            Graph collaterial = new Graph();

            collaterial.Vertices = graph.Vertices;

            foreach (Edge current in graph.Edges)
            {
                if (current != e)
                    collaterial.Edges.Add(current);
            }

            return collaterial;
        }
        /// <summary>
        /// search in network given size motifs and after changes MotifDictionary values
        /// </summary>
        /// <param name="network"></param>
        /// <param name="motifSize"></param>
        public void SearchMotifs(Graph network, int motifSize)
        {
            String pathName = "graph" + motifSize;
            PreloadMotifSamples(pathName, motifSize);
            int sampleingCount = 0;
            int edgeCount = network.Edges.Count;
            int sampleingCountForGivenMotif = 5000;
            int subGraphsCount = 0;
            log.Info("Sampling start");
            using (StreamWriter outfile = new StreamWriter("D:\\test.txt"))
            {
                while (sampleingCount < sampleingCountForGivenMotif)
                {
                    SubgraphSampler subgraphSampler = new SubgraphSampler();
                    ICollection<Graph> graphs;
                    graphs = MotifDictionary.Keys;
                    Graph graph = subgraphSampler.GetRandomSubgraphESU(network, motifSize);
                    if (graph != null)
                    {
                        bool isIsomorf = false;
                        foreach (Graph keyGraph in MotifDictionary.Keys.ToList())
                        {
                            MotifFinder.PrintGraphToConsole(graph, outfile);
                            //MotifFinder.PrintGraphToConsole(keyGraph);
                            if (Isomorphism.AreIsomorph(keyGraph, graph))
                            {
                                MotifDictionary[keyGraph]++;
                                isIsomorf = true;
                                break;
                            }
                        }
                        if (!isIsomorf)
                        {
                            StringBuilder str = new StringBuilder();
                            foreach (Edge e in graph.Edges)
                            {
                                str.Append(e.v1 + "-" + e.v2);
                            }
                            log.Info("this graph don»t have isomorf" + str);
                            outfile.WriteLine("bad graph");
                            MotifFinder.PrintGraphToConsole(graph, outfile);
                        }
                        subGraphsCount++;

                    }
                    sampleingCount++;

                }

                if (MotifDictionary.Keys.Count == 0)
                {
                    log.Info("You must preload motif samples first.");
                    throw new Exception("You must preload motif samples first.");
                }
                foreach (Graph keyGraph in MotifDictionary.Keys.ToList())
                {
                    MotifDictionary[keyGraph] = MotifDictionary[keyGraph] / subGraphsCount;

                }
                log.Info("Sampling end");
                try
                {

                }
                catch (Exception ex)
                {
                    log.Info(ex.Message);
                    Console.WriteLine(ex.Message);
                }

            }
        }
        public static Sign[,] GetSignMatrix(Graph graph)
        {
            Sign[,] signMatrix = new Sign[graph.Vertices.Count, graph.Vertices.Count];

            foreach (Vertice v1 in graph.Vertices)
            {
                foreach (Vertice v2 in graph.Vertices)
                {
                    Sign sign = new Sign();
                    int i = graph.Vertices.IndexOf(v1);
                    int j = graph.Vertices.IndexOf(v2);
                    Graph collaterial = GetCollaterialGraph(graph, new Edge(v1.index, v2.index));
                    List<List<Vertice>> collPaths = GetDijkstraShortestPaths(collaterial, v1);
                    sign.binarySign = GetCollaterialSign(graph, new Edge(v1.index, v2.index));
                    if (collPaths[j] != null && collPaths[j].Count != 0)
                    {
                        sign.collDistance = collPaths[j].Count - 1;
                    }
                    Graph pair = GetPairGraph(graph, v1, v2);
                    sign.pairNumEdges = pair.Edges.Count;
                    sign.pairNumVertices = pair.Vertices.Count;
                    signMatrix[i, j] = sign;
                }
            }
            return signMatrix;
        }
        //Dijkstra's shortest paths
        public static List<List<Vertice>> GetDijkstraShortestPaths(Graph graph, Vertice vSource)
        {
            int[] distances = new int[graph.Vertices.Count];
            bool[] visited = new bool[graph.Vertices.Count];
            visited[vSource.index] = true;

            foreach (Vertice vOuter in graph.Vertices)
                distances[vOuter.index] = GetTentativeDistance(graph, vOuter, vSource);

            while (true)
            {
                int iMin = GetMinimumUnvisitedIndex(distances, visited);
                visited[iMin] = true;

                foreach (Vertice vCurrent in graph.Vertices)
                {
                    if (visited[vCurrent.index] == false)
                    {
                        if (GetTentativeDistance(graph, graph.Vertices[iMin], vCurrent) == int.MaxValue)
                            continue;

                        distances[vCurrent.index] = Math.Min(distances[iMin] + GetTentativeDistance(graph, graph.Vertices[iMin], vCurrent), distances[vCurrent.index]);
                    }
                }

                bool finished = true;
                for (int i = 0; i < visited.Length; i++)
                {
                    if (visited[i] == false && distances[i] != int.MaxValue)
                    {
                        finished = false;
                        break;
                    }
                }
                if (finished)
                    break;
            }

            var shortestPaths = new List<List<Vertice>>();

            foreach (Vertice vCurrent in graph.Vertices)
            {
                Vertice vTemp = vCurrent;
                shortestPaths.Add(new List<Vertice>());
                shortestPaths[vCurrent.index].Insert(0, vCurrent);
                if (distances[vCurrent.index] == int.MaxValue)
                {
                    shortestPaths[vCurrent.index] = null;
                    continue;
                }
                if (vCurrent == vSource)
                {
                    shortestPaths[vCurrent.index].Add(vSource);
                    continue;
                }

                while (true)
                {
                    foreach (Edge eCurrent in graph.Edges)
                    {
                        if (eCurrent.v1 == vTemp.index && distances[eCurrent.v2] == distances[vTemp.index] - 1)
                        {
                            shortestPaths[vCurrent.index].Insert(0, graph.Vertices[eCurrent.v2]);
                            vTemp = graph.Vertices[eCurrent.v2];
                            break;
                        }
                        else if (eCurrent.v2 == vTemp.index && distances[eCurrent.v1] == distances[vTemp.index] - 1)
                        {
                            shortestPaths[vCurrent.index].Insert(0, graph.Vertices[eCurrent.v1]);
                            vTemp = graph.Vertices[eCurrent.v1];
                            break;
                        }
                    }
                    if (vTemp == vSource)
                    {
                        break;
                    }
                }
            }
            return shortestPaths;
        }
        public static int GetCollaterialDistanceAndPairGraph(Graph graph, Vertice u, Vertice v,  //Procedure 3.2
            ref Graph pair)
        {
            Graph collaterial = GetCollaterialGraph(graph, new Edge(u.index, v.index));
            List<List<Vertice>> shortestPathsU = GetDijkstraShortestPaths(collaterial, u);
            List<List<Vertice>> shortestPathsV = GetDijkstraShortestPaths(collaterial, v);
            pair = GetPairGraph(graph, u, v);

            int collaterialUVDistance = shortestPathsU[graph.Vertices.IndexOf(v)].Count - 1;
            return collaterialUVDistance;
        }
 /// <summary>
 /// returns sub graph neighbors vertices in super graph
 /// </summary>
 /// <param name="super"></param>
 /// <param name="sub"></param>
 /// <returns></returns>
 public static List<Vertice> GetVerticesNeighborhood(Graph super, Graph sub,Vertice subVertice)
 {
     List<Vertice> nhood = new List<Vertice>();
     foreach (Edge e in super.Edges)
             if (subVertice.index == e.v1 && !sub.Contains(e))
             {
                 nhood.Add(new Vertice(e.v2));
             }
             else if (subVertice.index == e.v2 && !sub.Contains(e))
             {
                 nhood.Add(new Vertice(e.v1));
             }
     return nhood;
 }
 //Procedure 3.3
 public static void GetSignMatrixAndCanonicalForm(Graph graph, ref Sign[,] matrix, ref Sign[,] canonical)
 {
     matrix = GetSignMatrix(graph);
     canonical = GetCanonicalForm(matrix);
 }
        /// <summary>
        /// create and returns graph in data from given BAContainer type graph
        /// </summary>
        /// <param name="graph"></param>
        /// <returns></returns>
        public static Graph reformatToOurGraghFromBAContainer(BAContainer graph)
        {
            Graph newGraph = new Graph();
            bool[,] matrix = new bool[graph.Neighbourship.Count, graph.Neighbourship.Count];

            List<int> list = new List<int>();
            SortedDictionary<int, List<int>> neighbourship = graph.Neighbourship;
            for (int i = 0; i < neighbourship.Count; i++)
            {

                list = neighbourship[i];
                newGraph.Vertices.Add(new Vertice(i));
                for (int j = 0; j < list.Count; j++)
                    newGraph.Edges.Add(new Edge(i, list[j]));
            }

            return newGraph;
        }
        /// <summary>
        /// prinnt graph edges indexes in console
        /// </summary>
        /// <param name="graph"></param>
        public void PrintGraphToConsole(Graph graph)
        {
            Console.WriteLine();

            Console.WriteLine("Vertice count: " + graph.Vertices.Count);

            Console.Write("Edges: ");
            foreach (Edge e in graph.Edges)
            {
                Console.Write(e.v1 + "-" + e.v2);
            }

            Console.WriteLine();
        }