コード例 #1
0
        /// <summary>
        /// Parse the given string into a matching instance.
        /// </summary>
        /// <param name="Input"></param>
        /// <returns></returns>
        private Instance Parse(string Input)
        {
            string[] Prios = Input.Split('-');
            List<Tuple<int, int>>[] PrioList = new List<Tuple<int, int>>[Prios.Length - 1];
            List<int> Posts = new List<int>();
            for (int i = 0; i < Prios.Length - 1; i++)
            {
                PrioList[i] = new List<Tuple<int, int>>();
                string[] Targets = Prios[i].Split(',');
                int RankCounter = 0;
                foreach (string Target in Targets)
                {
                    string[] Parts = Target.Split('.');
                    int ID = int.Parse(Parts[0]);
                    int Rank;
                    if (Parts.Length == 1)
                        Rank = RankCounter++;
                    else
                        Rank = int.Parse(Parts[1]);
                    PrioList[i].Add(new Tuple<int, int>(ID, Rank));
                    if (!Posts.Contains(ID))
                        Posts.Add(ID);
                }
            }
            int Capacity = int.Parse(Prios[Prios.Length - 1]);
            Instance Result = new Instance(Prios.Length - 1, Posts.Count, Capacity, PrioList);

            return Result;
        }
コード例 #2
0
        /// <summary>
        /// Prints the given instance into a string.
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private string Output(Instance input)
        {
            string Result = "";
            if (input == null)
                Result = "No popular matching.";
            else
            {
                int[] Matching = new int[input.Applicants.Length];
                for (int i = 0; i < input.Posts.Length; i++)
                {
                    if (input.Posts[i].NrMatchings > 0)
                        Matching[input.Posts[i].Matchings[0]] = i;
                }

                for (int j = 0; j < Matching.Length; j++)
                {
                    Result += j.ToString() + " -> " + Matching[j].ToString() + ";  ";
                }
            }

            return Result;
        }
コード例 #3
0
        public SwitchingGraph(Instance instance)
        {
            BaseInstance = instance;
            Component.statID = 0;
            Nodes = new List<Node>();
            foreach (Instance.Post p in instance.Posts)
            {
                Node Temp = new Node(p);
                Nodes.Add(Temp);
            }

            int Counter = 0;
            foreach (Instance.Post p in instance.Posts)
            {
                // create edges in the switching graph
                if (p.Matchings.Count > 0)
                {
                    Instance.Applicant Partner = instance.Applicants[p.Matchings[0]];
                    Node Start;
                    Node End;
                    if (instance.Posts[Partner.Priorities[0].Target].ID == p.ID && Partner.Priorities[0].Rank == 0)
                    {
                        Start = Nodes[Counter];
                        Start.IsS = false;
                        End = Nodes[Partner.Priorities[1].Target];
                        End.IsS = true;
                    }
                    else
                    {
                        Start = Nodes[Counter];
                        Start.IsS = true;
                        End = Nodes[Partner.Priorities[0].Target];
                        End.IsS = false;
                    }
                    Nodes[Counter].Outgoing.Add(new Edge(Start, End, Partner));
                }
                Counter++;
            }

            IdentifiyComponents();
        }
コード例 #4
0
 public Edge(Node start, Node end, Instance.Applicant app)
 {
     Applicant = app;
     Start = start;
     End = end;
 }
コード例 #5
0
        /// <summary>
        /// Check for applicant complete matching
        /// </summary>
        /// <param name="instance"></param>
        /// <returns></returns>
        private Instance GetApplicantComplete(Instance instance)
        {
            List<int>[] Suitors = new List<int>[instance.Posts.Length];
            for (int i = 0; i < instance.Posts.Length; i++)
            {
                Suitors[i] = new List<int>();
            }

            // create suitors list
            for (int i = 0; i < instance.Applicants.Length; i++)
            {
                for (int j = 0; j < instance.Applicants[i].Priorities.Count; j++)
                {
                    Suitors[instance.Applicants[i].Priorities.ElementAt(j).Target].Add(i);
                }
            }

            int Unmatched = instance.Posts.Length; // # of not full posts
            int UnmatchedApplicants = instance.Applicants.Length; // # unmatched applicants

            for (int i = 0; i < instance.Posts.Length; i++)
            {
                // if a post is connected to only one not matched applicant, match this
                if (Suitors[i].Count == 1 && !instance.Posts[i].Matched && !instance.Applicants[Suitors[i].ElementAt(0)].Matched)
                {
                    instance.Posts[i].Matched = true;
                    instance.AddMatch(i, Suitors[i].ElementAt(0));
                    UnmatchedApplicants--;
                    int Applicant = Suitors[i].ElementAt(0);
                    for (int j = 0; j < instance.Posts.Length; j++)
                    {
                        Suitors[j].Remove(Applicant);
                    }
                }
            }

            for (int i = 0; i < instance.Posts.Length; i++)
            {
                // delete not connected posts
                if (Suitors[i].Count == 0)
                {
                    instance.Posts[i].Matched = true;
                    Unmatched--;
                }
            }


            // check if there is enough space for the remaining applicants
            if (Unmatched < UnmatchedApplicants)
                return null;
            else
            {
                // if yes, walk over the disjoint cycle and take every second edge
                for (int i = 0; i < instance.Applicants.Length; i++)
                {
                    instance = GoPath(instance, i);
                    if (instance == null)
                        instance = null;
                }
            }

            return instance;
        }
