###################################################################### ## FindingMatchings.txt Save this file as FindingMatchings.txt to # # use it, stay in the # ## same directory, get into Maple (by typing: maple ) # ## and then type: read FindingMatchings.txt # ## Then follow the instructions given there # ## # ## Written by AJ Bu, Kayla Gibson, Lucy Martinez, Natalya # ## Ter-Saakov, and Doron Zeilberger, Rutgers University # ###################################################################### print(`First Written : May 2022 : tested for Maple 2021 `): print(`Version: May 2022 `): print(): print(`This is FindingMatchings.txt, A Maple package`): print(`accompanying AJ Bu, Kayla Gibson, Lucy Martinez, and Natalya Ter-Saakov's article: `): print(`Analysis of the Gale-Shapley Algorithm for the Stable Marriage Problem `): print(): print(`The most current version is available on WWW at:`): print(` INSERT WEBSITE HERE .`): print(`Please report all bugs to: ab1854 at math dot rutgers dot edu .`): print(``): print(`----------------------------------------------------`): print(): print(`To see the major procedures in this package, type "Help()"`): print(): print(`For a list of the SUPPORTING functions type "Help1();" `): print(`For explanation of each procedure, type "WhatIs(procedure_name)"`): print(): print(`----------------------------------------------------`): print(`----------------------------------------------------`): with(combinat): Help:=proc(): print(`EstHappMenProp(n,K), EstHappWomenProp(n,K), AvgHapOverAllMatch(r)`): print(`AvgHapMenPropOverAllRank(n),AvgHapWomenPropOverAllRank(n)`): print(`AvgHapOverAllRankMatch(n),EstHappAllMatch(n,K)`): print(`GaleShCollegeAdmissions(A,C,Q), TerseGaleShCollegeAdmissions(A,C,Q)`): end: Help1:=proc(): print(` RT(n), IsStable1(M,W,pi,i1,i2), IsStable(M,W,pi), FindStable(M,W,K) `): print(`CountInstablities(M,W,pi), GFstab(n,K,x) `): print(` inv(pi), GaleSh(M,W), GaleShT(M,W), GaleShTw(M,W) `): print(`CheckOpt(M,W),CompGaleSh(M,W),EstStat(n,K),FindNeighbors(pi)`): print(`FindHappiness(M,W,matching), AllRank(n), AllMatchings(M,W), SlowAvgHapOverAllMatch(r)`): print(`inverse(pi,N)`): end: WhatIs:=proc(procedure): if procedure=FindHappiness then print(`FindHappiness(M,W,matching): inputs ranking tables M,W, and a matching`): print(`outputs the average happiness of the men and the average happiness of the women,`): print(`where a person's happiness is the ranking they gave their spouse they are matched with`): elif procedure=EstHappMenProp then print(`EstHappMenProp(n,K): inputs an integer n and a large integer K,`): print(`generates K examples of M,W (using RT(n)), applies the Gale-Shapley algorithm where the men propose,`): print(`and outputs the average happiness of the men and the average happiness of the women`): elif procedure=EstHappWomenProp then print(`EstHappWomenProp(n,K): inputs an integer n and a large integer K,`): print(`generates K examples of M,W (using RT(n)), applies the Gale-Shapley algorithm where the women propose,`): print(`and outputs the average happiness of the men and the average happiness of the women`): elif procedure=AllRank then print(`AllRank(n): The list of all ways n men (respectively, women) can rank n women (respectively, men)`): elif procedure=AllMatchings then print(`AllMatchings(M,W): inputs ranking tables M,W and outputs all stable matchings`): elif procedure=SlowAvgHapOverAllMatch then print(`SlowAvgHapOverAllMatch(M,W): inputs ranking tables M,W`): print(`and finds the average happiness of the men and the average happiness of the women over all stable matchings`): elif procedure=AvgHapOverAllMatch then print(`AvgHapOverAllMatch(M,W): inputs ranking tables M,W`): print(`and finds the average happiness of the men and the average happiness of the women over all stable matchings`): elif procedure=AvgHapMenPropOverAllRank then print(`AvgHapMenPropOverAllRank(n): Inputs an integer n and calculates, over all possible rankings of n men and n women,`): print(`the average happiness of the men and the average happiness of the women when men are proposing in the Gale-Shapley algorithm`): elif procedure=AvgHapWomenPropOverAllRank then print(`AvgHapWomenPropOverAllRank(n): Inputs an integer n and calculates, over all possible rankings of n men and n women,`): print(`the average happiness of the men and the average happiness of the women when women are proposing in the Gale-Shapley algorithm`): elif procedure=AvgHapOverAllRankMatch then print(`AvgHapOverAllRankMatch(n): Inputs an integer n and calculates the average happiness of men and the average happiness of women`): print(`over all possible rankings of n men and women and all stable matchings of each ranking`): elif procedure=EstHappAllMatch then print(`EstHappAllMatch(n,K): Inputs an integer n and a large integer K,`): print(`generates K examples of M,W (using RT(n)),`): print(`and outputs the average happiness of the men and the average happiness of the women`): print(`over all stable matchings of the K rankings`): elif procedure=RT then print(`RT(n): Generates a pair of random preference M,W, two lists-of-lists`): elif procedure=GaleShCollegeAdmissions then print(`GaleShCollegeAdmissions(A,C,Q): The Gale-Shapley algorithm: admissions version`): elif procedure=TerseGaleShCollegeAdmissions then print(`TerseGaleShCollegeAdmissions(A,C,Q): The Gale-Shapley algorithm: admissions version (TERSE)`): elif procedure=inverse then print(`inverse(pi,N): The inverse of an incomplete permutation pi`): fi: end: #RT(n): Generates a pair of random preference M,W, two lists-of-lists #M[i][j]:= The ranking of Ms. j in the eyes of Mr. i #W[j][i]:= The ranking of Mr. i in the eyes of Ms. j RT:=proc(n) local i,j: [seq(randperm(n),i=1..n)],[seq(randperm(n),j=1..n)]: end: # i1 is married to j1 #i2 is married to j2 #i1 would rather be married to j2 and j2 would rather be married to i1 IsStable1:=proc(M,W,pi,i1,i2) local j1,j2: j1:=pi[i1]: j2:=pi[i2]: not(M[i1][j2]i2 then if not IsStable1(M,W,pi,i1,i2) then RETURN(false, [i1,i2]): fi: fi: od: od: true,true: end: #FindStable(M,W,K): Given the Men's and Women's preference tables, starts with a random matching #and keeps "fixing it" until hopefully you get a stable matching, we limit the number of #iterations to K, if none found it will return FAIL. Otherwise it will return a stable #mathing, followed by the number if iterations it took FindStable:=proc(M,W,K) local n,pi,co,a,i1,i2,j1,j2: print(`Warning: This is a stupid program that usually FAILS, for larger n`): n:=nops(M): pi:=randperm(n): for co from 1 to K do a:=IsStable(M,W,pi): if a[1] then RETURN(pi,co): else i1:=a[2][1]: i2:=a[2][2]: j1:=pi[i1]: j2:=pi[i2]: if i1{} do #i is the current proposer i:=SinM[1]: #Mr. i proposes to the best remaining woman j:=Mrank[i][1]: #Mr. i1 is the current husband of Ms. j i1:=CurH[j]: co:=co+1: print(`I am Mr.`, i, `Ms. `, j, `would you marry me?`): if i1=0 then print(`Sure, you are my`, W[j][i], `-th choice, but since I am single it does not matter, so sure`): SinM:=SinM minus {i}: SinW:=SinW minus {j}: CurW[i]:=j: CurH[j]:=i: elif W[j][i1]{} do #i is the current proposer i:=SinM[1]: #Mr. i proposes to the best remaining woman j:=Mrank[i][1]: #Mr. i1 is the current husband of Ms. j i1:=CurH[j]: co:=co+1: if i1=0 then SinM:=SinM minus {i}: SinW:=SinW minus {j}: CurW[i]:=j: CurH[j]:=i: elif W[j][i1]M[i][MWprop[i]] then print("Mr.",i,"prefers the wife he would have had if the women proposed"): return(false): fi: if W[i][WMprop[i]]n+1 then return(FAIL) fi: [ops(GaleShT[1], 1..n)], GaleShT[2]: end: Compare:=proc(n) local K, M,W, fails, stupid, notStupid, st: stupid:=0: notStupid:=0:fails:=0: for K from 1 to 1000 do M,W:=RT(n): st:=FindStable(M,W,10000): if st=FAIL then fails+=1: elif st[2]0 do co+=1: for altPi in FindNeighbors(pi) do t:=CountInstabilities(M,W,altPi): if t0 then if Q[applicants[j]]>nops(waitlist[applicants[j]]) then printf(`Quota is non empty so %d is added to the waitlist and taken off of the rejected list. \n`,j): waitlist[applicants[j]]:=waitlist[applicants[j]] union {j}: rejected:=rejected minus {j}: else printf(`Quota is empty so we need to make a decision about %d \n`,j): #We need to make a decision. #Who is the highest (worst) ranked person in my waitlist? worst:=0: for k in waitlist[applicants[j]] do if CRank[applicants[j]][k]>worst then worst:=k: fi: od: printf(`The worst applicant in the waitlist is %d \n`, worst): if CRank[applicants[j]][j]0 then if Q[applicants[j]]>nops(waitlist[applicants[j]]) then waitlist[applicants[j]]:=waitlist[applicants[j]] union {j}: rejected:=rejected minus {j}: else #We need to make a decision. #Who is the highest (worst) ranked person in my waitlist? worst:=0: for k in waitlist[applicants[j]] do if CRank[applicants[j]][k]>worst then worst:=k: fi: od: if CRank[applicants[j]][j]