private bool check(EdgeWeightedDigraph G)
        {
            if (hasCycle)
            {
                DirectedEdge first = new DirectedEdge(0, 0, 0);
                DirectedEdge last = new DirectedEdge(0, 0, 0);

                foreach (DirectedEdge e in cycle)
                {
                    if (!first.IsSet) first = e;
                    if (last.IsSet)
                    {
                        if (last.To != e.From)
                        {
                            Log.Info("cycle edges " + last + " and " + e + " not incident");
                            return false;
                        }
                    }
                    last = e;
                }

                if (last.To != first.From)
                {
                    Log.Info("cycle edges " + last + " and " + first + " not incident");
                    return false;
                }
            }

            return true;
        }
        public BellmanFordSP(EdgeWeightedDigraph G, int s)
        {
            m_distTo  = new double[G.V];
            m_edgeTo  = new DirectedEdge[G.V];
            m_onQueue = new bool[G.V];

            for (int v = 0; v < G.V; v++)
            {
                m_distTo[v] = double.PositiveInfinity;
            }

            m_distTo[s] = 0.0;

            m_queue = new Queue <int>();
            m_queue.Enqueue(s);

            /*
             * int negativeCycleCheck = 1000;
             * while (m_queue.Count > 0 && !hasNegativeCycle)
             * {
             *  int v = m_queue.Dequeue();
             *  m_onQueue[v] = false;
             *  relax(G, v);
             *
             *  if (m_cost++ % negativeCycleCheck == 0)
             *     findNegativeCycle();
             * }*/

            for (int i = 0; i < G.V; i++)
            {
                if (m_queue.Count > 0)
                {
                    int v = m_queue.Dequeue();
                    m_onQueue[v] = false;
                    relax(G, v);
                }
            }

            findNegativeCycle();

            //TODO

            /*if (!check(G, s))
             * {
             *  //throw new Exception("found cycle in digraph");
             *  Log.Info("failed to assert a cycle in digraph");
             * }*/
        }
        public EdgeWeightedDirectedCycle(EdgeWeightedDigraph G)
        {
            m_marked = new bool[G.V];
            m_onStack = new bool[G.V];
            m_edgeTo = new DirectedEdge[G.V];

            for (int v = 0; v < G.V; v++)
            {
                if (!m_marked[v]) dfs(G, v);
            }

            if (!check(G))
            {
                //throw new Exception("found cycle in digraph");
                Log.Error("failed to assert a cycle in digraph");
            }
        }
        public IEnumerable <DirectedEdge> findNegativeCycle()
        {
            int V = m_edgeTo.Length;
            EdgeWeightedDigraph spt = new EdgeWeightedDigraph(V);

            for (int v = 0; v < V; v++)
            {
                if (m_edgeTo[v].IsSet)
                {
                    spt.addEdge(m_edgeTo[v]);
                }
            }

            EdgeWeightedDirectedCycle finder = new EdgeWeightedDirectedCycle(spt);

            return(m_cycle = finder.cycle);
        }
        public BellmanFordSP(EdgeWeightedDigraph G, int s)
        {
            m_distTo = new double[G.V];
            m_edgeTo = new DirectedEdge[G.V];
            m_onQueue = new bool[G.V];

            for (int v = 0; v < G.V; v++)
                m_distTo[v] = double.PositiveInfinity;

            m_distTo[s] = 0.0;

            m_queue = new Queue<int>();
            m_queue.Enqueue(s);

            /*
            int negativeCycleCheck = 1000;
            while (m_queue.Count > 0 && !hasNegativeCycle)
            {
                int v = m_queue.Dequeue();
                m_onQueue[v] = false;
                relax(G, v);

                if (m_cost++ % negativeCycleCheck == 0)
                   findNegativeCycle();
            }*/

            for (int i = 0; i < G.V; i++)
            {
                if (m_queue.Count > 0)
                {
                    int v = m_queue.Dequeue();
                    m_onQueue[v] = false;
                    relax(G, v);
                }
            }

            findNegativeCycle();

            //TODO
            /*if (!check(G, s))
            {
                //throw new Exception("found cycle in digraph");
                Log.Info("failed to assert a cycle in digraph");
            }*/
        }
 private void relax(EdgeWeightedDigraph G, int v)
 {
     foreach (DirectedEdge e in G.adj(v))
     {
         int w = e.To;
         if (m_distTo[w] > m_distTo[v] + e.Weight)
         {
             m_distTo[w] = m_distTo[v] + e.Weight;
             m_edgeTo[w] = e;
             if (!m_onQueue[w])
             {
                 m_queue.Enqueue(w);
                 m_onQueue[w] = true;
             }
         }
         // if (m_cost++ % G.V == 0)
         //   findNegativeCycle();
     }
 }
        public EdgeWeightedDirectedCycle(EdgeWeightedDigraph G)
        {
            m_marked  = new bool[G.V];
            m_onStack = new bool[G.V];
            m_edgeTo  = new DirectedEdge[G.V];

            for (int v = 0; v < G.V; v++)
            {
                if (!m_marked[v])
                {
                    dfs(G, v);
                }
            }

            if (!check(G))
            {
                //throw new Exception("found cycle in digraph");
                Log.Error("failed to assert a cycle in digraph");
            }
        }
        private void CalculateShortestPath()
        {
            EdgeWeightedDigraph G = new EdgeWeightedDigraph(m_a.Rows);

            for (int v = 0; v < m_a.Rows; v++)
            {
                for (int w = 0; w < m_a.Cols; w++)
                {
                    DirectedEdge e = new DirectedEdge(v, w, -Math.Log(m_a[v, w]));
                    G.addEdge(e);
                }
            }

            BellmanFordSP spt = new BellmanFordSP(G, 0);

            if (spt.negativeCycleCount > 2)
            {
                double stake     = 25000;
                double arbitrage = 1;

                ArbitrageCycle cycle = new ArbitrageCycle(m_currentTime);

                foreach (DirectedEdge e in spt.negativeCycle)
                {
                    double weight = Math.Exp(-e.Weight);
                    arbitrage *= weight;
                    cycle.Edges.Add(new DirectedEdge(e.From, e.To, weight));
                }

                if (!m_activeArbitrage.Contains(cycle, ARBITRAGE_CYCLE_COMPARER))
                {
                    m_activeArbitrage.Add(cycle);
                    Status(cycle.Summary);
                    Status("arbitrage(" + arbitrage + ") stake(" + stake + ") balance(" + (arbitrage * stake) + ") profit(" + Math.Round(((arbitrage * stake) / stake) - 1, 5) + "%)");
                }
            }
        }
        private void dfs(EdgeWeightedDigraph G, int v)
        {
            m_onStack[v] = true;
            m_marked[v] = true;

            foreach (DirectedEdge e in G.adj(v))
            {
                int w = e.To;

                if (m_cycle != null)
                {
                    return;
                }
                else if (!m_marked[w])
                {
                    m_edgeTo[w] = e;
                    dfs(G, w);
                }
                else if (m_onStack[w])
                {
                    m_cycle = new Stack<DirectedEdge>();
                    DirectedEdge ee = e;
                    while (ee.From != w)
                    {
                        m_cycle.Push(ee);
                        ee = m_edgeTo[ee.From];
                    }
                    m_cycle.Push(ee);
                }
            }

            m_onStack[v] = false;
        }
        private void CalculateShortestPath()
        {
            EdgeWeightedDigraph G = new EdgeWeightedDigraph(m_a.Rows);
            for (int v = 0; v < m_a.Rows; v++)
            {
                for (int w = 0; w < m_a.Cols; w++)
                {
                    DirectedEdge e = new DirectedEdge(v, w, -Math.Log(m_a[v, w]));
                    G.addEdge(e);
                }
            }

            BellmanFordSP spt = new BellmanFordSP(G, 0);

            if (spt.negativeCycleCount > 2)
            {
                double stake = 25000;
                double arbitrage = 1;

                ArbitrageCycle cycle = new ArbitrageCycle(m_currentTime);

                foreach (DirectedEdge e in spt.negativeCycle)
                {
                    double weight = Math.Exp(-e.Weight);
                    arbitrage *= weight;
                    cycle.Edges.Add(new DirectedEdge(e.From, e.To, weight));
                }

                if (!m_activeArbitrage.Contains(cycle, ARBITRAGE_CYCLE_COMPARER))
                {
                    m_activeArbitrage.Add(cycle);
                    Status(cycle.Summary);
                    Status("arbitrage(" + arbitrage + ") stake(" + stake + ") balance(" + (arbitrage * stake) + ") profit(" + Math.Round(((arbitrage * stake) / stake) - 1, 5) + "%)");
                }
            }
        }
 private void relax(EdgeWeightedDigraph G, int v)
 {
     foreach (DirectedEdge e in G.adj(v))
     {
         int w = e.To;
         if (m_distTo[w] > m_distTo[v] + e.Weight)
         {
             m_distTo[w] = m_distTo[v] + e.Weight;
             m_edgeTo[w] = e;
             if (!m_onQueue[w])
             {
                 m_queue.Enqueue(w);
                 m_onQueue[w] = true;
             }
         }
        // if (m_cost++ % G.V == 0)
          //   findNegativeCycle();
     }
 }
        public IEnumerable<DirectedEdge> findNegativeCycle()
        {
            int V = m_edgeTo.Length;
            EdgeWeightedDigraph spt = new EdgeWeightedDigraph(V);
            for (int v = 0; v < V; v++)
            {
                if (m_edgeTo[v].IsSet)
                    spt.addEdge(m_edgeTo[v]);
            }

            EdgeWeightedDirectedCycle finder = new EdgeWeightedDirectedCycle(spt);
            return m_cycle = finder.cycle;
        }