盖尔-沙普利算法

“盖尔-沙普利算法”(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. 初识Flink广播变量broadcast

    Broadcast 广播变量:可以理解为是一个公共的共享变量,我们可以把一个dataset 或者不变的缓存对象(例如map list集合对象等)数据集广播出去,然后不同的任务在节点上都能够获取到,并在 ...

  2. MYSQL中常用的工具

    1.mysql(客户端链接工具):   -u :指定用户名   -p:指定密码   -h:指定服务器ip或者域名   -P(大写):指定端口  例子:mysql -u root -h 202.194. ...

  3. Java面试之String、StringBuffer和StringBuilder的区别和原理

    首先我们先来谈谈String: String 对象一旦创建,其值是不能修改的,如果要修改,会重新开辟内存空间来存储修改之后的对象,即修改了 String 的引用. 因为 String 的底层是用数组来 ...

  4. Vue-Cli3环境安装

    一,安装node环境 尽量使用高版本的node环境,低版本的node环境会出现各种安装问题 下载地址: http://nodejs.cn/download/ 打开cmd node -v :查看node ...

  5. Java 枚举和类的区别

    枚举 包含一组常量合法的数据,不能创建枚举实例,也不能进行扩展. package com.jtfr.demo; public enum Week { MONDAY, TUESDAY, WEDNESDA ...

  6. 函数传递是如何让HTTP服务器工作的

    var http = require("http"); http.createServer(function(request, response) { response.write ...

  7. Python星号表达式提取数据

    def drop_first_last(grades): first,*middle,last=grades return middle 这段代码的作用是grades中的元素,第一个和最后一个分别被提 ...

  8. shell 读取文件的每一行

    1.使用while #!/bin/bash while read line do echo $line done < file.txt #!/bin/bash cat file.txt | wh ...

  9. php floor()函数 语法

    php floor()函数 语法 floor函数是什么意思? php floor()函数用来向下舍入为最接近的整数.语法是floor(number),表示返回不大于参数number的下一个整数,有小数 ...

  10. delphi 动态获取文件类型的图标

    delphi 动态获取文件类型的图标.txt我不奢望什么,只希望你以后的女人一个不如一个.真怀念小时候啊,天热的时候我也可以像男人一样光膀子!在应用程序的编写中,组合框(ComboBox).列表框(L ...