private void ENUM_MAXIMUM_MATCHINGS(BipartiteGraph G, bool getAllMatchings)
        {
            /*-------------------------------------------------------------------------------------------------------------------
             * Step1: Find a maximum matching M of G and output M.
             * ------------------------------------------------------------------------------------------------------------------*/
            EdgeList     M        = MaximumMatching.Get(G);  //Edges of Matching
            MatchingList matching = EdgeListToMatching(M);

            matching.Sort();

            FindOverconstrainedModelsReversalCost(matching);
            if (OverConstrainedModels.Count > 0)
            {
                OverConstrained = true;
                return;
            }

            AddMatching(matching);
            if (MinimumCost > minimumAchievableCost)
            {
                /*-------------------------------------------------------------------------------------------------------------------
                 * Step2: Trim unnecessary arcs from D(G,M) by a strongly connected component decomposition algorithm.
                 * ------------------------------------------------------------------------------------------------------------------*/
                //Need further action on this to trim edges after finding SCCs in a D(G,M). Here only SCCs are found. Edges are not trimmed yet.
                //Graph D_GM = Get_D_GM(G.Clone(), M); //Directed graph is obtained here with reversing edges of matchingEdges.
                //List<List<GraphNode>> sCCs = TarjanCycleDetect.DetectCycle(D_GM);


                /*-------------------------------------------------------------------------------------------------------------------
                 * Step3: Call ENUM_MAXIMUM_MATCHINGS_ITER(G, M, D(G,M))
                 * ------------------------------------------------------------------------------------------------------------------*/
                if (getAllMatchings)
                {
                    ENUM_MAXIMUM_MATCHINGS_ITER(G.Clone(), M, matching, 0);
                }
            }

            FilterDuplicateMatchings();
        }
        //This method find the corresponding edges of matching M(which contains edges from other Graph) for the given Graph G
        private static EdgeList CorrespondingEdgeList(BipartiteGraph G, EdgeList M)
        {
            var corresponding = new EdgeList();

            foreach (Edge edge in M)
            {
                GraphNode from = G.GetNode(edge.FromNode.Value);
                GraphNode to   = G.GetNode(edge.ToNode.Value);
                if (from == null && to == null)
                {
                    continue;
                }

                if (G.Edges.FindByNodes(from, to) != null)
                {
                    corresponding.Add(G.Edges.FindByNodes(from, to));
                }
                else
                {
                    corresponding.Add(G.Edges.FindByNodes(to, from));
                }
            }
            return(corresponding);
        }
        private EdgeList MatchingToEdgeList(BipartiteGraph G, MatchingList M_String)
        {
            var edgeList = new EdgeList();

            foreach (string edg in M_String)
            {
                GraphNode node1 = G.GetNode(edg.Split('-')[0]);
                GraphNode node2 = G.GetNode(edg.Split('-')[1]);
                if (G.Contains(node1, node2))
                {
                    edgeList.Add(G.Edges.FindByNodes(node1, node2));
                }
                else if (G.Contains(node2, node1))
                {
                    edgeList.Add(G.Edges.FindByNodes(node2, node1));
                }
                //else
                //{
                //    M_to_EdgeListM.Add(new Edge(nd1,nd2,0));
                //}
            }

            return(edgeList);
        }
Ejemplo n.º 4
0
        private static EdgeList CorrespondingListForTheGraph(BipartiteGraph G, EdgeList M) //This method find the corresponding edges of matching M(which contains edges from other Graph) for the given Graph G
        {
            var M_corresp = new EdgeList();

            foreach (Edge edg in M)
            {
                GraphNode frm = G.GetNode(edg.FromNode.Value);
                GraphNode to  = G.GetNode(edg.ToNode.Value);
                if (frm == null && to == null)
                {
                    goto xyz;
                }
                if (G.Edges.FindByNodes(frm, to) != null)
                {
                    M_corresp.Add(G.Edges.FindByNodes(frm, to));
                }
                else
                {
                    M_corresp.Add(G.Edges.FindByNodes(to, frm));
                }
                xyz :;
            }
            return(M_corresp);
        }
Ejemplo n.º 5
0
 //Here matching edges nodes are checked if it is model or variable
 //And then directed graph is created, where matching edges are oriented from model to variable whereas,
 //other graph edges(original graph edges) are from variable to model.
 public BipartiteGraph GetDirectedGraphAsPerMatching(EdgeList M)
 {
     foreach (Edge edge in M)
     {
         GraphNode from = edge.FromNode;
         GraphNode to   = edge.ToNode;
         if (from != null && to != null)
         {
             if (from.NodeType == GraphNode.Type.Type2)
             {
                 if (Contains(from, to))
                 {
                     RemoveDirectedEdge(to, from);
                 }
                 else if (Contains(to, from))
                 {
                     RemoveDirectedEdge(to, from);
                     AddDirectedEdge(from, to, 0, 0);
                 }
             }
             else
             {
                 if (Contains(from, to))
                 {
                     RemoveDirectedEdge(from, to);
                     AddDirectedEdge(to, from, 0, 0);
                 }
                 else if (Contains(to, from))
                 {
                     RemoveDirectedEdge(from, to);
                 }
             }
         }
     }
     return(this);
 }
        //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);
            }
        }
Ejemplo n.º 7
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
        }
        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);
        }
Ejemplo n.º 9
0
        }                                                      //here this class constructor is called with inputs as null nodeSet and edgeSet. Here NodeList and EdgeList are created if they are null

        public BipartiteGraph(NodeList nodeSet, EdgeList edgeSet)
        {
            Nodes = nodeSet ?? new NodeList();
            Edges = edgeSet ?? new EdgeList();
        }