盖尔-沙普利算法

“盖尔-沙普利算法”(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# 盖尔-沙普利算法的改进的更多相关文章

  1. JavaScript 盖尔-沙普利算法

    最近在学 JavaScript , 为了尽快熟悉语法,决定移植以前写的盖尔-沙普利算法. c# 下的代码:https://www.cnblogs.com/aitong/p/10973774.html ...

  2. ISAP算法对 Dinic算法的改进

    ISAP算法对 Dinic算法的改进: 在刘汝佳图论的开头引言里面,就指出了,算法的本身细节优化,是比较复杂的,这些高质量的图论算法是无数优秀算法设计师的智慧结晶. 如果一时半会理解不清楚,也是正常的 ...

  3. 海量数据挖掘MMDS week2: 频繁项集挖掘 Apriori算法的改进:非hash方法

    http://blog.csdn.net/pipisorry/article/details/48914067 海量数据挖掘Mining Massive Datasets(MMDs) -Jure Le ...

  4. 海量数据挖掘MMDS week2: 频繁项集挖掘 Apriori算法的改进:基于hash的方法

    http://blog.csdn.net/pipisorry/article/details/48901217 海量数据挖掘Mining Massive Datasets(MMDs) -Jure Le ...

  5. md5是哈希算法的改进加强,因为不同原始值可能hash结果一样,但md5则改善了用于验证消息完整性,不同md5值原始值也必将不一样

    md5是哈希算法的改进加强,因为不同原始值可能hash结果一样,但md5则改善了用于验证消息完整性,不同md5值原始值也必将不一样

  6. KMP算法的改进

    KMP算法的改进 KMP算法已经在极大程度上提高了子符串的匹配效率,但是仍然有改进的余地. 1. 引入的情景 下面我们就其中的一种情况进行分析: 主串T为"aaaabcde-" 子 ...

  7. KMP算法(改进的模式匹配算法)——next函数

    KMP算法简介 KMP算法是在基础的模式匹配算法的基础上进行改进得到的算法,改进之处在于:每当匹配过程中出现相比较的字符不相等时,不需要回退主串的字符位置指针,而是利用已经得到的部分匹配结果将模式串向 ...

  8. soundtouch变速wsola算法之改进

    soundtouch变速算法很类似sola算法,细看才知道是wsola算法. 上个星期有个需求,将该变速应用到直播的包处理,有点类似于webrtc的netEQ处理机制. 直接使用soundtouch, ...

  9. 大话数据结构(十二)java程序——KMP算法及改进的KMP算法实现

    1.朴素的模式匹配算法 朴素的模式匹配算法:就是对主串的每个字符作为子串开头,与要连接的字符串进行匹配.对主串做大循环,每个字符开头做T的长度的小循环,直到成功匹配或全部遍历完成为止. 又称BF算法 ...

随机推荐

  1. Linux下MySQL Error 1130 不能远程访问(转)

    Linux下MySQL Error 1130 不能远程访问 内容简介:远程连接MySQL时总是报出erro 2003: Can't connect to MySQL server on '211.87 ...

  2. 【数据驱动】python之mysql的操作

    1.准备工作 在本篇中,我们使用python版本为python3.7.在python3中,连接mysql数据库我们需要使用pymysql这个第三方库.我们可以直接使用pip命令来安装,安装的命令为: ...

  3. Codeforces 497B Tennis Game( 枚举+ 二分)

    B. Tennis Game time limit per test 2 seconds memory limit per test 256 megabytes input standard inpu ...

  4. springboot 项目启动脚本

    springboot项目启动可通过下面的shell脚本启动. startup.sh app=order-service-rest.jar appout=logs/${app/.jar/.out} ap ...

  5. 三、spring的AOP

    AOP的基本认识 Aspect Oriented Programming,面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术 利用AOP可以对业务逻辑的各个部分进行隔离,从而 ...

  6. Vue内敛模板

    在学习<Vue实战>一书时,学习到组件高级应用-内联模板这一小节时,照着书上的例子敲了一遍,发现未达到预期,切报错. 书上源代码如下: <!DOCTYPE html> < ...

  7. shell位置参数处理举例

  8. C++判断字符是否是元音字母

    写这个随笔的起因很奇怪. 我本来想找找C++有没有内置的函数(类似isalpha(), isdigit(), isalnum()之流)能直接完成这个功能,但是函数没发现,却发现很多博客都是逐个字符判断 ...

  9. 第5篇K8S创建资源的两种方式

      一.创建方式分类: 命令 vs 配置文件 Kubernetes 支持两种方式创建资源: 1.用 kubectl 命令直接创建,比如: kubectl run httpd-app --image=r ...

  10. 转 top、postop、scrolltop、offsetTop、scrollHeight、offsetHeight、clientHeight

    1.top 此属性仅仅在对象的定位(position)属性被设置时可用.否则,此属性设置会被忽略. 复制代码 代码如下: <div style=" position:absolute; ...