All possible solutions to the problem of stable marriage

Preface:
Recently, I was asked to write an algorithm about stable marriage. Stable marriage is a classic problem. I will not describe it here. You can find a lot on the Internet. A famous algorithm to solve the stable marriage problem is G-S algorithm, also known as delay recognition algorithm, which will not be described in detail. This algorithm can only reach a single optimal solution. Not long ago, in a book, we saw an algorithm (exhaustive method) for finding all possible solutions of stable matching. These days due to the new pneumonia lead to special leisure (hope that the pneumonia will soon end), so I plan to write about it.

Specific method (implemented in C + +):

1. Algorithm idea:
First, find a perfect match, and then judge whether there are unstable factors in the perfect match. If there are, discard the perfect match (that is, the perfect match is not a stable match). If there are no unstable factors, output the perfect match (the perfect match is a stable match). Then continue to find the next perfect match, and judge

2. Specific code:
① First, define a data structure to store everyone's information:

typedef struct tagPartner
{
	string name;   //Name
	int next = 0;     //Next match
	int current = -1;  //Current pairing, - 1 means no pairing yet
	int pCount = UNIT_COUNT; //Number of favors in the list
	int* perfect = new int[UNIT_COUNT]; //Favorable list
}PARTNER;

② . find the perfect match and judge whether it is stable (main algorithm)

//Main algorithm part
void SearchStableMatch(int index, PARTNER *boys, PARTNER *girls)
{
	//If index = = Unit Ou count, it indicates that a set of perfect matching is successful and whether it is stable
	if (index == UNIT_COUNT)
	{
		if (IsStableMatch(boys, girls))//Judge whether it is a stable match
		{
			PrintResult(boys, girls, UNIT_COUNT);//Printing
		}
		return;
	}

	//Match the boy with index, i.e. find the perfect match
	for (int i = 0; i < boys[index].pCount; i++)
	{
		int gid = boys[index].perfect[i];//boy matching girl number

		if (!IsPartnerAssigned(&girls[gid]) && IsFavoritePartner(&girls[gid], index))//If girl gid has no objects, and index man is in her favorite list
		{
			boys[index].current = gid;//Match index men and gid women into a group
			girls[gid].current = index;
			SearchStableMatch(index + 1, boys, girls);//For the next man

			//The following two statements are the end of the recursive call, that is, a statement executed after a perfect match succeeds
			//Return to single status
			boys[index].current = -1;
			girls[gid].current = -1;
		}
	}
}

③ . judge whether the perfect match is stable

//Judge whether the match is stable
bool IsStableMatch(PARTNER *boys, PARTNER *girls)
{
	for (int i = 0; i < UNIT_COUNT; i++)
	{
		//Find the position of the boy's current match in his preference list
		int gpos = GetPerfectPosition(&boys[i], boys[i].current);
		//Before the position position, boys like them better than current
		for (int k = 0; k < gpos; k++)
		{
			int gid = boys[i].perfect[k];
			//Find the boy's place in the girl's liking list
			int bpos = GetPerfectPosition(&girls[gid], i);
			//Find the location of the girl's current partner in the girl's liking list
			int cpos = GetPerfectPosition(&girls[gid], girls[gid].current);
			if (bpos < cpos)
			{
				//Girls also like this boy better than their current partners, which is a factor of instability
				return false;
			}
		}
	}
	return true;
}

④ . other auxiliary functions

//Get the position of the person with id in the partner preference list
int GetPerfectPosition(PARTNER *partner, int id)
{
	for (int i = 0; i < partner->pCount; i++)
	{
		if (partner->perfect[i] == id)
		{
			return i;
		}
	}//Returns a very large value, which means it doesn't match the right value at all
	return 9999999;
}

void PrintResult(PARTNER *boys, PARTNER *girls, int count)
{
	for (int i = 0; i < count; i++)
	{
		out << boys[i].name << "<---> " << girls[boys[i].current].name << endl;
	}
	out << "========== " << endl;
}

//Judge whether the partner has objects
bool IsPartnerAssigned(PARTNER *partner)
{
	return (partner->current != -1);
}

//Judge whether the boy bid is the girl partner's favorite
bool IsFavoritePartner(PARTNER *partner, int bid)
{
	for (int i = 0; i < partner->pCount; i++)
	{
		if (partner->perfect[i] == bid)
		{
			return true;
		}
	}
	return false;
}

3. Optimize input and output:
Change the I / O to read in and read out of the file, for example:

Import file style:

4 / / number of people
 ==========/ / separator
 Three Zhang, four Li, four Wang, six Zhang, five / / space off the dating list (male side)
One flower, two flowers, three flowers and six flowers / / space off the blind date list (female side)
==========/ / separator
 2 3 1 0 / * sorting of the number of men's favorite girls, for example, the first line:
The most favorite girl of the boy (Zhang San) was No.2 (ER NAI), and the next was No				
0 23 1 3 (Sanhua), according to this rule
1 3 2 0                  */
==========
0.3.2 1 / / the ranking of the number of boys that the woman likes is the same as that of boys
0 1 2 3
0 2 3 1
1 0 3 2

