c# 盖尔-沙普利算法的改进
盖尔-沙普利算法
“盖尔-沙普利算法”(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(, );
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<Male> maleList = (marry.MaleDic.Values.Where(p => !p.Marryed)).ToList<Male>();
//List<Female> femaleList = (marry.FemaleDic.Values.Where(p => !p.Marryed)).ToList<Female>();
//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.##");
}
}
/// <summary>
/// 请求对象
/// </summary>
public class RequestObj
{
/// <summary>
/// 对象编号
/// </summary>
public int ID { get; private set; }
/// <summary>
/// 对象在自己心目中的估分
/// </summary>
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 = ;
private static double MinPoint = ;
/// <summary>
/// 个人编号
/// </summary>
public int ID { get; set; }
/// <summary>
/// 配偶编号
/// </summary>
public int PartnerID { get; set; }
public bool Marryed
{
get
{
return this.PartnerID < ? false : true;
}
}
/// <summary>
/// 实际得分
/// </summary>
public double Point { get; set; }
/// <summary>
/// 个人估分
/// </summary>
public double MyEstimatePoint { get; set; }
/// <summary>
/// 配偶得分
/// </summary>
public double PartnerEstimatePoint { get; set; }
/// <summary>
/// 满意度
/// </summary>
public double Satisfaction
{
get
{
if (!this.Marryed)
{
return ;
}
//很难找到合适的计算满意度的方法
double mul = Math.Abs(this.MyEstimatePoint - this.PartnerEstimatePoint) / People.MaxPoint;
if (this.MyEstimatePoint > this.PartnerEstimatePoint)
{
return 50.0 * ( - mul);
}
else
{
return 50.0 * ( + mul);
}
}
}
public People(int id)
{
this.PartnerID = -;
this.ID = id;
this.Point = Marry.Rnd.NextDouble() * (People.MaxPoint - People.MinPoint) + People.MinPoint; //个人得分在0-1000之间,平均分布
this.MyEstimatePoint = People.GetEstimatePoint(this.Point);
} /// <summary>
/// 估分系统
/// </summary>
/// <param name="point">实际得分</param>
/// <returns>估分</returns>
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<RequestObj> RequestList { get; set; }
public Male(int id)
: base(id)
{ }
public void InitRequestList(Dictionary<int, Female> femaleDic)
{
this.RequestList = new List<RequestObj>();
foreach (Female female in femaleDic.Values)
{
if (Marry.Rnd.Next() != )//控制此人可以接触到的女性人数,目前所有男性的范围相同,可以由个人的交际能力代替
{
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<RequestObj>();//降序
} /// <summary>
/// 求婚
/// </summary>
/// <param name="maleDic"></param>
/// <param name="femaleDic"></param>
public void Request(Dictionary<int, Male> maleDic, Dictionary<int, Female> femaleDic)
{
if (this.Marryed)
{
return;
}
if (this.RequestList.Count == )
{
return;
}
Female female = femaleDic[this.RequestList[].ID];
if (female.BeRequest(this, maleDic))
{
this.PartnerID = female.ID;
this.PartnerEstimatePoint = this.RequestList[].EstimatePoint;
}
this.RequestList.RemoveAt();
} /// <summary>
/// 离婚
/// </summary>
public void Divorce()
{
this.PartnerID = -;
this.PartnerEstimatePoint = ;
}
}
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
{
/// <summary>
/// 全局使用的随机数
/// </summary>
public static Random Rnd = new Random();
public Dictionary<int, Male> MaleDic { get; set; }
public Dictionary<int, Female> FemaleDic { get; set; }
/// <summary>
/// 结婚数
/// </summary>
public int MarriageCount
{
get
{
int count = ;
foreach (Male male in this.MaleDic.Values)
{
if (male.Marryed)
{
count++;
}
}
return count;
}
}
/// <summary>
/// 单身人数
/// </summary>
public int SingleCount
{
get
{
return this.MaleDic.Count + this.FemaleDic.Count - this.MarriageCount * ;
}
}
public double MaleSatisfaction
{
get
{
double satisfaction = ;
foreach (Male male in this.MaleDic.Values)
{
satisfaction += male.Satisfaction;
}
return satisfaction / this.MaleDic.Count;
}
}
public double FemaleSatisfaction
{
get
{
double satisfaction = ;
foreach (Female female in this.FemaleDic.Values)
{
satisfaction += female.Satisfaction;
}
return satisfaction / this.FemaleDic.Count;
}
}
/// <summary>
/// 需要继续匹配
/// </summary>
public bool NeedMatch
{
get
{
foreach (Male male in this.MaleDic.Values)
{
if (male.RequestList.Count > && !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 = ; i < maleNum; i++)
{
MaleDic.Add(i, new Male(i));
}
for (int i = ; 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);
}
}
}
}
}
c# 盖尔-沙普利算法的改进的更多相关文章
- JavaScript 盖尔-沙普利算法
最近在学 JavaScript , 为了尽快熟悉语法,决定移植以前写的盖尔-沙普利算法. c# 下的代码:https://www.cnblogs.com/aitong/p/10973774.html ...
- ISAP算法对 Dinic算法的改进
ISAP算法对 Dinic算法的改进: 在刘汝佳图论的开头引言里面,就指出了,算法的本身细节优化,是比较复杂的,这些高质量的图论算法是无数优秀算法设计师的智慧结晶. 如果一时半会理解不清楚,也是正常的 ...
- 海量数据挖掘MMDS week2: 频繁项集挖掘 Apriori算法的改进:非hash方法
http://blog.csdn.net/pipisorry/article/details/48914067 海量数据挖掘Mining Massive Datasets(MMDs) -Jure Le ...
- 海量数据挖掘MMDS week2: 频繁项集挖掘 Apriori算法的改进:基于hash的方法
http://blog.csdn.net/pipisorry/article/details/48901217 海量数据挖掘Mining Massive Datasets(MMDs) -Jure Le ...
- md5是哈希算法的改进加强,因为不同原始值可能hash结果一样,但md5则改善了用于验证消息完整性,不同md5值原始值也必将不一样
md5是哈希算法的改进加强,因为不同原始值可能hash结果一样,但md5则改善了用于验证消息完整性,不同md5值原始值也必将不一样
- KMP算法的改进
KMP算法的改进 KMP算法已经在极大程度上提高了子符串的匹配效率,但是仍然有改进的余地. 1. 引入的情景 下面我们就其中的一种情况进行分析: 主串T为"aaaabcde-" 子 ...
- KMP算法(改进的模式匹配算法)——next函数
KMP算法简介 KMP算法是在基础的模式匹配算法的基础上进行改进得到的算法,改进之处在于:每当匹配过程中出现相比较的字符不相等时,不需要回退主串的字符位置指针,而是利用已经得到的部分匹配结果将模式串向 ...
- soundtouch变速wsola算法之改进
soundtouch变速算法很类似sola算法,细看才知道是wsola算法. 上个星期有个需求,将该变速应用到直播的包处理,有点类似于webrtc的netEQ处理机制. 直接使用soundtouch, ...
- 大话数据结构(十二)java程序——KMP算法及改进的KMP算法实现
1.朴素的模式匹配算法 朴素的模式匹配算法:就是对主串的每个字符作为子串开头,与要连接的字符串进行匹配.对主串做大循环,每个字符开头做T的长度的小循环,直到成功匹配或全部遍历完成为止. 又称BF算法 ...
随机推荐
- Python面试题之如何用Python来发送邮件?
python实现发送和接收邮件功能主要用到poplib和smtplib模块. poplib用于接收邮件,而smtplib负责发送邮件. 代码如下: 1 #! /usr/bin/env python 2 ...
- “CreateRiaClientFilesTask”任务意外失败。 未能加载文件程序集“System.ComponentModel.DataAnnot...
错误 77 “CreateRiaClientFilesTask”任务意外失败. System.Web.HttpException (0x80004005): 未能加载文件或程序集“System. ...
- vue项目的脚手架
> cnpm i @vue/cli@3 -g > vue create myapp * 选择 Manually select features ----- 自选预设文件 * 选择 vue ...
- Linux学习笔记0-CentOS7关闭防火墙
关闭防火墙 systemctl stop firewalld.service //停止firewall systemctl disable firewalld.service //禁止firewall ...
- flask开发问题小记
前因 最近在使用flask开发一个APP的后端时出现了一些小问题.我使用sqlalchemy建立了如下多对多关系: 中间表 user_manager_group = db.Table('manage_ ...
- 关于python全局变量
今天踩了一个坑,记录一下,避免后犯 在constant.py 中定义了一个全局变量 ZH_LIST= [],以个用于存储配置一些信息: 在views.py 中引用了这个ZH_LIST : 然后在app ...
- oracle时间问题 与case then
思路一 --select * from nls_session_parameters where parameter='NLS_DATE_LANGUAGE'; -- 修改会话的默认日期格式 ALTER ...
- ThreadLocal内存泄漏
原创转载请注明出处:https://www.cnblogs.com/agilestyle/p/11421437.html 内存泄漏 内存泄漏是指不再使⽤的对象⽆法得到及时的回收,持续占⽤内存空间,从⽽ ...
- SpringDataJpa全部依赖
<properties> <spring.version>4.2.4.RELEASE</spring.version> <hibernate.version& ...
- 记一次pycharm和vscode因网络问题插件下载失败的问题
WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connec ...