public MyPath <V> FindPath(V start, V end, Predicate <V> vertexTraversable = null, Predicate <IMyPathEdge <V> > edgeTraversable = null)
        {
            // CH: TODO: Make multiple private copies of this method and call the right one
            // according to what were the arguments to the public interface method

            CalculateNextTimestamp();

            MyPathfindingData startData = start.PathfindingData;

            Visit(startData);
            startData.Predecessor = null;
            startData.PathLength  = 0.0f;

            IMyPathVertex <V> retVal             = null;
            float             shortestPathLength = float.PositiveInfinity;

            m_openVertices.Insert(start.PathfindingData, start.EstimateDistanceTo(end));
            while (m_openVertices.Count > 0)
            {
                MyPathfindingData currentData = m_openVertices.RemoveMin();
                V     current           = currentData.Parent as V;
                float currentPathLength = currentData.PathLength;

                if (retVal != null && currentPathLength >= shortestPathLength)
                {
                    break;
                }

                for (int i = 0; i < current.GetNeighborCount(); ++i)
                {
                    /*IMyPathVertex<V> neighbor = current.GetNeighbor(i);
                     * if (neighbor == null) continue;*/

                    IMyPathEdge <V> edge = current.GetEdge(i);
                    if (edge == null || (edgeTraversable != null && !edgeTraversable(edge)))
                    {
                        continue;
                    }

                    V neighbor = edge.GetOtherVertex(current);
                    if (neighbor == null || (vertexTraversable != null && !vertexTraversable(neighbor)))
                    {
                        continue;
                    }

                    float             newPathLength = currentData.PathLength + edge.GetWeight();
                    MyPathfindingData neighborData  = neighbor.PathfindingData;

                    if (neighbor == end && newPathLength < shortestPathLength)
                    {
                        retVal             = neighbor;
                        shortestPathLength = newPathLength;
                    }

                    if (Visited(neighborData))
                    {
                        if (newPathLength < neighborData.PathLength)
                        {
                            neighborData.PathLength  = newPathLength;
                            neighborData.Predecessor = currentData;
                            m_openVertices.ModifyUp(neighborData, newPathLength + neighbor.EstimateDistanceTo(end));
                        }
                    }
                    else
                    {
                        Visit(neighborData);
                        neighborData.PathLength  = newPathLength;
                        neighborData.Predecessor = currentData;
                        m_openVertices.Insert(neighborData, newPathLength + neighbor.EstimateDistanceTo(end));
                    }
                }
            }

            m_openVertices.Clear();

            if (retVal == null)
            {
                return(null);
            }
            else
            {
                return(ReturnPath(retVal.PathfindingData, null, 0));
            }
        }