Guest User

Medical_Match_2

a guest
Feb 21st, 2015
2,073
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.16 KB | None | 0 0
  1. #!/usr/bin/python
  2.  
  3. ## programe-Shapley algorithm
  4. # http://www.nrmp.org/match-process/match-algorithm/
  5. # http://www.nber.org/papers/w6963
  6.  
  7. # From http://rosettacode.org/wiki/Stable_marriage_problem
  8. # Uses deepcopy to make actual copy of the contents of the dictionary in a new object
  9. # http://pymotw.com/2/copy/
  10.  
  11. import copy
  12. from collections import defaultdict
  13.  
  14. #Create python dictionary with names as keys, values as list
  15. studentprefers = {
  16.  'Alex':  ['American', 'Mercy', 'County', 'Mission', 'General', 'Fairview', 'Saint Mark', 'City', 'Deaconess', 'Park'],
  17.  'Brian':  ['County', 'Deaconess', 'American', 'Fairview', 'Mercy', 'Saint Mark', 'City', 'General', 'Mission', 'Park'],
  18.  'Cassie':  ['Deaconess', 'Mercy', 'American', 'Fairview', 'City', 'Saint Mark', 'Mission', 'Park', 'County', 'General'],
  19.  'Dana':  ['Mission', 'Saint Mark', 'Fairview', 'Park', 'Deaconess', 'Mercy', 'General', 'City', 'County', 'American'],
  20.  'Edward':   ['General', 'Fairview', 'City', 'County', 'Saint Mark', 'Mercy', 'American', 'Mission', 'Deaconess', 'Park'],
  21.  'Faith': ['City', 'American', 'Fairview', 'Park', 'Mercy', 'Mission', 'County', 'General', 'Deaconess', 'Saint Mark'],
  22.  'George':  ['Park', 'Mercy', 'Mission', 'City', 'County', 'American', 'Fairview', 'Deaconess', 'General', 'Saint Mark'],
  23.  'Hannah':  ['American', 'Mercy', 'Deaconess', 'Saint Mark', 'Mission', 'County', 'General', 'City', 'Park', 'Fairview'],
  24.  'Ian':  ['Park', 'County', 'Fairview', 'Deaconess', 'City', 'American', 'Saint Mark', 'Mission', 'General', 'Mercy'],
  25.  #'Ian':  ['Park'],
  26.  'Jessica':  ['American', 'Saint Mark', 'General', 'Park', 'Mercy', 'City', 'Fairview', 'County', 'Mission', 'Deaconess']}
  27. programprefers = {
  28.  'American':  ['Brian', 'Faith', 'Jessica', 'George', 'Ian', 'Alex', 'Dana', 'Edward', 'Cassie', 'Hannah'],
  29.  'City':  ['Brian', 'Alex', 'Cassie', 'Faith', 'George', 'Dana', 'Ian', 'Edward', 'Jessica', 'Hannah'],
  30.  'County': ['Faith', 'Brian', 'Edward', 'George', 'Hannah', 'Cassie', 'Ian', 'Alex', 'Dana', 'Jessica'],
  31.  'Fairview':  ['Faith', 'Jessica', 'Cassie', 'Alex', 'Ian', 'Hannah', 'George', 'Dana', 'Brian', 'Edward'],
  32.  'Mercy':  ['Jessica', 'Hannah', 'Faith', 'Dana', 'Alex', 'George', 'Cassie', 'Edward', 'Ian', 'Brian'],
  33.  'Saint Mark':  ['Brian', 'Alex', 'Edward', 'Ian', 'Jessica', 'Dana', 'Faith', 'George', 'Cassie', 'Hannah'],
  34.  'Park':  ['Jessica', 'George', 'Hannah', 'Faith', 'Brian', 'Alex', 'Cassie', 'Edward', 'Dana', 'Ian'],
  35.  'Deaconess': ['George', 'Jessica', 'Brian', 'Alex', 'Ian', 'Dana', 'Hannah', 'Edward', 'Cassie', 'Faith'],
  36.  'Mission':  ['Ian', 'Cassie', 'Hannah', 'George', 'Faith', 'Brian', 'Alex', 'Edward', 'Jessica', 'Dana'],
  37.  'General':  ['Edward', 'Hannah', 'George', 'Alex', 'Brian', 'Jessica', 'Cassie', 'Ian', 'Faith', 'Dana']}
  38. programSlots = {
  39.  'American': 1,
  40.  'City': 1,
  41.  'County': 1,
  42.  'Fairview': 1,
  43.  'Mercy': 1,
  44.  'Saint Mark': 2,
  45.  'Park': 1,
  46.  'Deaconess': 2,
  47.  'Mission': 2,
  48.  'General': 9}
  49.  
  50. students = sorted(studentprefers.keys())
  51. programs = sorted(programprefers.keys())
  52.  
  53.  
  54.  
  55. def matchmaker():
  56.     studentsfree = students[:]
  57.     studentslost = []
  58.     matched = {}
  59.     for programName in programs:
  60.         if programName not in matched:
  61.              matched[programName] = list()
  62.     studentprefers2 = copy.deepcopy(studentprefers)
  63.     programprefers2 = copy.deepcopy(programprefers)
  64.     while studentsfree:
  65.         student = studentsfree.pop(0)
  66.         print("%s is on the market" % (student))
  67.         studentslist = studentprefers2[student]
  68.         program = studentslist.pop(0)
  69.         print("  %s (program's #%s) is checking out %s (student's #%s)" % (student, (programprefers[program].index(student)+1), program, (studentprefers[student].index(program)+1)) )
  70.         tempmatch = matched.get(program)
  71.         if len(tempmatch) < programSlots.get(program):
  72.             # Program's free
  73.             if student not in matched[program]:
  74.                 matched[program].append(student)
  75.                 print("    There's a spot! Now matched: %s and %s" % (student.upper(), program.upper()))
  76.         else:
  77.             # The student proposes to an full program!
  78.             programslist = programprefers2[program]
  79.             for (i, matchedAlready) in enumerate(tempmatch):
  80.                 if programslist.index(matchedAlready) > programslist.index(student):
  81.                     # Program prefers new student
  82.                     if student not in matched[program]:
  83.                         matched[program][i] = student
  84.                         print("  %s dumped %s (program's #%s) for %s (program's #%s)" % (program.upper(), matchedAlready, (programprefers[program].index(matchedAlready)+1), student.upper(), (programprefers[program].index(student)+1)))
  85.                         if studentprefers2[matchedAlready]:
  86.                             # Ex has more programs to try
  87.                             studentsfree.append(matchedAlready)
  88.                         else:
  89.                             studentslost.append(matchedAlready)
  90.                 else:
  91.                     # Program still prefers old match
  92.                     print("  %s would rather stay with %s (their #%s) over %s (their #%s)" % (program, matchedAlready, (programprefers[program].index(matchedAlready)+1), student, (programprefers[program].index(student)+1)))
  93.                     if studentslist:
  94.                         # Look again
  95.                         studentsfree.append(student)
  96.                     else:
  97.                         studentslost.append(student)
  98.     print
  99.     for lostsoul in studentslost:
  100.         print('%s did not match' % lostsoul)
  101.     return (matched, studentslost)
  102.  
  103.  
  104.  
  105.  
  106.  
  107. def check(matched):
  108.     inversematched = defaultdict(list)
  109.     for programName in matched.keys():
  110.         for studentName in matched[programName]:
  111.             inversematched[programName].append(studentName)
  112.  
  113.     for programName in matched.keys():
  114.         for studentName in matched[programName]:
  115.  
  116.             programNamelikes = programprefers[programName]
  117.             programNamelikesbetter = programNamelikes[:programNamelikes.index(studentName)]
  118.             helikes = studentprefers[studentName]
  119.             helikesbetter = helikes[:helikes.index(programName)]
  120.             for student in programNamelikesbetter:
  121.                 for p in inversematched.keys():
  122.                     if student in inversematched[p]:
  123.                         studentsprogram = p
  124.                 studentlikes = studentprefers[student]
  125.                
  126.                 ## Not sure if this is correct
  127.                 try:
  128.                     studentlikes.index(studentsprogram)
  129.                 except ValueError:
  130.                     continue
  131.                
  132.                 if studentlikes.index(studentsprogram) > studentlikes.index(programName):
  133.                     print("%s and %s like each other better than "
  134.                           "their present match: %s and %s, respectively"
  135.                           % (programName, student, studentName, studentsprogram))
  136.                     return False
  137.             for program in helikesbetter:
  138.                 programsstudents = matched[program]
  139.                 programlikes = programprefers[program]
  140.                 for programsstudent in programsstudents:
  141.                     if programlikes.index(programsstudent) > programlikes.index(studentName):
  142.                         print("%s and %s like each other better than "
  143.                               "their present match: %s and %s, respectively"
  144.                               % (studentName, program, programName, programsstudent))
  145.                         return False
  146.     return True
  147.  
  148.  
  149. print('\nPlay-by-play:')
  150. (matched, studentslost) = matchmaker()
  151.  
  152. print('\nCouples:')
  153. print('  ' + ',\n  '.join('%s is matched to %s' % couple
  154.                           for couple in sorted(matched.items())))
  155. print
  156. print('Match stability check PASSED'
  157.       if check(matched) else 'Match stability check FAILED')
  158.  
  159. print('\n\nSwapping two matches to introduce an error')
  160. matched[programs[0]], matched[programs[1]] = matched[programs[1]], matched[programs[0]]
  161. for program in programs[:2]:
  162.     print('  %s is now matched to %s' % (program, matched[program]))
  163. print
  164. print('Match stability check PASSED'
  165.       if check(matched) else 'Match stability check FAILED')
Advertisement
Add Comment
Please, Sign In to add comment