コード例 #6
0
        public Instance Match(Instance instance, string path, bool print)
        {
            Instance oldcopy = instance.Copy();

            if (!System.IO.Directory.Exists(path) && print)
                System.IO.Directory.CreateDirectory(path);

            if (print)
            {
                Bitmap Bmp1 = instance.Draw();
                Bmp1.Save(path + "/0Start.bmp");
                Bmp1.Dispose();
            }

            instance = GetReduced(instance);

            if (print)
            {
                Bitmap Bmp2 = instance.Draw();
                Bmp2.Save(path + "/1Reduced.bmp");
                Bmp2.Dispose();
            }

            if (print)
            {
                Bitmap Bmp3 = instance.Draw();
                Bmp3.Save(path + "/2Inflated.bmp");
                Bmp3.Dispose();
            }


            // check for applicant-complete matching
            instance = GetApplicantComplete(instance);

            if (instance == null)
            {

                if (print)
                {
                    Bitmap Result = new Bitmap(1000, 1000);
                    Graphics G = Graphics.FromImage(Result);
                    Pen P = new Pen(new SolidBrush(Color.Black));
                    G.DrawString("No Popular Matching", new Font("Arial", 36), new SolidBrush(Color.Black), 100, 100);
                    Result.Save(path + "/3NoPop.bmp");
                    G.Dispose();
                    Result.Dispose();
                }
                return null;
            }
            else
            {
                if (print)
                {
                    Bitmap Bmp4 = instance.Draw();
                    Bmp4.Save(path + "/3ApplicantComplete.bmp");
                    Bmp4.Dispose();
                }
            }

            List<int>[] FPosts = new List<int>[instance.Posts.Length];

            for (int i = 0; i < instance.Posts.Length; i++)
            {
                FPosts[i] = new List<int>();
            }

            for (int i = 0; i < instance.Applicants.Length; i++)
            {
                FPosts[instance.Applicants[i].Priorities.ElementAt(0).Target].Add(i);
            }

            for (int i = 0; i < instance.Posts.Length; i++)
            {
                if (FPosts[i].Count > 0 && instance.Posts[i].NrMatchings == 0)
                {
                    instance.DeleteMatch(FPosts[i][0]);
                    instance.AddMatch(i, FPosts[i][0]);
                }
            }

            if (print)
            {
                Bitmap Bmp4 = instance.Draw();
                Bmp4.Save(path + "/4AllFPostsMatched.bmp");
                Bmp4.Dispose();
            }

            return instance;
        }
コード例 #7
0
 public Instance Copy()
 {
     Instance result = new Instance(n, m);
     for (int i = 0; i < Applicants.Length; i++)
     {
         result.Applicants[i] = new Applicant(i);
         for (int j = 0; j < Applicants[i].Priorities.Count; j++)
         {
             result.Applicants[i].Priorities.Add(new Priority(Applicants[i].Priorities[j].Target, Applicants[i].Priorities[j].Rank));
         }
     }
     for (int i = 0; i < Posts.Length; i++)
     {
         result.Posts[i] = new Post(i, Posts[i].Capacity);
     }
     return result;
 }
コード例 #8
0
        /// <summary>
        /// Recursively create all possible instances by creating all possible combinations of priority lists.
        /// </summary>
        /// <param name="depth"></param>
        /// <param name="n"></param>
        /// <param name="seeds"></param>
        /// <param name="start"></param>
        /// <param name="print"></param>
        /// <param name="path"></param>
        private void RecPrios(int depth, int n, List<int> seeds, int start, bool print, string path)
        {
            if (depth < n)
            {
                // call the next level with every possible priority configuration
                for (int a = 0; a < (int)Factorial((ulong)(n)); a++)
                {
                    List<int> dummy = Copy(seeds);
                    dummy.Add(a);
                    RecPrios(depth + 1, n, dummy, a, print, path);
                }
            }
            else
            {
                // if final level reached, create instance
                List<Tuple<int, int>>[] Prios = new List<Tuple<int, int>>[n];
                for (int i = 0; i < n; i++)
                {
                    Prios[i] = new List<Tuple<int, int>>();
                }

                for (int i = 0; i < n; i++)
                {
                    for (int x = 0; x < Perms[seeds[i]].Count; x++)
                    {
                        Prios[i].Add(new Tuple<int, int>(Perms[seeds[i]][x], x));
                    }
                }

                Instance Temp = new Instance(n, n, 1, Prios);


                // check for popular matching
                Temp = ChosenSolver.Match(Temp, path, print);

                // multiply this value by Factor, since the first applicant always gets the same priority seed - this way, a permutation less has to be examined
                double Factor = Factorial((ulong)n);

                if (Temp == null)
                {
                    NotPop += (long)Factor;
                }

                CC += (long)Factor;
            }
        }
