Exemplo n.º 1
0
        /// <summary>
        /// Tries to Push the overflow in current vertex to neighbours if possible.
        /// Push is possible if neighbour edge is not full
        /// and any of neighbour has height of current vertex
        /// otherwise returns false.
        /// </summary>
        private bool push(WeightedDiGraphVertex <T, W> overflowVertex,
                          Dictionary <T, ResidualGraphVertexStatus> vertexStatusMap)
        {
            var overflow = vertexStatusMap[overflowVertex.Key].Overflow;

            foreach (var edge in overflowVertex.OutEdges)
            {
                //if out edge has +ive weight and neighbour height is less then flow is possible
                if (edge.Value.CompareTo(@operator.defaultWeight) > 0 &&
                    vertexStatusMap[edge.Key.Key].Height
                    < vertexStatusMap[overflowVertex.Key].Height)
                {
                    var possibleWeightToPush = edge.Value.CompareTo(overflow) < 0 ? edge.Value : overflow;

                    //decrement overflow
                    vertexStatusMap[overflowVertex.Key].Overflow =
                        @operator.SubstractWeights(vertexStatusMap[overflowVertex.Key].Overflow,
                                                   possibleWeightToPush);

                    //increment flow of target vertex
                    vertexStatusMap[edge.Key.Key].Overflow =
                        @operator.AddWeights(vertexStatusMap[edge.Key.Key].Overflow,
                                             possibleWeightToPush);

                    //decrement edge weight
                    overflowVertex.OutEdges[edge.Key] = @operator.SubstractWeights(edge.Value, possibleWeightToPush);
                    //increment reverse edge weight
                    edge.Key.OutEdges[overflowVertex] = @operator.AddWeights(edge.Key.OutEdges[overflowVertex], possibleWeightToPush);

                    return(true);
                }
            }

            return(false);
        }
        private static int getMinWeight(WeightedDiGraphVertex <int, int> currentVertex,
                                        WeightedDiGraphVertex <int, int> tgtVertex,
                                        int remainingVertexCount,
                                        HashSet <WeightedDiGraphVertex <int, int> > visited,
                                        Dictionary <string, int> cache)
        {
            var cacheKey = $"{currentVertex.Value}-{remainingVertexCount}";

            if (cache.ContainsKey(cacheKey))
            {
                return(cache[cacheKey]);
            }

            visited.Add(currentVertex);

            var results = new List <int>();

            foreach (var vertex in currentVertex.OutEdges)
            {
                //base case
                if (vertex.Key == tgtVertex &&
                    remainingVertexCount == 1)
                {
                    results.Add(vertex.Value);
                    break;
                }

                if (!visited.Contains(vertex.Key))
                {
                    var result = getMinWeight(vertex.Key, tgtVertex, remainingVertexCount - 1, visited, cache);

                    if (result != int.MaxValue)
                    {
                        results.Add(result + vertex.Value);
                    }
                }
            }

            visited.Remove(currentVertex);

            if (results.Count == 0)
            {
                return(int.MaxValue);
            }

            var min = results.Min();

            cache.Add(cacheKey, min);
            return(min);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Increases the height of a vertex by one greater than min height of neighbours.
        /// </summary>

        private void relabel(WeightedDiGraphVertex <T, W> vertex,
                             Dictionary <T, ResidualGraphVertexStatus> vertexStatusMap)
        {
            var min = int.MaxValue;

            foreach (var edge in vertex.OutEdges)
            {
                //+ive out capacity
                if (min.CompareTo(vertexStatusMap[edge.Key.Key].Height) > 0 &&
                    edge.Value.CompareTo(@operator.defaultWeight) > 0)
                {
                    min = vertexStatusMap[edge.Key.Key].Height;
                }
            }

            vertexStatusMap[vertex.Key].Height = min + 1;
        }
Exemplo n.º 4
0
        /// <summary>
        /// Recursive DFS
        /// </summary>
        /// <param name="currentResidualGraphVertex"></param>
        /// <param name="visited"></param>
        /// <param name="searchVetex"></param>
        /// <returns></returns>
        private void DFS(WeightedDiGraph <T, W> graph,
                         WeightedDiGraphVertex <T, W> currentResidualGraphVertex,
                         HashSet <T> visited)
        {
            visited.Add(currentResidualGraphVertex.Value);

            foreach (var edge in currentResidualGraphVertex.OutEdges)
            {
                if (!visited.Contains(edge.Key.Value))
                {
                    //reachable only if +ive weight (unsaturated edge)
                    if (edge.Value.CompareTo(operators.defaultWeight) != 0)
                    {
                        DFS(graph, edge.Key, visited);
                    }
                }
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Recursive DFS.
        /// </summary>
        private void dfs(WeightedDiGraphVertex <T, W> currentResidualGraphVertex,
                         HashSet <T> visited)
        {
            visited.Add(currentResidualGraphVertex.Key);

            foreach (var edge in currentResidualGraphVertex.OutEdges)
            {
                if (visited.Contains(edge.Key.Key))
                {
                    continue;
                }

                //reachable only if +ive weight (unsaturated edge)
                if (edge.Value.CompareTo(@operator.defaultWeight) != 0)
                {
                    dfs(edge.Key, visited);
                }
            }
        }
        /// <summary>
        /// depth first search to find a path to sink in residual graph from source
        /// </summary>
        /// <param name="residualGraph"></param>
        /// <param name="source"></param>
        /// <param name="sink"></param>
        /// <returns></returns>
        private List <T> DFS(WeightedDiGraph <T, W> residualGraph, T source, T sink)
        {
            //init parent lookup table to trace path
            var parentLookUp = new Dictionary <WeightedDiGraphVertex <T, W>, WeightedDiGraphVertex <T, W> >();

            foreach (var vertex in residualGraph.Vertices)
            {
                parentLookUp.Add(vertex.Value, null);
            }

            //regular DFS stuff
            var stack   = new Stack <WeightedDiGraphVertex <T, W> >();
            var visited = new HashSet <WeightedDiGraphVertex <T, W> >();

            stack.Push(residualGraph.Vertices[source]);
            visited.Add(residualGraph.Vertices[source]);

            WeightedDiGraphVertex <T, W> currentVertex = null;

            while (stack.Count > 0)
            {
                currentVertex = stack.Pop();

                //reached sink? then break otherwise dig in
                if (currentVertex.Value.Equals(sink))
                {
                    break;
                }
                else
                {
                    foreach (var edge in currentVertex.OutEdges)
                    {
                        //visit only if edge have available flow
                        if (!visited.Contains(edge.Key) &&
                            edge.Value.CompareTo(operators.defaultWeight) > 0)
                        {
                            //keep track of this to trace out path once sink is found
                            parentLookUp[edge.Key] = currentVertex;
                            stack.Push(edge.Key);
                            visited.Add(edge.Key);
                        }
                    }
                }
            }

            //could'nt find a path
            if (currentVertex == null || !currentVertex.Value.Equals(sink))
            {
                return(null);
            }

            //traverse back from sink to find path to source
            var path = new Stack <T>();

            path.Push(sink);

            while (currentVertex != null && !currentVertex.Value.Equals(source))
            {
                path.Push(parentLookUp[currentVertex].Value);
                currentVertex = parentLookUp[currentVertex];
            }

            //now reverse the stack to get the path from source to sink
            var result = new List <T>();

            while (path.Count > 0)
            {
                result.Add(path.Pop());
            }

            return(result);
        }