Output file style: output all cases with good matching, divided by ====================(only one stable matching exists in this column)

Zhang San < --- > Sanhua
 Li Si
 Wang Liu
 Zhang Wu < --- > six flowers
========== 

Total code:

#include <stdio.h>
#include <cassert>
#include <iostream>
#include <stack>
#include <queue>
#include <vector>
#include<string>
#include <fstream>
using namespace std;
int UNIT_COUNT;
ofstream out("C:\\Users\\26216\\Desktop\\stable\\output.txt");
typedef struct tagPartner
{
	string name;   //Name
	int next = 0;     //Next match
	int current = -1;  //Current pairing, - 1 means no pairing yet
	int pCount = UNIT_COUNT; //Number of favors in the list
	int* perfect = new int[UNIT_COUNT]; //Favorable list
}PARTNER;


//Get the position of the person with id in the partner preference list
int GetPerfectPosition(PARTNER *partner, int id)
{
	for (int i = 0; i < partner->pCount; i++)
	{
		if (partner->perfect[i] == id)
		{
			return i;
		}
	}//Returns a very large value, which means it doesn't match
	return 9999999;
}

void PrintResult(PARTNER *boys, PARTNER *girls, int count)
{
	for (int i = 0; i < count; i++)
	{
		out << boys[i].name << "<---> " << girls[boys[i].current].name << endl;
	}
	out << "========== " << endl;
}

//Judge whether the partner has objects
bool IsPartnerAssigned(PARTNER *partner)
{
	return (partner->current != -1);
}

//Judge whether the boy bid is the girl partner's favorite
bool IsFavoritePartner(PARTNER *partner, int bid)
{
	for (int i = 0; i < partner->pCount; i++)
	{
		if (partner->perfect[i] == bid)
		{
			return true;
		}
	}
	return false;
}

//Judge whether the match is stable
bool IsStableMatch(PARTNER *boys, PARTNER *girls)
{
	for (int i = 0; i < UNIT_COUNT; i++)
	{
		//Find the position of the boy's current match in his preference list
		int gpos = GetPerfectPosition(&boys[i], boys[i].current);
		//Before the position position, boys like them better than current
		for (int k = 0; k < gpos; k++)
		{
			int gid = boys[i].perfect[k];
			//Find the boy's place in the girl's liking list
			int bpos = GetPerfectPosition(&girls[gid], i);
			//Find the location of the girl's current partner in the girl's liking list
			int cpos = GetPerfectPosition(&girls[gid], girls[gid].current);
			if (bpos < cpos)
			{
				//Girls also like this boy better than their current partners, which is a factor of instability
				return false;
			}
		}
	}
	return true;
}

//Main algorithm part
void SearchStableMatch(int index, PARTNER *boys, PARTNER *girls)
{
	//If index = = Unit Ou count, it indicates that a set of perfect matching is successful and whether it is stable
	if (index == UNIT_COUNT)
	{
		if (IsStableMatch(boys, girls))//Judge whether it is a stable match
		{
			PrintResult(boys, girls, UNIT_COUNT);//Printing
		}
		return;
	}

	//Match the boy with index, i.e. find the perfect match
	for (int i = 0; i < boys[index].pCount; i++)
	{
		int gid = boys[index].perfect[i];//boy matching girl number

		if (!IsPartnerAssigned(&girls[gid]) && IsFavoritePartner(&girls[gid], index))//If girl gid has no objects, and index man is in her favorite list
		{
			boys[index].current = gid;//Match index men and gid women into a group
			girls[gid].current = index;
			SearchStableMatch(index + 1, boys, girls);//For the next man

			//The following two statements are the end of the recursive call, that is, a statement executed after a perfect match succeeds
			//Return to single status
			boys[index].current = -1;
			girls[gid].current = -1;
		}
	}
}

int main(int argc, char* argv[])
{
	ifstream in("C:\\Users\\26216\\Desktop\\stable\\input.txt");
	in >> UNIT_COUNT;
	string* bName = new string[UNIT_COUNT];
	string* gName = new string[UNIT_COUNT];
	PARTNER* boys = new PARTNER[UNIT_COUNT];
	PARTNER* girls = new PARTNER[UNIT_COUNT];
	in.seekg(12, ios::cur);
	for (int i = 0; i < UNIT_COUNT; i++)
		in >> bName[i];
	for (int j = 0; j < UNIT_COUNT; j++)
		in >> gName[j];
	in.seekg(12, ios::cur);
	for (int i = 0; i < UNIT_COUNT; i++)
		for (int j = 0; j < UNIT_COUNT; j++)
			in >> boys[i].perfect[j];
	in.seekg(12, ios::cur);
	for (int i = 0; i < UNIT_COUNT; i++)
		for (int j = 0; j < UNIT_COUNT; j++)
			in >> girls[i].perfect[j];
	for (int i = 0; i < UNIT_COUNT; i++)
	{
		boys[i].name = bName[i];
		girls[i].name = gName[i];
	}
	in.close();
	SearchStableMatch(0, boys, girls);
	out.close();
	return 0;
}

