예제 #1
0
        /**
         * Simple breadth first search in the directed graph
         *
         * @param g The directed Graph
         * @param start The object that identifying the start node of the search
         * @param target The object that identifying the target node of the search
         * @param flow A HashMap of the form like getMaxFlow produces them. If an
         * edge has a value > 0 in it, it will also be used in the opposite
         * direction. Also edges that have a value equal to its capacity will be
         * ignored.
         * @return A list of all edges of the found path in the order in which they
         * are used, null if there is no path. If the start node equals the target
         * node, an empty list is returned.
         */
        public LinkedList <EdgeF> bfs(DirectedGraph g, Object start, Object target,
                                      Dictionary <EdgeF, int> flow)
        {
            //-------------------

            // The edge by which a node was reached.
            Dictionary <Object, EdgeF> parent = new Dictionary <Object, EdgeF>(); af++; ffLines++;
            // All outer nodes of the current search iteration.
            LinkedList <Object> fringe = new LinkedList <Object>(); af++; ffLines++;

            //-------------------

            // We need to put the start node into those two.
            parent.Add(start, null); af++; ffLines++;
            fringe.AddLast(start); af++; ffLines++;
            // The actual algorithm
            bool stop = false; af++; ffLines++;

            //-------------------

            compF++; ffLines++;
            while (!fringe.Count.Equals(0))
            {
                ffLines++;
                compF++;
                // This variable is needed to prevent the JVM from having a
                // concurrent modification
                //-------------------

                LinkedList <Object> newFringe = new LinkedList <Object>(); af++; ffLines++;

                //-------------------

                // Iterate through all nodes in the fringe.
                compF++;
                ffLines++;
                foreach (Object nodeID in fringe)
                {
                    ffLines++;
                    compF++;
                    Node nodes = g.getNode(nodeID); af++; ffLines++;
                    // Iterate through all the edges of the node.
                    compF++; af++; ffLines++;
                    for (int i = 0; i < nodes.getOutLeadingOrder(); i++)
                    {
                        compF++; af++; ffLines++;
                        EdgeF e = nodes.getEdge(i); af++; ffLines++;
                        //-------------------

                        // Only add the node if the flow can be changed in an out
                        // leading direction. Also break, if the target is reached.
                        //-------------------

                        compF += 3; ffLines += 3;
                        if (e.getStart().Equals(nodeID) &&
                            !parent.ContainsKey(e.getTarget()) &&
                            flow[e] < e.getCapacity())
                        {
                            parent.Add(e.getTarget(), e); af++; ffLines++;
                            compF++; ffLines++;
                            if (e.getTarget().Equals(target))
                            {
                                stop = true; af++; ffLines++;
                                break;
                            }
                            newFringe.AddLast(e.getTarget()); af++; ffLines++;
                        }
                        else if (e.getTarget().Equals(nodeID) &&
                                 !parent.ContainsKey(e.getStart()) &&
                                 flow[e] > 0)
                        {
                            ffLines++;
                            parent.Add(e.getStart(), e); af++; ffLines++;
                            compF++;
                            ffLines++;
                            if (e.getStart().Equals(target))
                            {
                                stop = true; af++; ffLines++;
                                break;
                            }
                            newFringe.AddLast(e.getStart()); af++; ffLines++;
                        }
                        ffLines++;
                        compF += 3;
                    }
                    ffLines++;
                    compF++;
                    if (stop)
                    {
                        break;
                    }
                }
                compF++; ffLines++;
                if (stop)
                {
                    break;
                }
                // Replace the fringe by the new one.
                fringe = newFringe; af++; ffLines++;
            }
            // Return null, if no path was found.
            compF++; ffLines++;
            if (fringe.Count.Equals(0))
            {
                return(null);
            }
            // If a path was found, reconstruct it.
            Object             node = target; af++; ffLines++;
            LinkedList <EdgeF> path = new LinkedList <EdgeF>(); af++; ffLines++;

            compF++;
            ffLines++;
            while (!node.Equals(start))
            {
                ffLines++;
                compF++;
                EdgeF e = parent[node]; af++; ffLines++;
                path.AddFirst(e); af++; ffLines++;
                compF++;
                ffLines++;
                if (e.getStart().Equals(node))
                {
                    node = e.getTarget(); af++; ffLines++;
                }
                else
                {
                    ffLines++;
                    node = e.getStart(); af++; ffLines++;
                }
            }
            ffLines++;
            // Return the path.
            return(path);
        }
