ここでは2つのグループ(男、女)があり、お互いのグループの各メンバーは異なるグループのメンバーとカップルとなることを望んでおり、それぞれ異なるグループのメンバーについて、カップルとなりたい順序を持っているとする。 また誰ともカップルとならなかったら、最悪だと考えている。 さらにここでは簡単化のため、カップルの申し込みはグループ1のメンバーのみとする。
GSアルゴリズムの手順:
1. グループ1のメンバーはグループ2の第1希望のメンバーに一斉にカップルの申し込みを行う。
2. グループ2のメンバーは自分の好みにいちばん近い人を選んでキープし、残りのメンバーを拒否する
3. グループ1のメンバーは拒否される度に次に好みのメンバーに申し込む。
4. グループ2のメンバーはより好みのグループ1のメンバーの申し込みが来るたびにキープ相手を変更し、残りを断る。
※この作業を断られるグループ1のメンバーがいなくなるまで続ける。
/* * Stable Matching Algorithm * Gale-Shapley Algorithm */ #include <stdio.h> #include <stdlib.h> #include <time.h> /* prefrence value is stronger as value is small ( 0 is most prefered ) */ #define NUMBER 10 void set_random( int* ); void initialize( int **, int **, int *, int *, int * ); int main( int argc, char **argv ) { int i, j; /* NUMBER is invalid(initial) NUMBER */ int *men_pref[ NUMBER ], *women_pref[ NUMBER ]; /* preference list of women */ int prop_list[ NUMBER ]; int marriage_men[ NUMBER ]; int marriage_women[ NUMBER ]; initialize( men_pref, women_pref, prop_list, marriage_men, marriage_women ); for( j = 0; j < NUMBER; j++ ) { printf( "MAN[%d]: ", j ); for( i = 0; i < NUMBER; i++ ) printf( "%d, ", men_pref[ j ][ i ] ); printf( "\tWOMAN[%d]: ", j ); for( i = 0; i < NUMBER; i++ ) printf( "%d, ", women_pref[ j ][ i ] ); printf("\n"); } for( j = 0; j < NUMBER; j++ ) { printf( "== trial %d ==\n", j ); trial( men_pref, women_pref, prop_list, marriage_men, marriage_women ); printf("MEN: "); for( i = 0; i < NUMBER; i++ ) { printf( "%2d ", marriage_men[ i ] ); } printf( "\nWOMEN: " ); for( i = 0; i < NUMBER; i++ ) { printf( "%2d ", marriage_women[ i ] ); } printf( "\n" ); } for( i = 0; i < NUMBER; i++ ) { free( men_pref[ i ] ); free( women_pref[ i ] ); } return 0; } int trial( int *men_list[], int *women_list[], int *prop_list, int *marriage_men, int *marriage_women ) { int i, j; int man_index, woman_index; for( i = 0; i < NUMBER; i++ ) { if( marriage_men[ i ] != NUMBER ) { // already married continue; } woman_index = men_list[ i ][ prop_list [ i ] ]; if( marriage_women[ woman_index ] == NUMBER ) { // woman is free marriage_men[ i ] = woman_index; // marriage marriage_women[ woman_index ] = i; // marriage } else { man_index = marriage_women[ woman_index ]; // man married targeted woman for( j = 0; j < NUMBER; j++ ) { if( women_list[ woman_index ][ j ] == man_index ) // marriaged man is prefered break; else if( women_list[ woman_index ][ j ] == i ) { // proposed man is prefered marriage_men[ i ] = woman_index; // marriage marriage_women[ woman_index ] = i; // marriage marriage_men[ man_index ] = NUMBER; // dismarriage } } } prop_list[ i ] ++; } return 0; } void set_random( int *list ) { int i, tmp; for( i = 0; i < NUMBER; i++ ){ list[i] = NUMBER; } for( i = 0; i < NUMBER; i++ ){ while( list[( tmp = random( ) % NUMBER )] != NUMBER ); /* retry */ list[tmp] = i; /* set preference value */ } return; } void initialize( int *men_list[], int *women_list[], int *prop_list, int *marriage_men, int *marriage_women ) { int i, tmp; srandom( time( 0 ) ); for( i = 0; i < NUMBER; i++ ) { if( ( men_list[ i ] = (int *)malloc( NUMBER * sizeof( int ) ) ) == NULL ) { perror( "malloc" ); exit( EXIT_FAILURE ); } set_random( men_list[ i ] ); if( ( women_list[ i ] = (int *)malloc( NUMBER * sizeof( int ) ) ) == NULL ) { perror( "malloc" ); exit( EXIT_FAILURE ); } set_random( women_list[ i ] ); prop_list[ i ] = 0; marriage_men[ i ] = NUMBER; marriage_women[ i ] = NUMBER; } return; }
出力結果
MAN[0]: 2, 3, 8, 0, 4, 9, 1, 7, 5, 6, WOMAN[0]: 8, 3, 4, 7, 6, 0, 9, 1, 2, 5, MAN[1]: 9, 0, 6, 3, 5, 8, 7, 2, 1, 4, WOMAN[1]: 2, 5, 0, 8, 4, 3, 7, 1, 6, 9, MAN[2]: 1, 7, 6, 3, 0, 4, 2, 8, 9, 5, WOMAN[2]: 2, 9, 3, 5, 0, 4, 8, 1, 7, 6, MAN[3]: 6, 5, 2, 9, 1, 7, 8, 4, 0, 3, WOMAN[3]: 8, 4, 5, 7, 3, 6, 9, 2, 0, 1, MAN[4]: 6, 2, 5, 9, 0, 1, 7, 4, 3, 8, WOMAN[4]: 5, 4, 8, 3, 1, 9, 2, 0, 6, 7, MAN[5]: 9, 0, 2, 1, 3, 5, 4, 7, 8, 6, WOMAN[5]: 7, 5, 8, 0, 6, 1, 2, 9, 4, 3, MAN[6]: 5, 1, 3, 8, 6, 4, 7, 0, 9, 2, WOMAN[6]: 1, 3, 0, 4, 5, 7, 9, 6, 2, 8, MAN[7]: 7, 9, 4, 8, 3, 2, 5, 1, 0, 6, WOMAN[7]: 9, 2, 0, 3, 4, 1, 6, 5, 8, 7, MAN[8]: 2, 4, 1, 6, 3, 5, 9, 0, 8, 7, WOMAN[8]: 6, 4, 1, 8, 7, 5, 3, 0, 9, 2, MAN[9]: 8, 0, 2, 5, 4, 3, 9, 1, 7, 6, WOMAN[9]: 3, 2, 6, 4, 1, 7, 9, 0, 8, 5, == trial 0 == MEN: 2 9 1 6 10 10 5 7 10 8 WOMEN: 10 2 0 10 10 6 3 7 9 1 == trial 1 == MEN: 2 9 1 6 10 0 5 7 4 8 WOMEN: 5 2 0 10 8 6 3 7 9 1 == trial 2 == MEN: 2 9 1 6 10 0 5 7 4 8 WOMEN: 5 2 0 10 8 6 3 7 9 1 == trial 3 == MEN: 2 10 1 6 9 0 5 7 4 8 WOMEN: 5 2 0 10 8 6 3 7 9 4 == trial 4 == MEN: 10 0 1 6 9 2 5 7 4 8 WOMEN: 1 2 5 10 8 6 3 7 9 4 == trial 5 == MEN: 3 0 1 6 9 2 5 7 4 8 WOMEN: 1 2 5 0 8 6 3 7 9 4 == trial 6 == MEN: 3 0 1 6 9 2 5 7 4 8 WOMEN: 1 2 5 0 8 6 3 7 9 4 == trial 7 == MEN: 3 0 1 6 9 2 5 7 4 8 WOMEN: 1 2 5 0 8 6 3 7 9 4 == trial 8 == MEN: 3 0 1 6 9 2 5 7 4 8 WOMEN: 1 2 5 0 8 6 3 7 9 4 == trial 9 == MEN: 3 0 1 6 9 2 5 7 4 8 WOMEN: 1 2 5 0 8 6 3 7 9 4
#include <stdio.h> int verbose = 0; enum { clown = -1, abe, bob, col, dan, ed, fred, gav, hal, ian, jon, abi, bea, cath, dee, eve, fay, gay, hope, ivy, jan, }; const char *name[] = { "Abe", "Bob", "Col", "Dan", "Ed", "Fred", "Gav", "Hal", "Ian", "Jon", "Abi", "Bea", "Cath", "Dee", "Eve", "Fay", "Gay", "Hope", "Ivy", "Jan" }; int pref[jan + 1][jon + 1] = { { abi, eve, cath, ivy, jan, dee, fay, bea, hope, gay }, { cath, hope, abi, dee, eve, fay, bea, jan, ivy, gay }, { hope, eve, abi, dee, bea, fay, ivy, gay, cath, jan }, { ivy, fay, dee, gay, hope, eve, jan, bea, cath, abi }, { jan, dee, bea, cath, fay, eve, abi, ivy, hope, gay }, { bea, abi, dee, gay, eve, ivy, cath, jan, hope, fay }, { gay, eve, ivy, bea, cath, abi, dee, hope, jan, fay }, { abi, eve, hope, fay, ivy, cath, jan, bea, gay, dee }, { hope, cath, dee, gay, bea, abi, fay, ivy, jan, eve }, { abi, fay, jan, gay, eve, bea, dee, cath, ivy, hope }, { bob, fred, jon, gav, ian, abe, dan, ed, col, hal }, { bob, abe, col, fred, gav, dan, ian, ed, jon, hal }, { fred, bob, ed, gav, hal, col, ian, abe, dan, jon }, { fred, jon, col, abe, ian, hal, gav, dan, bob, ed }, { jon, hal, fred, dan, abe, gav, col, ed, ian, bob }, { bob, abe, ed, ian, jon, dan, fred, gav, col, hal }, { jon, gav, hal, fred, bob, abe, col, ed, dan, ian }, { gav, jon, bob, abe, ian, dan, hal, ed, col, fred }, { ian, col, hal, gav, fred, bob, abe, ed, jon, dan }, { ed, hal, gav, abe, bob, jon, col, ian, fred, dan }, }; int pairs[jan + 1], proposed[jan + 1]; void engage(int man, int woman) { pairs[man] = woman; pairs[woman] = man; if (verbose) printf("%4s is engaged to %4s\n", name[man], name[woman]); } void dump(int woman, int man) { pairs[man] = pairs[woman] = clown; if (verbose) printf("%4s dumps %4s\n", name[woman], name[man]); } /* how high this person ranks that: lower is more preferred */ int rank(int this, int that) { int i; for (i = abe; i <= jon && pref[this][i] != that; i++); return i; } void propose(int man, int woman) { int fiance = pairs[woman]; if (verbose) printf("%4s proposes to %4s\n", name[man], name[woman]); if (fiance == clown) { engage(man, woman); } else if (rank(woman, man) < rank(woman, fiance)) { dump(woman, fiance); engage(man, woman); } } int covet(int man1, int wife2) { if (rank(man1, wife2) < rank(man1, pairs[man1]) && rank(wife2, man1) < rank(wife2, pairs[wife2])) { printf( " %4s (w/ %4s) and %4s (w/ %4s) prefer each other" " over current pairing.\n", name[man1], name[pairs[man1]], name[wife2], name[pairs[wife2]] ); return 1; } return 0; } int thy_neighbors_wife(int man1, int man2) { /* +: force checking all pairs; "||" would shortcircuit */ return covet(man1, pairs[man2]) + covet(man2, pairs[man1]); } int unstable() { int i, j, bad = 0; for (i = abe; i < jon; i++) { for (j = i + 1; j <= jon; j++) if (thy_neighbors_wife(i, j)) bad = 1; } return bad; } int main() { int i, unengaged; /* init: everyone marries the clown */ for (i = abe; i <= jan; i++) pairs[i] = proposed[i] = clown; /* rounds */ do { unengaged = 0; for (i = abe; i <= jon; i++) { //for (i = abi; i <= jan; i++) { /* could let women propose */ if (pairs[i] != clown) continue; unengaged = 1; propose(i, pref[i][++proposed[i]]); } } while (unengaged); printf("Pairing:\n"); for (i = abe; i <= jon; i++) printf(" %4s - %s\n", name[i], pairs[i] == clown ? "clown" : name[pairs[i]]); printf(unstable() ? "Marriages not stable\n" /* draw sad face here */ : "Stable matchup\n"); printf("\nBut if Bob and Fred were to swap:\n"); i = pairs[bob]; engage(bob, pairs[fred]); engage(fred, i); printf(unstable() ? "Marriages not stable\n" : "Stable matchup\n"); return 0; }
出力結果
Pairing: Abe - Ivy Bob - Cath Col - Dee Dan - Fay Ed - Jan Fred - Bea Gav - Gay Hal - Eve Ian - Hope Jon - Abi Stable matchup But if Bob and Fred were to swap: Fred (w/ Cath) and Ivy (w/ Abe) prefer each other over current pairing. Bob (w/ Bea) and Fay (w/ Dan) prefer each other over current pairing. Bob (w/ Bea) and Hope (w/ Ian) prefer each other over current pairing. Bob (w/ Bea) and Abi (w/ Jon) prefer each other over current pairing. Fred (w/ Cath) and Dee (w/ Col) prefer each other over current pairing. Fred (w/ Cath) and Abi (w/ Jon) prefer each other over current pairing. Marriages not stable