コード例 #9
0
        private Instance GetReduced(Instance instance)
        {
            for (int i = 0; i < instance.n; i++)
            {
                int HighestSecond = int.MaxValue;

                for (int j = 0; j < instance.Applicants[i].Priorities.Count; j++)
                {
                    if (instance.Applicants[i].Priorities.ElementAt(j).Rank != 0 && instance.Posts[instance.Applicants[i].Priorities.ElementAt(j).Target].Type != 1)
                    {
                        instance.Applicants[i].Priorities.RemoveAt(j);
                        j--;
                    }
                    else
                    {
                        if (instance.Applicants[i].Priorities[j].Rank < HighestSecond && instance.Posts[instance.Applicants[i].Priorities[j].Target].Type == 1)
                        {
                            HighestSecond = (instance.Applicants[i].Priorities[j].Rank);
                        }
                    }
                }

                for (int j = 0; j < instance.Applicants[i].Priorities.Count; j++)
                {
                    if (instance.Applicants[i].Priorities.ElementAt(j).Rank > HighestSecond)
                    {
                        instance.Applicants[i].Priorities.RemoveAt(j);
                        j--;
                    }
                }

            }

            // now every applicant has only 2 edges, to his f- and s-post
            return instance;

        }
コード例 #10
0
        private Instance DeleteEdges(Instance instance)
        {
            for (int i = 0; i < instance.Applicants.Length; i++)
            {
                for (int j = 0; j < instance.Applicants[i].Priorities.Count; j++)
                {
                    if ((instance.Applicants[i].Type == 0 && instance.Posts[instance.Applicants[i].Priorities[j].Target].Type == 0) || (instance.Applicants[i].Type == 0 && instance.Posts[instance.Applicants[i].Priorities[j].Target].Type == 2) || (instance.Applicants[i].Type == 2 && instance.Posts[instance.Applicants[i].Priorities[j].Target].Type == 0))
                    {
                        instance.Applicants[i].Priorities.RemoveAt(j);
                        j--;
                    }

                }
            }
            return instance;
        }
コード例 #11
0
        public Instance Match(Instance instance, string path, bool print)
        {
            if (!System.IO.Directory.Exists(path) && print)
                System.IO.Directory.CreateDirectory(path);

            if (print)
            {
                Bitmap Bmp1 = instance.Draw();
                Bmp1.Save(path + "/0Start.bmp");
                Bmp1.Dispose();
            }

            instance = Inflate(instance);

            if (print)
            {
                Bitmap Bmp1 = instance.Draw();
                Bmp1.Save(path + "/1Inflated.bmp");
                Bmp1.Dispose();
            }

            instance = MaxMatching(instance, 0);

            if (print)
            {
                Bitmap Bmp1 = instance.Draw();
                Bmp1.Save(path + "/2FirstMax.bmp");
                Bmp1.Dispose();
            }

            instance = DetermineTypes(instance);

            if (print)
            {
                Bitmap Bmp3 = instance.Draw();
                Bmp3.Save(path + "/3Types.bmp");
                Bmp3.Dispose();

            }

            instance = GetReduced(instance);

            if (print)
            {
                Bitmap Bmp4 = instance.Draw();
                Bmp4.Save(path + "/4Reduced.bmp");
                Bmp4.Dispose();

            }

            instance = DeleteEdges(instance);

            if (print)
            {
                Bitmap Bmp5 = instance.Draw();
                Bmp5.Save(path + "/5EdgesDeleted.bmp");
                Bmp5.Dispose();
            }

            instance = MaxMatching(instance, -1);

            if (print)
            {
                Bitmap Bmp6 = instance.Draw();
                Bmp6.Save(path + "/6GeneralMaxMatching.bmp");
                Bmp6.Dispose();

            }

            for (int i = 0; i < instance.Applicants.Length; i++)
            {
                if (!instance.Applicants[i].Matched)
                {
                    if (print)
                    {
                        Bitmap Bmp7 = instance.Draw();
                        Bmp7.Save(path + "/7NoPopularMatching.bmp");
                        Bmp7.Dispose();
                    }
                    return null;
                }
            }

            return instance;
        }
コード例 #12
0
        private void button1_Click(object sender, EventArgs e)
        {
            textBox2.Text = "";
            string Input = textBox1.Text.Replace(" ", "");

            Instance Test = Parse(Input);

            Instance Result;
            if (radioButton1.Checked)
            {
                PopSolver poppi = new PopSolver();
                Result = poppi.Match(Test, Path, checkBox1.Checked);
            }
            else
            {
                PopSolver2 poppi = new PopSolver2();
                Result = poppi.Match(Test, Path, checkBox1.Checked);
            }
            textBox2.Text = Output(Result);
            GlobalResult = Result;
        }