예제 #2
0
        /**
         * This method actually calculates the maximum flow by using the
         * Ford-Fulkerson Algorithm.
         *
         * @param g The directed graph
         * @param source The object identifying the source node of the flow
         * @param sink The object identifying the sink node of the flow
         * @return A HashMap for the edges, giving every edge in the graph a value
         * which shows the part of the edge's capacity that is used by the flow
         */
        // 47 Lineas
        public Dictionary <EdgeF, int> getMaxFlow(DirectedGraph g, Object source,
                                                  Object sink)
        {
            // reset asignation and comparation
            af    = 0;
            compF = 0;

            // The path from source to sink that is found in each iteration
            LinkedList <EdgeF> path; ffLines++;
            // The flow, i.e. the capacity of each edge that is actually used

            //-------------------
            Dictionary <EdgeF, int> flow = new Dictionary <EdgeF, int>(); af++; ffLines++;

            //-------------------

            // Create initial empty flow.

            //-------------------
            compF++; af++;
            foreach (EdgeF e in g.getEdges())
            {
                ffLines++;
                compF++;
                flow.Add(e, 0); af++; ffLines++;
            }
            //-------------------

            // The Algorithm itself
            compF++;
            while ((path = bfs(g, source, sink, flow)) != null)
            {
                ffLines++;
                compF++;
                //-------------------

                // Activating this output will illustrate how the algorithm works
                // System.out.println(path);
                // Find out the flow that can be sent on the found path.

                //-------------------
                int    minCapacity = int.MaxValue; af += 2; ffLines++;
                Object lastNode    = source; ffLines++;
                //-------------------
                compF++; af++;
                foreach (EdgeF edge in path)
                {
                    ffLines++;
                    compF++;
                    int c; ffLines++;
                    //-------------------
                    // Although the edges are directed they can be used in both
                    // directions if the capacity is partially used, so this if
                    // statement is necessary to find out the edge's actual
                    // direction.

                    //-------------------
                    compF++;
                    ffLines++;
                    if (edge.getStart().Equals(lastNode))
                    {
                        c        = edge.getCapacity() - flow[edge]; af++; ffLines++;
                        lastNode = edge.getTarget(); af++; ffLines++;
                    }
                    //-------------------
                    else
                    {
                        ffLines++;
                        c        = flow[edge]; af++; ffLines++;
                        lastNode = edge.getStart(); af++; ffLines++;
                    }
                    //-------------------
                    compF++;
                    ffLines++;
                    if (c < minCapacity)
                    {
                        minCapacity = c; af++; ffLines++;
                    }
                }

                // Change flow of all edges of the path by the value calculated
                // above.

                //-------------------
                lastNode = source; af++; ffLines++;
                //-------------------

                compF++; af++;
                foreach (EdgeF edge in path)
                {
                    ffLines++;
                    compF++;
                    // If statement like above
                    //-------------------
                    compF++;
                    ffLines++;
                    if (edge.getStart().Equals(lastNode))
                    {
                        flow[edge] = flow[edge] + minCapacity; af++; ffLines++;
                        lastNode   = edge.getTarget(); af++; ffLines++;
                    }
                    else
                    {
                        ffLines++;
                        flow.Add(edge, flow[edge] - minCapacity); af++; ffLines++;
                        lastNode = edge.getStart(); af++; ffLines++;
                    }
                }
            }
            ffLines++;
            return(flow);
        }