Additional:
Here is a bit of java code. It is not input according to the file:

class PARTNER{
	public static int UNIT_COUNT;//Number of boys or girls
	public String name;	//Name
	public int next;		//Next invited
	public int current;	//Current object number
	public int pCount;		//Number of people in preference table
	public int []perfect=new int[UNIT_COUNT];//Preference list
	
	public PARTNER(String name,int next,int current,int pCount,int []perfect) {
		this.name=name;
		this.current=current;
		this.pCount=pCount;
		this.perfect=perfect;
	}
}

public class marriage {
	
	int GetPerfectPosition(PARTNER partner, int id)
	{
		for (int i = 0; i < partner.pCount; i++)
		{
			if (partner.perfect[i] == id)
			{
				return i;
			}
		}//Returns a very large value, which means it's not right at all
		return 0x7FFFFFFF;
	}

	void PrintResult(PARTNER []boys, PARTNER []girls, int count)
	{
		System.out.println("Results after pairing:");
		for (int i = 0; i < count; i++)
		{
			System.out.println( boys[i].name + "<---> " + girls[boys[i].current].name );
		}
		System.out.println("================");
	}

	boolean IsPartnerAssigned(PARTNER partner)
	{
		return (partner.current != -1);
	}

	boolean IsFavoritePartner(PARTNER partner, int bid)
	{
		for (int i = 0; i < partner.pCount; i++)
		{
			if (partner.perfect[i] == bid)
			{
				return true;
			}
		}
		return false;
	}

	boolean IsStableMatch(PARTNER []boys, PARTNER []girls)
	{
		for (int i = 0; i < PARTNER.UNIT_COUNT; i++)
		{
			//Find out where the boy's current partner is on his preference list
			int gpos = GetPerfectPosition(boys[i], boys[i].current);
			//Boys like their partners before position more than current
			for (int k = 0; k < gpos; k++)
			{
				int gid = boys[i].perfect[k];
				//Find the boy's place in the girl's preference list
				int bpos = GetPerfectPosition(girls[gid], i);
				//Find out where the girl's current partner is on the girl's preference list
				int cpos = GetPerfectPosition(girls[gid], girls[gid].current);
				if (bpos < cpos)
				{
					//Girls also like this boy better than their current partners, which is a factor of instability
					return false;
				}
			}
		}
		return true;
	}

	public void SearchStableMatch(int index, PARTNER []boys, PARTNER []girls)
	{
		if (index == PARTNER.UNIT_COUNT)
		{
			if (IsStableMatch(boys, girls))
			{
				PrintResult(boys, girls, PARTNER.UNIT_COUNT);
			}
			return;
		}
	
		for (int i = 0; i < boys[index].pCount; i++)
		{
			int gid = boys[index].perfect[i];
	
			if (!IsPartnerAssigned(girls[gid]) && IsFavoritePartner(girls[gid], index))
			{
				boys[index].current = gid;
				girls[gid].current = index;
				SearchStableMatch(index + 1, boys, girls);
				boys[index].current = -1;
				girls[gid].current = -1;
			}
		}
	}

	public static void main(String[] args) {
		
		PARTNER.UNIT_COUNT=3;
		PARTNER [] boys=new PARTNER[3];
		PARTNER [] girls=new PARTNER[3];
		
		int []a= {2,0,1};
		PARTNER boy1=new PARTNER("Zhang San", 0, -1, 3, a);
		int []b= {0,2,1};
		PARTNER boy2=new PARTNER("Li Si", 0, -1, 3, b);
		int []c= {1,0,2};
		PARTNER boy3=new PARTNER("Wang Wu", 0, -1, 3, c);
		
		int []ga= {0,2,1};
		PARTNER girl1=new PARTNER("A flower", 0, -1, 3, ga);
		int []gb= {1,2,0};
		PARTNER girl2=new PARTNER("Erhua", 0, -1, 3, gb);
		int []gc= {0,1,2};
		PARTNER girl3=new PARTNER("Three flowers", 0, -1, 3, gc);
		
		boys[0]=boy1;
		boys[1]=boy2;
		boys[2]=boy3;
		
		girls[0]=girl1;
		girls[1]=girl2;
		girls[2]=girl3;
		
		marriage m=new marriage();

		m.SearchStableMatch(0, boys, girls);
	}

}

Output results:

Results after pairing:
Zhang San
 Li Si < --- > Yihua
 Wang Wu
================
Results after pairing:
Zhang San
 Li Si
 Wang Wu
================

Reference: the fun of algorithm, Wang Xiaohua, people's post and Telecommunications Press

Published 4 original articles, won praise 2, visited 133
Private letter follow

Keywords: iOS Java

Added by drranch on Sat, 08 Feb 2020 10:42:50 +0200