コード例 #13
0
        /// <summary>
        /// DFS to find an augmenting path
        /// </summary>
        /// <param name="graph"></param>
        /// <param name="inst"></param>
        /// <returns></returns>
        private List<int> DFS(DirectedGraph graph, Instance inst)
        {
            Stack<DirectedGraph.Node> Stack = new Stack<DirectedGraph.Node>();

            for (int i = 0; i < graph.Nodes.Count; i++)
            {
                if (graph.Nodes[i].Type == 0 && !inst.Applicants[graph.Nodes[i].ID - inst.Posts.Length].Matched)
                {
                    Stack.Push(graph.Nodes[i]);
                }
            }

            while (Stack.Count > 0)
            {
                DirectedGraph.Node n = Stack.Pop();
                if (n.Type == 1 && inst.Posts[n.ID].NrMatchings == 0)
                {
                    List<int> Path = new List<int>();
                    DirectedGraph.Node Current = n;
                    Path.Insert(0, n.ID);
                    while (Current.PrevId != -1)
                    {
                        Current = graph.Nodes[Current.PrevId];
                        if (Current.Type == 0)
                            Path.Insert(0, Current.ID - inst.Posts.Length);
                        else
                            Path.Insert(0, Current.ID);
                    }
                    return Path;
                }
                for (int j = 0; j < n.Outgoing.Count; j++)
                {
                    int Target = n.Outgoing[j];


                    int Prev = n.ID;

                    if (!graph.Nodes[Target].Marked)
                    {
                        graph.Nodes[Target].PrevId = Prev;
                        Stack.Push(graph.Nodes[Target]);
                        graph.Nodes[Target].Marked = true;
                    }
                }

            }

            return null;
        }
コード例 #14
0
            public DirectedGraph(Instance inst, int useOnly)
            {
                Nodes = new List<Node>();

                for (int j = 0; j < inst.Posts.Length; j++)
                {
                    Nodes.Add(new Node(1, j));
                }

                for (int i = 0; i < inst.Applicants.Length; i++)
                {
                    Nodes.Add(new Node(0, inst.Posts.Length + i));
                    for (int k = 0; k < inst.Applicants[i].Priorities.Count; k++)
                    {
                        if (useOnly != -1 && inst.Applicants[i].Priorities[k].Rank != useOnly)
                            continue;
                        if (inst.Posts[inst.Applicants[i].Priorities[k].Target].Matchings.Contains(i))
                        {
                            Nodes.ElementAt(inst.Applicants[i].Priorities[k].Target).Outgoing.Add(inst.Posts.Length + i);
                        }
                        else
                        {
                            Nodes.ElementAt(inst.Posts.Length + i).Outgoing.Add(inst.Applicants[i].Priorities[k].Target);
                        }
                    }
                }

            }
コード例 #15
0
        /// <summary>
        /// Completess the applicant-complete matching, by traversing the disjoint cycle and taking every second edge.
        /// </summary>
        /// <param name="instance"></param>
        /// <param name="start"></param>
        /// <returns></returns>
        private Instance GoPath(Instance instance, int start)
        {
            if (instance.Applicants[start].Matched)
                return instance;
            else
            {
                int Target = -1;
                if (!instance.Posts[instance.Applicants[start].Priorities.ElementAt(0).Target].Full)
                {
                    instance.AddMatch(instance.Applicants[start].Priorities.ElementAt(0).Target, start);
                    Target = instance.Applicants[start].Priorities.ElementAt(0).Target;

                }
                else
                {
                    if (!instance.Posts[instance.Applicants[start].Priorities.ElementAt(1).Target].Full)
                    {
                        instance.AddMatch(instance.Applicants[start].Priorities.ElementAt(1).Target, start);
                        Target = instance.Applicants[start].Priorities.ElementAt(1).Target;
                    }
                    else
                        return instance;
                }

                for (int j = 0; j < instance.Applicants.Length; j++)
                {
                    if (instance.Applicants[j].Priorities.ElementAt(0).Target == Target || instance.Applicants[j].Priorities.ElementAt(1).Target == Target)
                    {
                        if (!instance.Applicants[j].Matched)
                            instance = GoPath(instance, j);
                    }
                }
            }
            return instance;
        }
コード例 #16
0
 public LPEdge(Instance.Applicant app, Instance.Post post, int rank)
 {
     Applicant = app;
     Post = post;
     Rank = rank;
 }
