盖尔-沙普利算法

“盖尔-沙普利算法”(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. 一个spark streaming的黑名单过滤小例子

    > nc -lk 9999 20190912,sz 20190913,lin package com.lin.spark.streaming import org.apache.spark.Sp ...

  2. 金额格式化,例子:fmoney("12345.675910", 3),返回12,345.676

    /** * 金额格式化 * 例子:fmoney("12345.675910", 3),返回12,345.676 * @data 备注lhh 2016-09-18 */ functi ...

  3. linux+Apache开启伪静态配置

    linux+Apache伪静态配置 一.环境准备:CentOS Linux release 7.4.1708 (Core)1.配置源[root@localhost ~]#yum install -y ...

  4. DB2实例

    实例是逻辑数据库管理环境,可以在此环境中对数据库进行编目和设置配置参数.根据需要, 可以在一台服务器上创建多个实例,该服务器为每个实例提供唯一的数据库服务器环境.   默认实例:DB2   显示实例: ...

  5. Nginx+Keepalived主从配置(双机主从热备)+Tomcat集群

    拓扑环境 以下表格是这次測试须要的拓扑环境,几台server.每台server上安装什么,都有介绍. server名称 系统版本号 预装软件 IP地址/VIP Nginx主server CentOS ...

  6. 二、jQuery Ajax请求

    一.Ajax请求 1.jQuery Ajax请求 let ajaxTimeOut = $.ajax({ //将网络请求事件赋值给变量ajaxTimeOut url: "/api_v1.1/a ...

  7. RAD介绍及实战,LVM介绍及实战,磁盘常见故障

    目录 一.RAID 1.RAID好处: 2.RAID的运行方式: 3.RAID的级别: 二.RAID实战 软RAID 1.RAID0 2.RAID1 3.RAID5 4.RAID10 三.LVM介绍 ...

  8. Python中dict的特点

    dict的第一个特点是查找速度快,无论dict有10个元素还是10万个元素,查找速度都一样.而list的查找速度随着元素增加而逐渐下降. 不过dict的查找速度快不是没有代价的,dict的缺点是占用内 ...

  9. .net 开源项目地址

    https://github.com/dotnet/corefx 这个是.net core的 开源项目地址 https://github.com/aspnet 这个下面是asp.net core 框架 ...

  10. 全栈开发React-私有路由

    demo import React from 'react'; import {Route,Redirect} from 'react-router-dom' import {connect} fro ...