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算法 ...
随机推荐
- Structured Streaming本地local运行小例子
package com.lin.spark import org.apache.spark.sql.SparkSession object StructuredStreaming { def main ...
- CopyOnWriteArrayList(复制数组 去实现)
一.Vector和SynchronizedList 1.1回顾线程安全的Vector和SynchronizedList 我们知道ArrayList是用于替代Vector的,Vector是线程安全的容器 ...
- java并发编程之美-阅读记录7
java并发包中的并发队列 7.1ConcurrentLinkedQueue 线程安全的无界非阻塞队列(非阻塞队列使用CAS非阻塞算法实现),其底层数组使用单向列表实现,对于出队和入队操作使用CAS非 ...
- C#序列化json属性名首字母变成小写的解决方案
原文:C#序列化json属性名首字母变成小写的解决方案 //接口返回自动转小写,容易造成前后端不一致,获取不到数据,切换成转驼峰(首字母大写)如Code/Result //在ConfigureServ ...
- Python基础篇(is和==)
python基础篇(is,==,): 一.is和==的区别 1.id() 通过id()我们可以查看到一个变量表示的值在内存中的地址. s = 'alex' s = "alex" l ...
- 设计模式--简单工厂(Simple Factory)
工厂模式是最常用的一种创建型模式,通常所说的工厂模式一般是指工厂方法模式.本篇是是工厂方法模式的“小弟”,我们可以将其理解为工厂方法模式的预备知识,它不属于GoF 23种设计模式,但在软件开发中却也应 ...
- jgGrid常用操作--持续更新
最近有使用到jqGrid框架,有个需求是单击某个字段,比如name,然后把id带过去执行一个function,网上有说用线获取选中行,然后再得到id的方法,此方法经实验,必须要先选中才行,在用户没有进 ...
- C中整数的溢出
/** * 整数的溢出 */ #include <stdio.h> int main(int argc, char *argv[]) { short i = -24; // 将-24以无符 ...
- Blueprint的实现
Blueprint其实本身只是对view上的接口进行了注册,然后整体挂载在app上,Blueprint本身的目的就是组织多模块的平行共存,避免直接在app上注册view,其实更多的只是方便开发和代码的 ...
- hdu4857 拓扑排序
题目大意: 糟糕的事情发生啦,现在大家都忙着逃命.但是逃命的通道很窄,大家只能排成一行. 现在有n个人,从1标号到n.同时有一些奇怪的约束条件,每个都形如:a必须在b之前. 同时,社会是不平等的,这些 ...