コード例 #17
0
        public Instance Match(Instance instance, string path, bool print)
        {
            try
            {
                LP = "";
                if (!System.IO.Directory.Exists(path) && print)
                    System.IO.Directory.CreateDirectory(path);

                GRBEnv env = new GRBEnv("mip1.log");
                GRBModel model = new GRBModel(env);

                List<LPEdge> LPEdges = new List<LPEdge>();


                if (print)
                {
                    instance.Draw().Save(path + "/0Start.bmp");
                }

                int EdgeCounter = 0;
                foreach (Instance.Applicant a in instance.Applicants)
                {
                    EdgeCounter += a.Priorities.Count;
                    foreach (Instance.Priority Prio in a.Priorities)
                    {
                        {
                            LPEdges.Add(new LPEdge(a, instance.Posts[Prio.Target], Prio.Rank));
                            if (Prio.Rank == 0)
                                instance.Posts[Prio.Target].IsF = 1;
                        }
                    }

                }
                // Create variables

                GRBVar[] Edges = new GRBVar[EdgeCounter];

                for (int i = 0; i < Edges.Length; i++)
                {
                    Edges[i] = model.AddVar(0.0, 1.0, 0.0, GRB.BINARY, "ve" + i.ToString());
                }

                // Integrate new variables

                model.Update();

                if (print)
                    LP += "Applicant Matching Conditions:" + Environment.NewLine;

                foreach (Instance.Applicant a in instance.Applicants)
                {
                    GRBLinExpr Temp = new GRBLinExpr();
                    for (int i = 0; i < LPEdges.Count; i++)
                    {
                        if (LPEdges[i].Applicant == a)
                        {
                            Temp += Edges[i];
                            if (print)
                                LP += "(a" + LPEdges[i].Applicant.ID + ", p" + LPEdges[i].Post.ID + ") + ";
                        }
                    }
                    model.AddConstr(Temp == 1.0, "a" + a.ID.ToString());
                    if (print)
                        LP += " = 1;" + Environment.NewLine;
                }

                if (print)
                    LP += Environment.NewLine + "Post Matching Conditions:" + Environment.NewLine;
                
                foreach (Instance.Post p in instance.Posts)
                {
                    GRBLinExpr Temp = new GRBLinExpr();
                    for (int i = 0; i < LPEdges.Count; i++)
                    {
                        if (LPEdges[i].Post == p)
                        {
                            Temp += Edges[i];
                            if (print)
                                LP += "(a" + LPEdges[i].Applicant.ID + ", p" + LPEdges[i].Post.ID + ") + ";
                        }
                    }
                    model.AddConstr(Temp <= 1.0, "p" + p.ID.ToString());
                    if (print)
                        LP += " <= 1;" + Environment.NewLine;
                }

                if (print)
                    LP += Environment.NewLine + "First Choice Conditions:" + Environment.NewLine;

                for (int i = 0; i < LPEdges.Count; i++)
                {
                    LPEdge le1 = LPEdges[i];

                    if (le1.Post.IsF == 1 && le1.Rank != 0)
                    {
                        model.AddConstr(Edges[i] <= 0, "s" + i.ToString());
                        if (print)
                            LP += "(a" + LPEdges[i].Applicant.ID + ", p" + LPEdges[i].Post.ID + ") <= 0;" + Environment.NewLine;

                        for (int j = 0; j < LPEdges[i].Applicant.Priorities.Count; j++)
                        {
                            if (LPEdges[i].Applicant.Priorities[j].Target == LPEdges[i].Post.ID && LPEdges[i].Rank == LPEdges[i].Applicant.Priorities[j].Rank)
                            {
                                LPEdges[i].Applicant.Priorities.RemoveAt(j);
                            }
                        }
                    }
                }

                if (print)
                    LP += Environment.NewLine + "Second Choice Conditions:" + Environment.NewLine;

                for (int i = 0; i < LPEdges.Count; i++)
                {
                    LPEdge le1 = LPEdges[i];

                    foreach (LPEdge le2 in LPEdges)
                    {
                        if (le2 != le1 && le2.Post.IsF == 0 && le1.Applicant == le2.Applicant && le2.Rank != 0 && le2.Rank < le1.Rank)
                        {
                            model.AddConstr(Edges[i] <= 0, "s" + i.ToString());
                            if (print)
                                LP += "(a" + LPEdges[i].Applicant.ID + ", p" + LPEdges[i].Post.ID + ") <= 0;" + Environment.NewLine;
                            for (int j = 0; j < LPEdges[i].Applicant.Priorities.Count; j++)
                            {
                                if (LPEdges[i].Applicant.Priorities[j].Target == LPEdges[i].Post.ID && LPEdges[i].Rank == LPEdges[i].Applicant.Priorities[j].Rank)
                                {
                                    LPEdges[i].Applicant.Priorities.RemoveAt(j);
                                }
                            }
                            break;
                        }
                    }
                }

                if (print)
                    LP += Environment.NewLine + "First Post Conditions:" + Environment.NewLine;

                foreach (Instance.Post p in instance.Posts)
                {
                    if (p.IsF == 1)
                    {
                        GRBLinExpr Temp = new GRBLinExpr();
                        for (int i = 0; i < LPEdges.Count; i++)
                        {
                            if (LPEdges[i].Post == p)
                            {
                                Temp += Edges[i];
                                if (print)
                                    LP += "(a" + LPEdges[i].Applicant.ID + ", p" + LPEdges[i].Post.ID + ") + ";
                            }
                        }
                        model.AddConstr(Temp >= 1.0, "f" + p.ID.ToString());
                        if (print)
                            LP += ">= 1;" + Environment.NewLine;
                    }
                }


                // Optimize model

                model.Optimize();

                if (print)
                {
                    instance.Draw().Save(path + "/1Reduced.bmp");
                }

                for (int i = 0; i < Edges.Length; i++)
                {
                    if (Edges[i].Get(GRB.DoubleAttr.X) == 1)
                    {
                        instance.AddMatch(LPEdges[i].Post.ID, LPEdges[i].Applicant.ID);
                    }
                }

                if (print)
                {
                    instance.Draw().Save(path + "/2Matched.bmp");
                }

                // Dispose of model and env

                model.Dispose();
                env.Dispose();

                return instance;

            }
            catch (GRBException e)
            {
                Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message);
                return null;
            }
        }
