private bool TryGetActivity(InternalActivityEdge edge, out Activity activity)
        {
            activity = null;
            if (edge.ActivityId.HasValue && activitiesDictionary.ContainsKey(edge.ActivityId.Value))
            {
                activity = activitiesDictionary[edge.ActivityId.Value];
                return(true);
            }

            return(false);
        }
        private BidirectionalGraph <InternalEventVertex, InternalActivityEdge> ExplodeActivityNodeGraphToArrowGraph(BidirectionalGraph <int, SEdge <int> > nodeGraph)
        {
            var arrowGraph = new BidirectionalGraph <InternalEventVertex, InternalActivityEdge>();

            // Go over all vertice - add them as new activity edges.
            // activity vertex names are important for resuse when adding the edges.
            foreach (var vertex in nodeGraph.Vertices)
            {
                bool isCritical = activitiesDictionary[vertex].IsCritical;

                var startNode = InternalEventVertex.Create(vertex, ActivityVertexType.ActivityStart, isCritical);
                var endNode   = InternalEventVertex.Create(vertex, ActivityVertexType.ActivityEnd, isCritical);
                arrowGraph.AddVertex(startNode);
                arrowGraph.AddVertex(endNode);

                InternalActivityEdge activityEdge = new InternalActivityEdge(startNode, endNode, isCritical, vertex);

                arrowGraph.AddEdge(activityEdge);
            }

            // Go over all edges - convert them to dummy edges.
            // Make sure connections are maintained.
            foreach (var edge in nodeGraph.Edges)
            {
                bool isSourceCritical = activitiesDictionary[edge.Source].IsCritical;
                bool isTargetCritical = activitiesDictionary[edge.Target].IsCritical;

                InternalActivityEdge activityEdge = new InternalActivityEdge(
                    InternalEventVertex.Create(edge.Source, ActivityVertexType.ActivityEnd, isSourceCritical),
                    InternalEventVertex.Create(edge.Target, ActivityVertexType.ActivityStart, isTargetCritical),
                    isSourceCritical && isTargetCritical);

                arrowGraph.AddEdge(activityEdge);
            }

            return(arrowGraph);
        }
        private void RedirectCommonDependencyToNexus(InternalEventVertex nexusVertex, IEnumerable <InternalEventVertex> depndents, InternalEventVertex commonDependency)
        {
            bool isAddedEdgeCritical = false;
            IEnumerable <InternalActivityEdge> edgesOutOfDependency;

            if (arrowGraph.TryGetOutEdges(commonDependency, out edgesOutOfDependency))
            {
                // Remove the edges between the dependency and the dependents of the nexus vertex
                var edgesToRemove = edgesOutOfDependency.Where(e => depndents.Contains(e.Target)).ToList();
                foreach (var edgeToRemove in edgesToRemove)
                {
                    arrowGraph.RemoveEdge(edgeToRemove);

                    // Replacing even one critical edge means the new edge would be also critical
                    isAddedEdgeCritical = isAddedEdgeCritical || edgeToRemove.IsCritical;
                }
            }
            // Else should never happen

            // This dependency should point at nexus vertex
            var edgeToAdd = new InternalActivityEdge(commonDependency, nexusVertex, isAddedEdgeCritical);

            arrowGraph.AddEdge(edgeToAdd);
        }
        private bool TryRemoveDummyEdge(InternalActivityEdge edge)
        {
            bool edgeRemoved = false;

            // If this is a single edge out or a single edge in - it adds no information to the graph and can be merged.
            var outDegree = arrowGraph.OutDegree(edge.Source);
            var inDegree  = arrowGraph.InDegree(edge.Target);

            // Remove the vertex which has no other edges connected to it
            if (outDegree == 1)
            {
                IEnumerable <InternalActivityEdge> allIncoming;
                if (!arrowGraph.TryGetInEdges(edge.Source, out allIncoming))
                {
                    allIncoming = new List <InternalActivityEdge>();
                }

                bool abortMerge = WillParallelEdgesBeCreated(allIncoming, null, edge.Target);

                if (!abortMerge)
                {
                    // Add the edges with the new source vertex
                    // And remove the old edges
                    foreach (var incomingEdge in allIncoming.ToList())
                    {
                        arrowGraph.AddEdge(new InternalActivityEdge(incomingEdge.Source, edge.Target, incomingEdge.IsCritical, incomingEdge.ActivityId));
                        arrowGraph.RemoveEdge(incomingEdge);
                    }

                    // Remove the edge which is no longer needed
                    arrowGraph.RemoveEdge(edge);

                    // Now remove the vertex which is no longer needed
                    arrowGraph.RemoveVertex(edge.Source);

                    edgeRemoved = true;
                }
            }
            else if (inDegree == 1)
            {
                IEnumerable <InternalActivityEdge> allOutgoing;
                if (!arrowGraph.TryGetOutEdges(edge.Target, out allOutgoing))
                {
                    allOutgoing = new List <InternalActivityEdge>();
                }

                bool abortMerge = WillParallelEdgesBeCreated(allOutgoing, edge.Source, null);

                if (!abortMerge)
                {
                    // Add the edges with the new source vertex
                    // And remove the old edges
                    foreach (var outgoingEdge in allOutgoing.ToList())
                    {
                        arrowGraph.AddEdge(new InternalActivityEdge(edge.Source, outgoingEdge.Target, outgoingEdge.IsCritical, outgoingEdge.ActivityId));
                        arrowGraph.RemoveEdge(outgoingEdge);
                    }

                    // Remove the edge which is no longer needed
                    arrowGraph.RemoveEdge(edge);

                    // Now remove the vertex which is no longer needed
                    arrowGraph.RemoveVertex(edge.Target);

                    edgeRemoved = true;
                }
            }


            return(edgeRemoved);
        }
        private bool TryRemoveDummyEdge(InternalActivityEdge edge)
        {
            bool edgeRemoved = false;

            // If this is a single edge out or a single edge in - it adds no information to the graph and can be merged.
            var outDegree = arrowGraph.OutDegree(edge.Source);
            var inDegree = arrowGraph.InDegree(edge.Target);

            // Remove the vertex which has no other edges connected to it
            if (outDegree == 1)
            {
                IEnumerable<InternalActivityEdge> allIncoming;
                if (!arrowGraph.TryGetInEdges(edge.Source, out allIncoming))
                {
                    allIncoming = new List<InternalActivityEdge>();
                }

                bool abortMerge = WillParallelEdgesBeCreated(allIncoming, null, edge.Target);

                if (!abortMerge)
                {
                    // Add the edges with the new source vertex
                    // And remove the old edges
                    foreach (var incomingEdge in allIncoming.ToList())
                    {
                        arrowGraph.AddEdge(new InternalActivityEdge(incomingEdge.Source, edge.Target, incomingEdge.IsCritical, incomingEdge.ActivityId));
                        arrowGraph.RemoveEdge(incomingEdge);
                    }

                    // Remove the edge which is no longer needed
                    arrowGraph.RemoveEdge(edge);

                    // Now remove the vertex which is no longer needed
                    arrowGraph.RemoveVertex(edge.Source);

                    edgeRemoved = true;
                }
            }
            else if (inDegree == 1)
            {
                IEnumerable<InternalActivityEdge> allOutgoing;
                if (!arrowGraph.TryGetOutEdges(edge.Target, out allOutgoing))
                {
                    allOutgoing = new List<InternalActivityEdge>();
                }

                bool abortMerge = WillParallelEdgesBeCreated(allOutgoing, edge.Source, null);

                if (!abortMerge)
                {
                    // Add the edges with the new source vertex
                    // And remove the old edges
                    foreach (var outgoingEdge in allOutgoing.ToList())
                    {
                        arrowGraph.AddEdge(new InternalActivityEdge(edge.Source, outgoingEdge.Target, outgoingEdge.IsCritical, outgoingEdge.ActivityId));
                        arrowGraph.RemoveEdge(outgoingEdge);
                    }

                    // Remove the edge which is no longer needed
                    arrowGraph.RemoveEdge(edge);

                    // Now remove the vertex which is no longer needed
                    arrowGraph.RemoveVertex(edge.Target);

                    edgeRemoved = true;
                }
            }

            return edgeRemoved;
        }
        private bool TryGetActivity(InternalActivityEdge edge, out Activity activity)
        {
            activity = null;
            if (edge.ActivityId.HasValue && activitiesDictionary.ContainsKey(edge.ActivityId.Value))
            {
                activity = activitiesDictionary[edge.ActivityId.Value];
                return true;
            }

            return false;
        }
        private void RedirectCommonDependencyToNexus(InternalEventVertex nexusVertex, IEnumerable<InternalEventVertex> depndents, InternalEventVertex commonDependency)
        {
            bool isAddedEdgeCritical = false;
            IEnumerable<InternalActivityEdge> edgesOutOfDependency;
            if (arrowGraph.TryGetOutEdges(commonDependency, out edgesOutOfDependency))
            {
                // Remove the edges between the dependency and the dependents of the nexus vertex
                var edgesToRemove = edgesOutOfDependency.Where(e => depndents.Contains(e.Target)).ToList();
                foreach (var edgeToRemove in edgesToRemove)
                {
                    arrowGraph.RemoveEdge(edgeToRemove);

                    // Replacing even one critical edge means the new edge would be also critical
                    isAddedEdgeCritical = isAddedEdgeCritical || edgeToRemove.IsCritical;
                }
            }
            // Else should never happen

            // This dependency should point at nexus vertex
            var edgeToAdd = new InternalActivityEdge(commonDependency, nexusVertex, isAddedEdgeCritical);
            arrowGraph.AddEdge(edgeToAdd);
        }
        private BidirectionalGraph<InternalEventVertex, InternalActivityEdge> ExplodeActivityNodeGraphToArrowGraph(BidirectionalGraph<int, SEdge<int>> nodeGraph)
        {
            var arrowGraph = new BidirectionalGraph<InternalEventVertex, InternalActivityEdge>();

            // Go over all vertice - add them as new activity edges.
            // activity vertex names are important for resuse when adding the edges.
            foreach (var vertex in nodeGraph.Vertices)
            {
                bool isCritical = activitiesDictionary[vertex].IsCritical;

                var startNode = InternalEventVertex.Create(vertex, ActivityVertexType.ActivityStart, isCritical);
                var endNode = InternalEventVertex.Create(vertex, ActivityVertexType.ActivityEnd, isCritical);
                arrowGraph.AddVertex(startNode);
                arrowGraph.AddVertex(endNode);

                InternalActivityEdge activityEdge = new InternalActivityEdge(startNode, endNode, isCritical, vertex);

                arrowGraph.AddEdge(activityEdge);
            }

            // Go over all edges - convert them to dummy edges.
            // Make sure connections are maintained.
            foreach (var edge in nodeGraph.Edges)
            {
                bool isSourceCritical = activitiesDictionary[edge.Source].IsCritical;
                bool isTargetCritical = activitiesDictionary[edge.Target].IsCritical;

                InternalActivityEdge activityEdge = new InternalActivityEdge(
                    InternalEventVertex.Create(edge.Source, ActivityVertexType.ActivityEnd, isSourceCritical),
                    InternalEventVertex.Create(edge.Target, ActivityVertexType.ActivityStart, isTargetCritical),
                    isSourceCritical && isTargetCritical);

                arrowGraph.AddEdge(activityEdge);
            }

            return arrowGraph;
        }