c \ # 게 일 - 사 프 리 알고리즘 개선

37829 단어
게 일 - 사 프 리 알고리즘
'게 일 - 샤프 리 알고리즘' (the Gale - Shapley algorithm) 은 '지연 수용 알고리즘' (deferred - acceptance algorithm) 이 라 고도 불 리 며 'GS 알고리즘' 이 라 고도 부른다.게 일과 사 프 리 가 안정 적 인 매 칭 을 찾기 위해 설계 한 시장 메커니즘 이다.시장 한쪽 의 대상 (의료 기구) 은 다른 쪽 의 대상 (의과대학 학생) 에 게 요 구 를 하고 모든 학생 회 는 자신 이 받 은 요 구 를 고려 한 다음 에 자신 이 선 호 하 는 것 (받 아들 일 수 있다 고 생각 하 는 것) 을 잡 아 다른 것 을 거절 했다.이 알고리즘 의 관건 은 합의 한 요약 이 바로 받 아들 여지 지 않 고 '잡 히 기' (hold on to), 즉 '지연 수용' 이라는 점 이다.청 약이 거절당 한 후에 야 의료 기관 은 다른 의 대 학생 에 게 새로운 청 약 을 할 수 있다.전체 절 차 는 새로운 청 약 을 원 하 는 기관 이 없 을 때 까지 계속 되 었 고, 그때 가 되 어서 야 학생 들 은 결국 각자 의 '잡 아 라' 는 청 약 을 받 아 들 였 다.
본 고 는 이 알고리즘 을 바탕 으로 실제 상황 에 적응 하기 위해 다른 요 소 를 추가 했다.
1. 개인 득점 시스템, 평가 시스템 을 추가 합 니 다.결혼 할 때 쌍방의 점수 차 이 는 너무 크 면 안 된다.
2. 이혼 난이도 증가
3. 단체의 접촉 범 위 를 통제한다.한 남성 이 일부 여성 만 접촉 할 수 있다 는 것 이다.
원시 적 인 게 일 사 프 리 알고리즘 에 서 는 남성의 만족 도 는 100 에 가 깝 고 여성의 만족 도 는 50 에 가깝다.알고리즘 조정 후 쌍방의 만족 도 는 비교적 비슷 하 다.using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; // - [Gale-Shapley] // N ,M , ( ), , // , ( )。 // , 。 // namespace GaleShapley { class Program { static void Main(string[] args) { Marry marry = new Marry(200, 200); int number = marry.MaleDic.Count; marry.Start(); Console.WriteLine("MaleSatisfaction : " + marry.MaleSatisfaction); Console.WriteLine("FeMaleSatisfaction : " + marry.FemaleSatisfaction); //Console.WriteLine(" ID\t \t \t ID\t \t "); //foreach (Male male in marry.MaleDic.Values) //{ // if (!male.Marryed) // { // continue; // } // Female female = marry.FemaleDic[male.PartnerID]; // Console.WriteLine(male.ID + "\t" + male.Point.ToMyString() + "\t" + male.Satisfaction.ToMyString() + "\t" + // female.ID + "\t" + female.Point.ToMyString() + "\t" + female.Satisfaction.ToMyString()); //} //List maleList = (marry.MaleDic.Values.Where(p => !p.Marryed)).ToList(); //List femaleList = (marry.FemaleDic.Values.Where(p => !p.Marryed)).ToList(); //for (int i = 0; i < maleList.Count; i++) //{ // Male male = maleList[i]; // Female female = femaleList[i]; // Console.WriteLine(male.ID + "\t" + male.Point.ToMyString() + "\t" + male.Satisfaction.ToMyString() + "\t" + // female.ID + "\t" + female.Point.ToMyString() + "\t" + female.Satisfaction.ToMyString()); //} Console.ReadLine(); } } public static class DoubleExtendMethod { public static string ToMyString(this double num) { return num.ToString("0.##"); } } /// /// /// public class RequestObj { /// /// /// public int ID { get; private set; } /// /// /// public double EstimatePoint { get; private set; } public RequestObj(int id, double estimatePoint) { this.ID = id; this.EstimatePoint = estimatePoint; } } public class People { private static double MaxPoint = 1000; private static double MinPoint = 200; /// /// /// public int ID { get; set; } /// /// /// public int PartnerID { get; set; } public bool Marryed { get { return this.PartnerID < 0 ? false : true; } } /// /// /// public double Point { get; set; } /// /// /// public double MyEstimatePoint { get; set; } /// /// /// public double PartnerEstimatePoint { get; set; } /// /// /// public double Satisfaction { get { if (!this.Marryed) { return 0; } // double mul = Math.Abs(this.MyEstimatePoint - this.PartnerEstimatePoint) / People.MaxPoint; if (this.MyEstimatePoint > this.PartnerEstimatePoint) { return 50.0 * (1 - mul); } else { return 50.0 * (1 + mul); } } } public People(int id) { this.PartnerID = -1; this.ID = id; this.Point = Marry.Rnd.NextDouble() * (People.MaxPoint - People.MinPoint) + People.MinPoint; // 0-1000 , this.MyEstimatePoint = People.GetEstimatePoint(this.Point); } /// /// /// /// /// public static double GetEstimatePoint(double point) { //return point; double mul = 0.8 + Marry.Rnd.NextDouble() * 0.4; // 80% - 120% return point * mul; } } public class Male : People { public List RequestList { get; set; } public Male(int id) : base(id) { } public void InitRequestList(Dictionary<int, Female> femaleDic) { this.RequestList = new List(); foreach (Female female in femaleDic.Values) { if (Marry.Rnd.Next(10) != 1)// , , { continue; } double point = People.GetEstimatePoint(female.Point);// if (point > this.MyEstimatePoint) { double mul = (point - this.MyEstimatePoint) / this.MyEstimatePoint; if (mul < 0.2) { this.RequestList.Add(new RequestObj(female.ID, point)); } } else { double mul = (this.MyEstimatePoint - point) / this.MyEstimatePoint; if (mul < 0.2) { this.RequestList.Add(new RequestObj(female.ID, point)); } } } this.RequestList = this.RequestList.OrderByDescending(a => a.EstimatePoint).ToList();// } /// /// /// /// /// public void Request(Dictionary<int, Male> maleDic, Dictionary<int, Female> femaleDic) { if (this.Marryed) { return; } if (this.RequestList.Count == 0) { return; } Female female = femaleDic[this.RequestList[0].ID]; if (female.BeRequest(this, maleDic)) { this.PartnerID = female.ID; this.PartnerEstimatePoint = this.RequestList[0].EstimatePoint; } this.RequestList.RemoveAt(0); } /// /// /// public void Divorce() { this.PartnerID = -1; this.PartnerEstimatePoint = 0; } } public class Female : People { public Female(int id) : base(id) { } public bool BeRequest(Male male, Dictionary<int, Male> maleDic) { double estimatePoint = People.GetEstimatePoint(male.Point);// if (this.Marryed)// { if (this.PartnerEstimatePoint < estimatePoint) { double difference = estimatePoint / this.PartnerEstimatePoint; if (difference > 1.5) { maleDic[this.PartnerID].Divorce(); this.PartnerID = male.ID; this.PartnerEstimatePoint = estimatePoint; return true; } } return false; } else// { if (estimatePoint > (this.MyEstimatePoint * 0.8)) { this.PartnerID = male.ID; this.PartnerEstimatePoint = estimatePoint; return true; } return false; } } } public class Marry { /// /// /// public static Random Rnd = new Random(); public Dictionary<int, Male> MaleDic { get; set; } public Dictionary<int, Female> FemaleDic { get; set; } /// /// /// public int MarriageCount { get { int count = 0; foreach (Male male in this.MaleDic.Values) { if (male.Marryed) { count++; } } return count; } } /// /// /// public int SingleCount { get { return this.MaleDic.Count + this.FemaleDic.Count - this.MarriageCount * 2; } } public double MaleSatisfaction { get { double satisfaction = 0; foreach (Male male in this.MaleDic.Values) { satisfaction += male.Satisfaction; } return satisfaction / this.MaleDic.Count; } } public double FemaleSatisfaction { get { double satisfaction = 0; foreach (Female female in this.FemaleDic.Values) { satisfaction += female.Satisfaction; } return satisfaction / this.FemaleDic.Count; } } /// /// /// public bool NeedMatch { get { foreach (Male male in this.MaleDic.Values) { if (male.RequestList.Count > 0 && !male.Marryed) { return true; } } return false; } } public Marry(int maleNum, int femaleNum) { this.MaleDic = new Dictionary<int, Male>(); this.FemaleDic = new Dictionary<int, Female>(); for (int i = 0; i < maleNum; i++) { MaleDic.Add(i, new Male(i)); } for (int i = 0; i < femaleNum; i++) { FemaleDic.Add(i, new Female(i)); } foreach (Male male in this.MaleDic.Values) { male.InitRequestList(this.FemaleDic); } } public void Start() { while (this.NeedMatch) { foreach (Male male in this.MaleDic.Values) { male.Request(this.MaleDic, this.FemaleDic); } } } } }

 

좋은 웹페이지 즐겨찾기