コード例 #18
0
        private void GoTypePath(Instance instance, bool Applicant, bool match, bool odd, int id)
        {
            if (Applicant)
            {
                if (odd)
                {
                    instance.Applicants[id].Type = 0;
                }
                else
                {
                    instance.Applicants[id].Type = 1;
                }
                if (!match)
                {
                    for (int j = 0; j < instance.Applicants[id].Priorities.Count; j++)
                    {
                        if (instance.Posts[instance.Applicants[id].Priorities[j].Target].Type == -1 && instance.Applicants[id].Priorities[j].Rank == 0)
                            GoTypePath(instance, false, true, !odd, instance.Applicants[id].Priorities[j].Target);
                    }
                }
                if (match)
                {
                    for (int j = 0; j < instance.Applicants[id].Priorities.Count; j++)
                    {
                        if (instance.Posts[instance.Applicants[id].Priorities[j].Target].Matchings.Contains(id))
                        {
                            if (instance.Posts[instance.Applicants[id].Priorities[j].Target].Type == -1 && instance.Applicants[id].Priorities[j].Rank == 0)
                                GoTypePath(instance, false, false, !odd, instance.Applicants[id].Priorities[j].Target);

                        }
                    }
                }

            }
            else
            {
                if (odd)
                {
                    instance.Posts[id].Type = 0;
                }
                else
                {
                    instance.Posts[id].Type = 1;
                }
                if (match)
                {
                    for (int i = 0; i < instance.Posts[id].Matchings.Count; i++)
                    {
                        if (instance.Applicants[instance.Posts[id].Matchings[i]].Type == -1)
                            GoTypePath(instance, true, false, !odd, instance.Posts[id].Matchings[i]);
                    }
                }
                if (!match)
                {
                    for (int i = 0; i < instance.Applicants.Length; i++)
                    {
                        for (int j = 0; j < instance.Applicants[i].Priorities.Count; j++)
                        {
                            if (instance.Applicants[i].Priorities[j].Target == id && instance.Applicants[i].Priorities[j].Rank == 0)
                            {
                                if (instance.Applicants[i].Type == -1)
                                    GoTypePath(instance, true, true, !odd, i);

                            }
                        }
                    }
                }
            }
        }
コード例 #19
0
        /// <summary>
        /// Determine the types of the nodes.
        /// 0 = Odd
        /// 1 = Even
        /// 2 = Unreachable
        /// </summary>
        /// <param name="instance"></param>
        /// <returns></returns>
        private Instance DetermineTypes(Instance instance)
        {
            // Unmatched nodes are directly even, go possible paths to determine the other paths.
            for (int i = 0; i < instance.Applicants.Length; i++)
            {
                if (!instance.Applicants[i].Matched)
                {
                    instance.Applicants[i].Type = 1;
                    for (int j = 0; j < instance.Applicants[i].Priorities.Count; j++)
                    {
                        if (instance.Posts[instance.Applicants[i].Priorities[j].Target].Type == -1 && instance.Applicants[i].Priorities[j].Rank == 0)
                            GoTypePath(instance, false, true, true, instance.Applicants[i].Priorities[j].Target);
                    }
                }
            }
            for (int i = 0; i < instance.Posts.Length; i++)
            {
                if (!instance.Posts[i].Full)
                {
                    instance.Posts[i].Type = 1;

                    for (int j = 0; j < instance.Applicants.Length; j++)
                    {
                        for (int k = 0; k < instance.Applicants[j].Priorities.Count; k++)
                        {
                            if (instance.Applicants[j].Priorities[k].Target == i && instance.Applicants[j].Type == -1 && instance.Applicants[j].Priorities[k].Rank == 0)
                                GoTypePath(instance, true, true, true, j);
                        }
                    }
                }
            }


            // unreachable nodes
            for (int i = 0; i < instance.Applicants.Length; i++)
            {
                if (instance.Applicants[i].Type == -1)
                    instance.Applicants[i].Type = 2;
            }

            for (int i = 0; i < instance.Posts.Length; i++)
            {
                if (instance.Posts[i].Type == -1)
                    instance.Posts[i].Type = 2;
            }

            return instance;
        }
コード例 #20
0
        /// <summary>
        /// Uses a basic augmenting path algorithm to find a maximum matching.
        /// </summary>
        /// <param name="instance"></param>
        /// <param name="useOnly"></param>
        /// <returns></returns>
        private Instance MaxMatching(Instance instance, int useOnly)
        {
            FinalPath = new List<int>();
            while (FinalPath != null)
            {
                FinalPath = DFS(new DirectedGraph(instance, useOnly), instance);
                if (FinalPath != null)
                    instance.MatchPath(FinalPath, true);

            }
            return instance;
        }
