September 2017 Update
This commit is contained in:
parent
bba7bfd280
commit
ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions
|
|
@ -0,0 +1,87 @@
|
|||
constant men = {"abe","bob","col","dan","ed","fred","gav","hal","ian","jon"}
|
||||
enum abe , bob , col , dan , ed , fred , gav , hal , ian , jon
|
||||
constant hen = {"abi","bea","cath","dee","eve","fay","gay","hope","ivy","jan"}
|
||||
enum abi , bea , cath , dee , eve , fay , gay , hope , ivy , jan
|
||||
|
||||
-- Given a complete list of ranked preferences, where the most liked is to the left:
|
||||
sequence mpref = repeat(0,length(men))
|
||||
mpref[abe] = {abi, eve, cath, ivy, jan, dee, fay, bea, hope, gay}
|
||||
mpref[bob] = {cath, hope, abi, dee, eve, fay, bea, jan, ivy, gay}
|
||||
mpref[col] = {hope, eve, abi, dee, bea, fay, ivy, gay, cath, jan}
|
||||
mpref[dan] = {ivy, fay, dee, gay, hope, eve, jan, bea, cath, abi}
|
||||
mpref[ed] = {jan, dee, bea, cath, fay, eve, abi, ivy, hope, gay}
|
||||
mpref[fred] = {bea, abi, dee, gay, eve, ivy, cath, jan, hope, fay}
|
||||
mpref[gav] = {gay, eve, ivy, bea, cath, abi, dee, hope, jan, fay}
|
||||
mpref[hal] = {abi, eve, hope, fay, ivy, cath, jan, bea, gay, dee}
|
||||
mpref[ian] = {hope, cath, dee, gay, bea, abi, fay, ivy, jan, eve}
|
||||
mpref[jon] = {abi, fay, jan, gay, eve, bea, dee, cath, ivy, hope}
|
||||
|
||||
sequence hpref = repeat(0,length(hen))
|
||||
hpref[abi] = {bob, fred, jon, gav, ian, abe, dan, ed, col, hal}
|
||||
hpref[bea] = {bob, abe, col, fred, gav, dan, ian, ed, jon, hal}
|
||||
hpref[cath] = {fred, bob, ed, gav, hal, col, ian, abe, dan, jon}
|
||||
hpref[dee] = {fred, jon, col, abe, ian, hal, gav, dan, bob, ed}
|
||||
hpref[eve] = {jon, hal, fred, dan, abe, gav, col, ed, ian, bob}
|
||||
hpref[fay] = {bob, abe, ed, ian, jon, dan, fred, gav, col, hal}
|
||||
hpref[gay] = {jon, gav, hal, fred, bob, abe, col, ed, dan, ian}
|
||||
hpref[hope] = {gav, jon, bob, abe, ian, dan, hal, ed, col, fred}
|
||||
hpref[ivy] = {ian, col, hal, gav, fred, bob, abe, ed, jon, dan}
|
||||
hpref[jan] = {ed, hal, gav, abe, bob, jon, col, ian, fred, dan}
|
||||
|
||||
sequence engagements := repeat(0,length(hen))
|
||||
sequence freemen = tagset(length(men))
|
||||
printf(1,"Engagements:\n")
|
||||
|
||||
-- use the Gale Shapley algorithm to find a stable set of engagements:
|
||||
while length(freemen) do
|
||||
integer man = freemen[1]
|
||||
freemen = freemen[2..$]
|
||||
integer fem, dumpee
|
||||
-- each male loops through all females in order of his preference until one accepts him
|
||||
for j=1 to length(mpref[man]) do
|
||||
fem = mpref[man][j]
|
||||
dumpee = engagements[fem]
|
||||
if dumpee=0
|
||||
or find(man,hpref[fem])<find(dumpee,hpref[fem]) then
|
||||
exit
|
||||
end if
|
||||
end for
|
||||
if dumpee!=0 then -- if she was previously engaged
|
||||
freemen &= dumpee -- he goes to the bottom of the list
|
||||
printf(1,"%s dumped %s and accepted %s\n",{hen[fem],men[dumpee],men[man]})
|
||||
else
|
||||
printf(1,"%s accepted %s\n",{hen[fem],men[man]})
|
||||
end if
|
||||
engagements[fem] := man -- the new engagement is registered
|
||||
end while
|
||||
|
||||
printf(1,"\nCouples:\n")
|
||||
for fem=1 to length(hen) do
|
||||
printf(1,"%s is engaged to %s\n",{hen[fem],men[engagements[fem]]})
|
||||
end for
|
||||
|
||||
procedure stable()
|
||||
bool unstable = false
|
||||
for fem=1 to length(hen) do
|
||||
integer man = engagements[fem]
|
||||
for j=1 to length(hen) do
|
||||
if find(fem,mpref[man])>find(j,mpref[man])
|
||||
and find(engagements[j],hpref[j])>find(man,hpref[j]) then
|
||||
if unstable=false then
|
||||
printf(1,"\nThese couples are not stable.\n")
|
||||
unstable = true
|
||||
end if
|
||||
printf(1,"%s is engaged to %s but would prefer %s and %s is engaged to %s but would prefer %s\n",
|
||||
{men[man],hen[fem],hen[j],hen[j],men[engagements[j]],men[man]})
|
||||
end if
|
||||
end for
|
||||
end for
|
||||
if not unstable then
|
||||
printf(1,"\nThese couples are stable.\n")
|
||||
end if
|
||||
end procedure
|
||||
|
||||
stable()
|
||||
printf(1,"\nWhat if cath and ivy swap?\n")
|
||||
engagements[cath]:=abe; engagements[ivy]:=bob
|
||||
stable()
|
||||
|
|
@ -1,121 +1,107 @@
|
|||
import java.util._
|
||||
import scala.collection.JavaConversions._
|
||||
|
||||
object SMP extends App {
|
||||
def run() {
|
||||
Seq("abe" -> Array("abi", "eve", "cath", "ivy", "jan", "dee", "fay", "bea", "hope", "gay"),
|
||||
"bob" -> Array("cath", "hope", "abi", "dee", "eve", "fay", "bea", "jan", "ivy", "gay"),
|
||||
"col" -> Array("hope", "eve", "abi", "dee", "bea", "fay", "ivy", "gay", "cath", "jan"),
|
||||
"dan" -> Array("ivy", "fay", "dee", "gay", "hope", "eve", "jan", "bea", "cath", "abi"),
|
||||
"ed" -> Array("jan", "dee", "bea", "cath", "fay", "eve", "abi", "ivy", "hope", "gay"),
|
||||
"fred" -> Array("bea", "abi", "dee", "gay", "eve", "ivy", "cath", "jan", "hope", "fay"),
|
||||
"gav" -> Array("gay", "eve", "ivy", "bea", "cath", "abi", "dee", "hope", "jan", "fay"),
|
||||
"hal" -> Array("abi", "eve", "hope", "fay", "ivy", "cath", "jan", "bea", "gay", "dee"),
|
||||
"ian" -> Array("hope", "cath", "dee", "gay", "bea", "abi", "fay", "ivy", "jan", "eve"),
|
||||
"jon" -> Array("abi", "fay", "jan", "gay", "eve", "bea", "dee", "cath", "ivy", "hope"))
|
||||
.foreach { e => guyPrefers.put(e._1, e._2.toList) }
|
||||
private def checkMarriages(): Unit =
|
||||
if (check)
|
||||
println("Marriages are stable")
|
||||
else
|
||||
println("Marriages are unstable")
|
||||
|
||||
Seq("abi" -> Array("bob", "fred", "jon", "gav", "ian", "abe", "dan", "ed", "col", "hal"),
|
||||
"bea" -> Array("bob", "abe", "col", "fred", "gav", "dan", "ian", "ed", "jon", "hal"),
|
||||
"cath" -> Array("fred", "bob", "ed", "gav", "hal", "col", "ian", "abe", "dan", "jon"),
|
||||
"dee" -> Array("fred", "jon", "col", "abe", "ian", "hal", "gav", "dan", "bob", "ed"),
|
||||
"eve" -> Array("jon", "hal", "fred", "dan", "abe", "gav", "col", "ed", "ian", "bob"),
|
||||
"fay" -> Array("bob", "abe", "ed", "ian", "jon", "dan", "fred", "gav", "col", "hal"),
|
||||
"gay" -> Array("jon", "gav", "hal", "fred", "bob", "abe", "col", "ed", "dan", "ian"),
|
||||
"hope" -> Array("gav", "jon", "bob", "abe", "ian", "dan", "hal", "ed", "col", "fred"),
|
||||
"ivy" -> Array("ian", "col", "hal", "gav", "fred", "bob", "abe", "ed", "jon", "dan"),
|
||||
"jan" -> Array("ed", "hal", "gav", "abe", "bob", "jon", "col", "ian", "fred", "dan"))
|
||||
.foreach { e => girlPrefers.put(e._1, e._2.toList) }
|
||||
private def swap() {
|
||||
val girl1 = girls.head
|
||||
val girl2 = girls(1)
|
||||
val tmp = girl2 -> matches(girl1)
|
||||
matches += girl1 -> matches(girl2)
|
||||
matches += tmp
|
||||
println(girl1 + " and " + girl2 + " have switched partners")
|
||||
}
|
||||
|
||||
val matches = matching(guys, guyPrefers, girlPrefers)
|
||||
matches.foreach { e => println(s"${e._1} is engaged to ${e._2}") }
|
||||
if (checkMatches(guys, girls, matches, guyPrefers, girlPrefers))
|
||||
println("Marriages are stable")
|
||||
else
|
||||
println("Marriages are unstable")
|
||||
private type TM = scala.collection.mutable.TreeMap[String, String]
|
||||
|
||||
val tmp = matches(girls(0))
|
||||
matches += girls(0) -> matches(girls(1))
|
||||
matches += girls(1) -> tmp
|
||||
println(girls(0) + " and " + girls(1) + " have switched partners")
|
||||
if (checkMatches(guys, girls, matches, guyPrefers, girlPrefers))
|
||||
println("Marriages are stable")
|
||||
else
|
||||
println("Marriages are unstable")
|
||||
}
|
||||
private def check: Boolean = {
|
||||
if (!girls.toSet.subsetOf(matches.keySet) || !guys.toSet.subsetOf(matches.values.toSet))
|
||||
return false
|
||||
|
||||
private def matching(guys: Iterable[String],
|
||||
guyPrefers: Map[String, List[String]],
|
||||
girlPrefers: Map[String, List[String]]): Map[String, String] = {
|
||||
val engagements = new TreeMap[String, String]
|
||||
val freeGuys = new LinkedList[String](guys)
|
||||
while (!freeGuys.isEmpty) {
|
||||
val guy = freeGuys.remove(0)
|
||||
val guy_p = guyPrefers(guy)
|
||||
var break = false
|
||||
for (girl <- guy_p)
|
||||
if (!break)
|
||||
if (!engagements.containsKey(girl)) {
|
||||
engagements += girl -> guy
|
||||
break = true
|
||||
}
|
||||
else {
|
||||
val other_guy = engagements(girl)
|
||||
val girl_p = girlPrefers(girl)
|
||||
if (girl_p.indexOf(guy) < girl_p.indexOf(other_guy)) {
|
||||
engagements += girl -> guy
|
||||
freeGuys += other_guy
|
||||
break = true
|
||||
val invertedMatches = new TM
|
||||
matches foreach { invertedMatches += _.swap }
|
||||
|
||||
for ((k, v) <- matches) {
|
||||
val shePrefers = girlPrefers(k)
|
||||
val sheLikesBetter = shePrefers.slice(0, shePrefers.indexOf(v))
|
||||
val hePrefers = guyPrefers(v)
|
||||
val heLikesBetter = hePrefers.slice(0, hePrefers.indexOf(k))
|
||||
|
||||
for (guy <- sheLikesBetter) {
|
||||
val fiance = invertedMatches(guy)
|
||||
val guy_p = guyPrefers(guy)
|
||||
if (guy_p.indexOf(fiance) > guy_p.indexOf(k)) {
|
||||
println(s"$k likes $guy better than $v and $guy likes $k better than their current partner")
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (girl <- heLikesBetter) {
|
||||
val fiance = matches(girl)
|
||||
val girl_p = girlPrefers(girl)
|
||||
if (girl_p.indexOf(fiance) > girl_p.indexOf(v)) {
|
||||
println(s"$v likes $girl better than $k and $girl likes $v better than their current partner")
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
engagements
|
||||
}
|
||||
private val guys = "abe" :: "bob" :: "col" :: "dan" :: "ed" :: "fred" :: "gav" :: "hal" :: "ian" :: "jon" :: Nil
|
||||
private val girls = "abi" :: "bea" :: "cath" :: "dee" :: "eve" :: "fay" :: "gay" :: "hope" :: "ivy" :: "jan" :: Nil
|
||||
private val guyPrefers = Map("abe" -> List("abi", "eve", "cath", "ivy", "jan", "dee", "fay", "bea", "hope", "gay"),
|
||||
"bob" -> List("cath", "hope", "abi", "dee", "eve", "fay", "bea", "jan", "ivy", "gay"),
|
||||
"col" -> List("hope", "eve", "abi", "dee", "bea", "fay", "ivy", "gay", "cath", "jan"),
|
||||
"dan" -> List("ivy", "fay", "dee", "gay", "hope", "eve", "jan", "bea", "cath", "abi"),
|
||||
"ed" -> List("jan", "dee", "bea", "cath", "fay", "eve", "abi", "ivy", "hope", "gay"),
|
||||
"fred" -> List("bea", "abi", "dee", "gay", "eve", "ivy", "cath", "jan", "hope", "fay"),
|
||||
"gav" -> List("gay", "eve", "ivy", "bea", "cath", "abi", "dee", "hope", "jan", "fay"),
|
||||
"hal" -> List("abi", "eve", "hope", "fay", "ivy", "cath", "jan", "bea", "gay", "dee"),
|
||||
"ian" -> List("hope", "cath", "dee", "gay", "bea", "abi", "fay", "ivy", "jan", "eve"),
|
||||
"jon" -> List("abi", "fay", "jan", "gay", "eve", "bea", "dee", "cath", "ivy", "hope"))
|
||||
private val girlPrefers = Map("abi" -> List("bob", "fred", "jon", "gav", "ian", "abe", "dan", "ed", "col", "hal"),
|
||||
"bea" -> List("bob", "abe", "col", "fred", "gav", "dan", "ian", "ed", "jon", "hal"),
|
||||
"cath" -> List("fred", "bob", "ed", "gav", "hal", "col", "ian", "abe", "dan", "jon"),
|
||||
"dee" -> List("fred", "jon", "col", "abe", "ian", "hal", "gav", "dan", "bob", "ed"),
|
||||
"eve" -> List("jon", "hal", "fred", "dan", "abe", "gav", "col", "ed", "ian", "bob"),
|
||||
"fay" -> List("bob", "abe", "ed", "ian", "jon", "dan", "fred", "gav", "col", "hal"),
|
||||
"gay" -> List("jon", "gav", "hal", "fred", "bob", "abe", "col", "ed", "dan", "ian"),
|
||||
"hope" -> List("gav", "jon", "bob", "abe", "ian", "dan", "hal", "ed", "col", "fred"),
|
||||
"ivy" -> List("ian", "col", "hal", "gav", "fred", "bob", "abe", "ed", "jon", "dan"),
|
||||
"jan" -> List("ed", "hal", "gav", "abe", "bob", "jon", "col", "ian", "fred", "dan"))
|
||||
|
||||
private def checkMatches(guys: Iterable[String], girls: Iterable[String],
|
||||
matches: Map[String, String],
|
||||
guyPrefers: Map[String, List[String]],
|
||||
girlPrefers: Map[String, List[String]]): Boolean = {
|
||||
if (!matches.keySet.containsAll(girls) || !matches.values.containsAll(guys))
|
||||
return false
|
||||
|
||||
val invertedMatches = new TreeMap[String, String]
|
||||
matches.foreach { invertedMatches += _.swap }
|
||||
|
||||
for ((k, v) <- matches) {
|
||||
val shePrefers = girlPrefers(k)
|
||||
val sheLikesBetter = new LinkedList[String]
|
||||
sheLikesBetter.addAll(shePrefers.subList(0, shePrefers.indexOf(v)))
|
||||
val hePrefers = guyPrefers(v)
|
||||
val heLikesBetter = new LinkedList[String]
|
||||
heLikesBetter.addAll(hePrefers.subList(0, hePrefers.indexOf(k)))
|
||||
|
||||
for (guy <- sheLikesBetter) {
|
||||
val fiance = invertedMatches(guy)
|
||||
val guy_p = guyPrefers(guy)
|
||||
if (guy_p.indexOf(fiance) > guy_p.indexOf(k)) {
|
||||
println(s"$k likes $guy better than $v and $guy likes $k better than their current partner")
|
||||
return false
|
||||
private lazy val matches = {
|
||||
val engagements = new TM
|
||||
val freeGuys = scala.collection.mutable.Queue.empty ++ guys
|
||||
while (freeGuys.nonEmpty) {
|
||||
val guy = freeGuys.dequeue()
|
||||
val guy_p = guyPrefers(guy)
|
||||
var break = false
|
||||
for (girl <- guy_p)
|
||||
if (!break)
|
||||
if (!engagements.contains(girl)) {
|
||||
engagements(girl) = guy
|
||||
break = true
|
||||
}
|
||||
else {
|
||||
val other_guy = engagements(girl)
|
||||
val girl_p = girlPrefers(girl)
|
||||
if (girl_p.indexOf(guy) < girl_p.indexOf(other_guy)) {
|
||||
engagements(girl) = guy
|
||||
freeGuys += other_guy
|
||||
break = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (girl <- heLikesBetter) {
|
||||
val fiance = matches(girl)
|
||||
val girl_p = girlPrefers(girl)
|
||||
if (girl_p.indexOf(fiance) > girl_p.indexOf(v)) {
|
||||
println(s"$v likes $girl better than $k and $girl likes $v better than their current partner")
|
||||
return false
|
||||
}
|
||||
}
|
||||
engagements foreach { e => println(s"${e._1} is engaged to ${e._2}") }
|
||||
engagements
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
private val guys = "abe" :: "bob" :: "col" :: "dan" :: "ed" :: "fred" :: "gav" :: "hal" :: "ian" :: "jon" :: Nil
|
||||
private val girls = "abi" :: "bea" :: "cath" :: "dee" :: "eve" :: "fay" :: "gay" :: "hope" :: "ivy" :: "jan" :: Nil
|
||||
private val guyPrefers = new HashMap[String, List[String]]
|
||||
private val girlPrefers = new HashMap[String, List[String]]
|
||||
|
||||
run()
|
||||
checkMarriages()
|
||||
swap()
|
||||
checkMarriages()
|
||||
}
|
||||
|
|
|
|||
62
Task/Stable-marriage-problem/Zkl/stable-marriage-problem.zkl
Normal file
62
Task/Stable-marriage-problem/Zkl/stable-marriage-problem.zkl
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
var
|
||||
Boys=Dictionary(
|
||||
"abe", "abi eve cath ivy jan dee fay bea hope gay".split(),
|
||||
"bob", "cath hope abi dee eve fay bea jan ivy gay".split(),
|
||||
"col", "hope eve abi dee bea fay ivy gay cath jan".split(),
|
||||
"dan", "ivy fay dee gay hope eve jan bea cath abi".split(),
|
||||
"ed", "jan dee bea cath fay eve abi ivy hope gay".split(),
|
||||
"fred","bea abi dee gay eve ivy cath jan hope fay".split(),
|
||||
"gav", "gay eve ivy bea cath abi dee hope jan fay".split(),
|
||||
"hal", "abi eve hope fay ivy cath jan bea gay dee".split(),
|
||||
"ian", "hope cath dee gay bea abi fay ivy jan eve".split(),
|
||||
"jon", "abi fay jan gay eve bea dee cath ivy hope".split(), ),
|
||||
Girls=Dictionary(
|
||||
"abi", "bob fred jon gav ian abe dan ed col hal".split(),
|
||||
"bea", "bob abe col fred gav dan ian ed jon hal".split(),
|
||||
"cath","fred bob ed gav hal col ian abe dan jon".split(),
|
||||
"dee", "fred jon col abe ian hal gav dan bob ed".split(),
|
||||
"eve", "jon hal fred dan abe gav col ed ian bob".split(),
|
||||
"fay", "bob abe ed ian jon dan fred gav col hal".split(),
|
||||
"gay", "jon gav hal fred bob abe col ed dan ian".split(),
|
||||
"hope","gav jon bob abe ian dan hal ed col fred".split(),
|
||||
"ivy", "ian col hal gav fred bob abe ed jon dan".split(),
|
||||
"jan", "ed hal gav abe bob jon col ian fred dan".split(), ),
|
||||
Couples=List(); // ( (boy,girl),(boy,girl),...)
|
||||
|
||||
Boyz:=Boys.pump(Dictionary(),fcn([(b,gs)]){ return(b,gs.copy()) }); // make writable copy
|
||||
while( bgs:=Boyz.filter1( 'wrap([(Boy,gs)]){ // while unattached boy
|
||||
gs and (not Couples.filter1("holds",Boy))
|
||||
}) )
|
||||
{
|
||||
Boy,Girl:=bgs; Girl=Girl.pop(0);
|
||||
Pair:=Couples.filter1("holds",Girl); // is Girl part of a couple?
|
||||
if(not Pair) Couples.append(List(Boy,Girl)); # no, Girl was free
|
||||
else{ // yes, Girl is engaged to Pair[0]
|
||||
bsf,nBoy,nB:=Girls[Girl].index, bsf(Boy),bsf(Pair[0]);
|
||||
if(nBoy<nB) Pair[0]=Boy; # Girl prefers Boy, change Couples
|
||||
}
|
||||
}
|
||||
foreach Boy,Girl in (Couples){ println(Girl," is engaged to ",Boy) }
|
||||
|
||||
fcn checkCouples(Couples){
|
||||
Couples.filter(fcn([(Boy,Girl)]){
|
||||
Girls[Girl].filter1('wrap(B){
|
||||
// is B before Boy in Girls preferences?
|
||||
bsf,nBoy,nB:=Girls[Girl].index, bsf(Boy),bsf(B);
|
||||
// Does B prefer Girl (over his partner)?
|
||||
_,G:=Couples.filter1("holds",B); // (B,G)
|
||||
gsf,nGirl,nG:=Boys[B].index, gsf(Girl),gsf(G);
|
||||
( nB<nBoy and nGirl<nG and
|
||||
println(Girl," likes ",B," better than ",Boy," and ",
|
||||
B," likes ",Girl," better than ",G) )
|
||||
})
|
||||
}) or println("All marriages are stable");
|
||||
}
|
||||
|
||||
checkCouples(Couples);
|
||||
println();
|
||||
|
||||
println("Engage fred with abi and jon with bea");
|
||||
Couples.filter1("holds","fred")[1]="abi";
|
||||
Couples.filter1("holds","jon") [1]="bea";
|
||||
checkCouples(Couples);
|
||||
Loading…
Add table
Add a link
Reference in a new issue