Example #1
0
        private void ENUM_PERFECT_MATCHINGS_ITER(BipartiteGraph G, EdgeList M, List <string> M_String)
        {
            /*-------------------------------
             * Step1: If G has no edge, stop.
             * ---------------------------------*/

            if (G.Edges.Count == 0)
            {
                return;
            }

            /*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
             * Step2 & Step3: Choosing Edge-e and Finding Cycle. //Cycle is found using DFS algorithm and edge-e is chosen such that it is in cycle and in matching M ( and not in M'(which is found next)) of the directed graph(DG)
             * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/

            BipartiteGraph d_G  = G.Clone().GetDirectedGraphAsPerMatching(M);
            var            CIDG = new CycleInDirectedGraph(d_G); //Class object containing Method to detect and get cycle in a grah

            if (!CIDG.HasCycle)
            {
                return;
            }
            List <GraphNode> cycleInDG = CIDG.Cycle;                         //returns here cycle in a directed graph DG
            //Cycle: Vertices can not repeate and Edges can not repeat
            EdgeList      cycleInDG_Edges          = d_G.ToEdges(cycleInDG); //cycleInDG is list of nodes in a Cycle . Here this list is converted into edges in the Cycle.
            List <string> cycleInDG_EdgesAsStrings = d_G.ToEdgesAsStrings(cycleInDG);
            EdgeList      M_corresp = CorrespondingListForTheGraph(d_G, M);
            Edge          e         = chooseEdge(M_corresp, cycleInDG_Edges); //Edge - e is chosen here.
            ////String e_string = chooseEdgeStringVersion(M_String, cycleInDG_EdgesAsStrings); //Edge - e is chosen here.

            /*---------------------------------------------------------------------------------
             * Step4: Find a perfect matching M' by exchanging edges along the cycle. Output M'.
             * ------------------------------------------------------------------------------------*/

            EdgeList      M_dash        = ExchangingEdgesAlongCycle(M_corresp, cycleInDG_Edges);                          /* Write code here to find M' here */
            List <string> M_dash_String = ExchangingEdgesAlongCycleStringVersion(M_String, cycleToStringList(cycleInDG)); //this.matchingToStringList(M)

            //list_PerfectMatchings.Add(M_dash);
            list_AllPerfectMatchings.Add(M_dash_String);



            /*-----------------------------------------------------------------------------------------
             * Step5: Find G+(e), trim unnecessary edges of G+(e) using SCC decomposition algorithm.
             * ------------------------------------------------------------------------------------------*/

            //Graph<T> G_plus = G_plus_e(DG.Clone(), e); //G+(e) is obtained here
            BipartiteGraph           G_plus      = G_plus_e(G.Clone(), e);
            List <List <GraphNode> > sCCs_G_plus = TarjanCycleDetect.DetectCycle(G_plus); // /SCCs in G+(e) to trim unnecessary edges

            /* Write code for trimming edges here*/

            /*-----------------------------------------------------------------------------------------------------------
             * Step6: Enumerate all perfect matchings including e by ENUM_PERFECT_MATCHING_ITER with obtained graph and M
             * ------------------------------------------------------------------------------------------------------------*/

            ENUM_PERFECT_MATCHINGS_ITER(G_plus, M, M_String); //recursive call with G+(e) and M  // !! here G+(e) graph will not have edge which is there in matching

            /*-----------------------------------------------------------------------------------------
            *  Step7: Find G-(e), trim unnecessary edges of G-(e) using SCC decomposition algorithm.
            *  -----------------------------------------------------------------------------------------*/

            BipartiteGraph G_minus = G_minus_e(G.Clone(), e);                               //G+(e) is obtained here
            ////G_minus.plotMethod(this.goView1);
            List <List <GraphNode> > sCCs_G_minus = TarjanCycleDetect.DetectCycle(G_minus); // SCCs in G-(e) to trim unnecessary edges

            /* Write code for trimming edges here*/


            /*---------------------------------------------------------------------------------------------------------------
            *  Step8: Enumerate all perfect matchings not including e by ENUM_PERFECT_MATCHING_ITER with obtained graph and M'
            *  ---------------------------------------------------------------------------------------------------------------*/

            ENUM_PERFECT_MATCHINGS_ITER(G_minus, matchingStringsToEdgeList(G_minus, M_dash_String), M_dash_String); //recursive call with G+(e) and M
        }
        //This code has been tested and works fine for test-case under consideration
        private void ENUM_MAXIMUM_MATCHINGS_ITER(BipartiteGraph G, EdgeList M, MatchingList matching, int recursionLevel)
        {
            //System.Console.WriteLine(recursionLevel);			//System.Console.WriteLine(recursionLevel);
            if (recursionLevel >= MaximumRecursionLevel)
            {
                return;
            }

            /*-------------------------------------------------------------------------------------------------------------------
             * Step1: If G has no edge, stop.
             * ------------------------------------------------------------------------------------------------------------------*/
            if (G.Edges.Count <= 1)
            {
                return;
            }


            /*-------------------------------------------------------------------------------------------------------------------
             * Step2: If D(G,M) contains no cylce, Go to Step8.
             * ------------------------------------------------------------------------------------------------------------------*/
            BipartiteGraph directedGraph = G.Clone().GetDirectedGraphAsPerMatching(M);
            var            CIDG          = new CycleInDirectedGraph(directedGraph); //Class object containing Method to detect and get cycle in a grah
            Edge           e;
            MatchingList   Mdash;
            BipartiteGraph Gplus, Gminus;

            if (CIDG.HasCycle)
            {
                /*-------------------------------------------------------------------------------------------------------------------
                 * Step3 & 4: Choose an edge e as the same manner in ENUM_PERFECT_MATCHINGS_ITER.
                 * Find a cycle containing e by a depth-first-search algorithm.
                 * ------------------------------------------------------------------------------------------------------------------*/
                // Cycle is found using DFS algorithm and edge-e is chosen such that it is in cycle and in matching M
                // ( and not in M'(which is found next)) of the directed graph(DG)
                List <GraphNode> cycle      = CIDG.Cycle;                   //returns here cycle in a directed graph DG //'Cycle': Vertices can not repeate and Edges can not repeat
                EdgeList         cycleEdges = directedGraph.ToEdges(cycle); //cycleInDG is list of nodes in a Cycle . Here this list is converted into edges in the Cycle.
                EdgeList         MEdgeList  = CorrespondingEdgeList(directedGraph, M);
                e = ChooseEdge(MEdgeList, cycleEdges);                      //Edge - e is chosen here.


                /*-------------------------------------------------------------------------------------------------------------------
                 * Step5: Exchange edges along the cycle and output the obtained maximum matching M'.
                 * ------------------------------------------------------------------------------------------------------------------*/
                Mdash = ExchangeEdgesAlongCycleOrPath(matching, CycleToMatching(cycle));                //this.matchingToStringList(M)
                Mdash.Sort();

                AddMatching(Mdash);
                if (MinimumCost > minimumAchievableCost)
                {
                    /*-------------------------------------------------------------------------------------------------------------------
                     * Step6: Enumerate all maximum matchings including e by ENUM_MAXIMUM_MATCHINGS_ITER with G+(e), M and trimmed D(G+(e), M\e).
                     * ------------------------------------------------------------------------------------------------------------------*/
                    Gplus = BuildGplus(G, e);                                            //G+(e) is obtained here //!! here G+(e) graph will not have edge which is there in matching
                    ENUM_MAXIMUM_MATCHINGS_ITER(Gplus, M, matching, recursionLevel + 1); //recursive call with G+(e) and M


                    /*-------------------------------------------------------------------------------------------------------------------
                     * Step7: Enumerate all maximum matchings not including e by ENUM_MAXIMUM_MATCHINGS_ITER with G-(e), M' and trimmed D(G-(e), M'). Stop.
                     * ------------------------------------------------------------------------------------------------------------------*/
                    Gminus = BuildGminus(G, e);                                                                        //G-(e) is obtained here
                    ENUM_MAXIMUM_MATCHINGS_ITER(Gminus, MatchingToEdgeList(Gminus, Mdash), Mdash, recursionLevel + 1); //recursive call with G-(e) and M
                }

                return;
            }


            /*----------------------------------------------------------------------------------------------------------------------
             * Step8: Find a feasible path with length 2 and generate a new maximum matching M'.
             * Let e be the edge of the path not included in M.
             * ------------------------------------------------------------------------------------------------------------------*/
            //'Feasible Path':
            NodeList unmatchedVertices = directedGraph.GetUnmatchedVertices(matching);
            var      path = new MatchingList();

            foreach (GraphNode node in directedGraph)
            {
                if (node.NodeType == GraphNode.Type.Type1 || node.NodeType == GraphNode.Type.Type2 && !unmatchedVertices.Contains(node))
                {
                    var dfs = new DepthFirstSearch(directedGraph, node, unmatchedVertices);
                    path = dfs.length2Path;
                    if (path.Count == 3 && IsFeasiblePath(directedGraph, path, unmatchedVertices))
                    {
                        break;
                    }
                }
            }

            if (path.Count != 3)
            {
                return;
            }

            e     = GetEdgeInPathNotInM(G, matching, PathToMatching(G, path));
            Mdash = ExchangeEdgesAlongCycleOrPath(matching, PathToMatching(G, path));
            Mdash.Sort();

            AddMatching(Mdash);
            if (MinimumCost > minimumAchievableCost)
            {
                /*-------------------------------------------------------------------------------------------------------------------
                 * Step9: Call ENUM_MAXIMUM+MATCHINGS_ITER(G+(e), M', theta).
                 *      -* ------------------------------------------------------------------------------------------------------------------*/
                Gplus = BuildGplus(G, e);                 //G+(e) is obtained here
                ENUM_MAXIMUM_MATCHINGS_ITER(Gplus, MatchingToEdgeList(Gplus, Mdash), Mdash, recursionLevel + 1);


                /*-------------------------------------------------------------------------------------------------------------------
                 * Step10: Call ENUM_MAXIMUM+MATCHINGS_ITER(G-(e), M, theta).
                 * ------------------------------------------------------------------------------------------------------------------*/
                Gminus = BuildGminus(G, e);                 //G-(e) is obtained here
                ENUM_MAXIMUM_MATCHINGS_ITER(Gminus, M, matching, recursionLevel + 1);
            }
        }
        private void ENUM_MAXIMUM_MATCHINGS_ITER(BipartiteGraph G, EdgeList M, List <String> M_String, int recursionLevel)
        {
            if (recursionLevel > MaximumRecursionLevel)
            {
                return;
            }

            //This code has been tested and works fine for test-case under consideration

            /*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
             * Step1: If G has no edge, stop.
             * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
            if (G.Edges.Count <= 1)
            {
                return;
            }



            /*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
             * Step2: If D(G,M) contains no cylce, Go to Step8.
             * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
            BipartiteGraph d_G  = G.Clone().GetDirectedGraphAsPerMatching(M);
            var            CIDG = new CycleInDirectedGraph(d_G); //Class object containing Method to detect and get cycle in a grah

            if (!CIDG.HasCycle)
            {
                goto Step8;
            }



            /*--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
             * Step3 & 4: Choose an edge e as the same manner in ENUM_PERFECT_MATCHINGS_ITER. Find a cycle containing e by a depth-first-search algorithm.
             * ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
            //Cycle is found using DFS algorithm and edge-e is chosen such that it is in cycle and in matching M ( and not in M'(which is found next)) of the directed graph(DG)
            List <GraphNode> cycleInDG                = CIDG.Cycle;             //returns here cycle in a directed graph DG //'Cycle': Vertices can not repeate and Edges can not repeat
            EdgeList         cycleInDG_Edges          = d_G.ToEdges(cycleInDG); //cycleInDG is list of nodes in a Cycle . Here this list is converted into edges in the Cycle.
            List <String>    cycleInDG_EdgesAsStrings = d_G.ToEdgesAsStrings(cycleInDG);
            EdgeList         M_corresp                = CorrespondingListForTheGraph(d_G, M);
            Edge             e = chooseEdge(M_corresp, cycleInDG_Edges); //Edge - e is chosen here.



            /*--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
             * Step5: Exchange edges along the cycle and output the obtained maximum matching M'.
             * ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
            List <String> M_dash_String = ExchangingEdgesAlongCycleOrPathStringVersion(M_String, cycleToStringList(cycleInDG));//this.matchingToStringList(M)

            M_dash_String.Sort();
            list_AllMaximumMatchings.Add(M_dash_String);



            /*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
             * Step6: Enumerate all maximum matchings including e by ENUM_MAXIMUM_MATCHINGS_ITER with G+(e), M and trimmed D(G+(e), M\e).
             * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
            BipartiteGraph G_plus = G_plus_e(G.Clone(), e);

            ENUM_MAXIMUM_MATCHINGS_ITER(G_plus, M, M_String, ++recursionLevel); //recursive call with G+(e) and M  // !! here G+(e) graph will not have edge which is there in matching



            /*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
             * Step7: Enumerate all maximum matchings not including e by ENUM_MAXIMUM_MATCHINGS_ITER with G-(e), M' and trimmed D(G-(e), M'). Stop.
             * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
            BipartiteGraph G_minus = G_minus_e(G.Clone(), e);                                                                         //G-(e) is obtained here

            ENUM_MAXIMUM_MATCHINGS_ITER(G_minus, matchingStringsToEdgeList(G_minus, M_dash_String), M_dash_String, ++recursionLevel); //recursive call with G-(e) and M
            return;



            /*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
             * Step8: Find a feasible path with length 2 and generate a new maximum matching M'. Let e be the edge of the path not included in M.
             * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
            //'Feasible Path':
            Step8 :;
            NodeList unmatchedVertices = d_G.GetUnmatchedVertices(M_String);
            var      path = new List <String>();

            foreach (GraphNode Gn in d_G)
            {
                if (Gn.NodeType == GraphNode.Type.Type1)
                {
                    var dfs = new DepthFirstSearch(d_G, Gn, unmatchedVertices);
                    path = dfs.length2Path;
                    if (path.Count == 3 && isFeasiblePath(d_G, path, unmatchedVertices))
                    {
                        break;
                    }
                }
                if ((Gn.NodeType == GraphNode.Type.Type2) && !(unmatchedVertices.Contains(Gn)))
                {
                    var dfs = new DepthFirstSearch(d_G, Gn, unmatchedVertices);
                    path = dfs.length2Path;
                    if (path.Count == 3 && isFeasiblePath(d_G, path, unmatchedVertices))
                    {
                        break;
                    }
                }
            }

            if (path.Count != 3)
            {
                return;
            }

            e = getEdgeInPathNotInM(G, M_String, pathToEdgesAsStrings(G, path));

            M_dash_String = ExchangingEdgesAlongCycleOrPathStringVersion(M_String, pathToEdgesAsStrings(G, path));
            M_dash_String.Sort();
            list_AllMaximumMatchings.Add(M_dash_String);


            /*--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
             * Step9: Call ENUM_MAXIMUM+MATCHINGS_ITER(G+(e), M', theta).
             * ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
            G_plus = G_plus_e(G.Clone(), e);
            ENUM_MAXIMUM_MATCHINGS_ITER(G_plus, matchingStringsToEdgeList(G_plus, M_dash_String), M_dash_String, ++recursionLevel);



            /*--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
            *  Step10: Call ENUM_MAXIMUM+MATCHINGS_ITER(G-(e), M, theta).
            *  --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/

            G_minus = G_minus_e(G.Clone(), e); //G-(e) is obtained here
            ENUM_MAXIMUM_MATCHINGS_ITER(G_minus, M, M_String, ++recursionLevel);
        }