コード例 #21
0
 public Instance CopyWithMatching()
 {
     Instance result = new Instance(n, m);
     for (int i = 0; i < Applicants.Length; i++)
     {
         result.Applicants[i] = new Applicant(i);
         for (int j = 0; j < Applicants[i].Priorities.Count; j++)
         {
             result.Applicants[i].Priorities.Add(new Priority(Applicants[i].Priorities[j].Target, Applicants[i].Priorities[j].Rank));
         }
         result.Applicants[i].Matched = Applicants[i].Matched;
     }
     for (int i = 0; i < Posts.Length; i++)
     {
         result.Posts[i] = new Post(i, Posts[i].Capacity);
         result.Posts[i].Matched = Posts[i].Matched;
         result.Posts[i].Full = Posts[i].Full;
         result.Posts[i].NrMatchings = Posts[i].NrMatchings;
         result.Posts[i].Matchings = Copy(Posts[i].Matchings);
     }
     return result;
 }
コード例 #22
0
        /// <summary>
        /// Replace posts with capacity c by c posts.
        /// </summary>
        /// <param name="instance"></param>
        /// <returns></returns>
        private Instance Inflate(Instance instance)
        {
            int Capacity = 0;

            for (int i = 0; i < instance.m; i++)
            {
                Capacity += instance.Posts[i].Capacity;
            }

            Instance NewInstance = new Instance(instance.n, Capacity);

            for (int i = 0; i < instance.n; i++)
            {
                NewInstance.Applicants[i] = new Instance.Applicant(i);
            }

            int Counter = 0;
            for (int i = 0; i < instance.m + instance.n; i++)
            {
                for (int k = 0; k < instance.Posts[i].Capacity; k++)
                {
                    NewInstance.Posts[Counter] = new Instance.Post(Counter, 1);

                    for (int j = 0; j < instance.n; j++)
                    {
                        for (int z = 0; z < instance.Applicants[j].Priorities.Count; z++)
                        {
                            if (instance.Applicants[j].Priorities[z].Target == i)
                            {

                                NewInstance.Applicants[j].Priorities.Add(new Instance.Priority(Counter, instance.Applicants[j].Priorities[z].Rank));
                            }
                        }
                    }

                    Counter++;
                }
            }
            return NewInstance;
        }
コード例 #23
0
        /// <summary>
        /// Returns a random instance.
        /// </summary>
        /// <param name="n">Number of Applicants</param>
        /// <param name="m">Number of Posts</param>
        /// <param name="k">Length of the priority list</param>
        /// <param name="c">capacity of the Posts</param>
        /// <param name="seed">starting seed for random</param>
        /// <returns></returns>
        /// 
        public static Instance GetRandom(int n, int m, int k, int c, int seed)
        {
            Instance Result = new Instance(n, m);

            for (int i = 0; i < n; i++)
            {
                Result.Applicants[i] = new Applicant(i);
                Result.Applicants[i].Priorities = new List<Instance.Priority>();
                for (int j = 0; j < k; j++)
                {
                    int NextPrio = Rnd.Next(m);
                    bool Existing = true;
                    while (Existing)
                    {
                        Existing = false;
                        for (int z = 0; z < Result.Applicants[i].Priorities.Count; z++)
                        {
                            if (NextPrio == Result.Applicants[i].Priorities[z].Target)
                            {
                                Existing = true;
                                break;
                            }
                        }
                        if (Existing)
                            NextPrio = Rnd.Next(m);
                    }
                    Result.Applicants[i].Priorities.Add(new Instance.Priority(NextPrio, j));
                }
                Result.Applicants[i].Priorities.Add(new Instance.Priority(m + i, k));
            }

            for (int i = 0; i < m; i++)
            {
                Result.Posts[i] = new Post(i, c);
            }
            for (int i = m; i < m + n; i++)
            {
                Result.Posts[i] = new Post(i, 1);
            }

            return Result;
        }
コード例 #24
0
 public Node(Instance.Post p)
 {
     Post = p;
     Outgoing = new List<Edge>();
     Component = -1;
     Prev = null;
     IsS = true;
     Found = false;
 }
コード例 #25
0
        /// <summary>
        /// Creates the reduced subgraph.
        /// </summary>
        /// <param name="instance"></param>
        /// <returns></returns>
        private Instance GetReduced(Instance instance)
        {
            // Determine the f-posts
            List<int> FirstPosts = new List<int>();
            for (int i = 0; i < instance.n; i++)
            {
                if (!FirstPosts.Contains(instance.Applicants[i].Priorities.ElementAt(0).Target))
                    FirstPosts.Add(instance.Applicants[i].Priorities.ElementAt(0).Target);
            }

            for (int i = 0; i < instance.n; i++)
            {
                bool SecondFound = false;
                int j;

                for (j = 1; j < instance.Applicants[i].Priorities.Count - 1; j++)
                {

                    if (FirstPosts.Contains(instance.Applicants[i].Priorities.ElementAt(j).Target))
                    {
                        // delete all f-posts except the first one from priority list
                        instance.Applicants[i].Priorities.Remove(instance.Applicants[i].Priorities.ElementAt(j));
                        j--;
                    }
                    else
                    {
                        // look if there is some not f-post before l on the list
                        SecondFound = true;
                        break;
                    }
                }
                if (SecondFound)
                {
                    // if some second priority has been found before l, delete all posts behind it
                    for (j = j + 1; j < instance.Applicants[i].Priorities.Count; j++)
                    {
                        instance.Applicants[i].Priorities.Remove(instance.Applicants[i].Priorities.ElementAt(j));
                        j--;
                    }
                }


                if (instance.Applicants[i].Priorities.Count == 1)
                    return null;
            }

            // now only applicant has 2 edges, to f- and s-post
            return instance;
        }
コード例 #26
0
        /// <summary>
        /// Replace posts with capacity c by c posts
        /// </summary>
        /// <param name="instance"></param>
        /// <returns></returns>
        private Instance Inflate(Instance instance)
        {
            int Capacity = 0;

            // determine total complexity of the posts
            for (int i = 0; i < instance.m; i++)
            {
                Capacity += instance.Posts[i].Capacity;
            }

            Instance NewInstance = new Instance(instance.n, Capacity);

            for (int i = 0; i < instance.n; i++)
            {
                NewInstance.Applicants[i] = new Instance.Applicant(i);
            }

            int Counter = 0;
            for (int i = 0; i < instance.m; i++)
            {
                // traverse all old posts
                List<Tuple<int, int>> Suitors = new List<Tuple<int, int>>();
                for (int j = 0; j < instance.n; j++)
                {
                    // add all applicants connected to post j to the list of interested people
                    for (int z = 0; z < instance.Applicants[j].Priorities.Count; z++)
                    {
                        if (instance.Applicants[j].Priorities.ElementAt(z).Target == i)
                        {
                            Suitors.Add(new Tuple<int, int>(j, z));
                        }
                        // in the last iteration of the loop maybe add an edge to the l post of the applicant and mind the changed ID
                        if (i == instance.m - 1 && instance.Applicants[j].Priorities.ElementAt(z).Target >= instance.m)
                            NewInstance.Applicants[j].Priorities.Add(new Instance.Priority(instance.Applicants[j].Priorities.ElementAt(z).Target + (Capacity - instance.m), 0));

                    }
                }

                // more applicants are interested in the post than there is capacity
                if (Suitors.Count >= instance.Posts[i].Capacity)
                {
                    // fill every new posts with about equally many interested people
                    // calculate current interested people per space
                    int Factor = (int)((Suitors.Count) / (decimal)instance.Posts[i].Capacity);
                    int SCounter = 0;
                    for (int j = 0; j < instance.Posts[i].Capacity; j++)
                    {
                        // traverse all posts
                        NewInstance.Posts[Counter] = new Instance.Post(Counter, 1);

                        // adapt factor depending on still existing interested people and remaining new posts
                        Factor = (int)Math.Ceiling((Suitors.Count - SCounter) / ((decimal)instance.Posts[i].Capacity - j));

                        // add according to the factor calculated above many people to the new post
                        for (int z = 0; z < Factor; z++)
                        {
                            // mind the priority list
                            if (Suitors.ElementAt(SCounter).Item2 == 0 || NewInstance.Applicants[Suitors.ElementAt(SCounter).Item1].Priorities.Count == 0)
                                NewInstance.Applicants[Suitors.ElementAt(SCounter++).Item1].Priorities.Insert(0, new Instance.Priority(Counter, 0));
                            else
                            {
                                NewInstance.Applicants[Suitors.ElementAt(SCounter++).Item1].Priorities.Insert(1, new Instance.Priority(Counter, 1));
                            }
                        }

                        Counter++;
                    }
                }
                else
                {
                    // other more available places than interested people exist, just fill the places
                    int Next = Counter + instance.Posts[i].Capacity;
                    for (int j = 0; j < Suitors.Count; j++)
                    {
                        NewInstance.Posts[Counter] = new Instance.Post(Counter, 1);

                        if (Suitors.ElementAt(j).Item2 == 0)
                            NewInstance.Applicants[Suitors.ElementAt(j).Item1].Priorities.Insert(0, new Instance.Priority(Counter, 0));
                        else
                            NewInstance.Applicants[Suitors.ElementAt(j).Item1].Priorities.Insert(1, new Instance.Priority(Counter, 1));

                        Counter++;
                    }
                    for (; Counter < Next; Counter++)
                    {
                        NewInstance.Posts[Counter] = new Instance.Post(Counter, 1);
                    }
                }

            }
            for (int j = Counter; j < NewInstance.Posts.Length; j++)
            {
                NewInstance.Posts[j] = new Instance.Post(j, 1);
            }
            return NewInstance;
        }