app/soc/logic/allocations.py
changeset 1717 d4c4c8668871
parent 1651 ce52003ca18f
child 1718 ca34f4a8c61b
equal deleted inserted replaced
1716:a387bb7a39d4 1717:d4c4c8668871
    45   # I tried to write explicit code that does not require any
    45   # I tried to write explicit code that does not require any
    46   # additional comments (with the exception of the set notation for
    46   # additional comments (with the exception of the set notation for
    47   # the convenience of any mathematicians that happen to read this
    47   # the convenience of any mathematicians that happen to read this
    48   # piece of code ;).
    48   # piece of code ;).
    49 
    49 
    50   def __init__(self, orgs, applications, slots, max_slots_per_org):
    50   def __init__(self, orgs, applications, mentors, slots,
       
    51                max_slots_per_org, min_slots_per_org, iterative):
    51     """Initializes the allocator.
    52     """Initializes the allocator.
    52 
    53 
    53     Args:
    54     Args:
    54       orgs: a list of all the orgs that need to be allocated
    55       orgs: a list of all the orgs that need to be allocated
    55       applications: a dictionary with for each org a list of applicants
    56       applications: a dictionary with for each org a list of applicants
       
    57       mentors: the amount of assigned mentors per org
    56       slots: the total amount of available slots
    58       slots: the total amount of available slots
       
    59       max_slots_per_org: how many slots an org should get at most
       
    60       min_slots_per_org: how many slots an org should at least get
    57     """
    61     """
    58 
    62 
    59     all_applications = []
    63     all_applications = []
    60 
    64 
    61     for _, value in applications.iteritems():
    65     for _, value in applications.iteritems():
    62       all_applications += value
    66       all_applications += value
    63     
    67     
    64     self.locked_slots = {}
    68     self.locked_slots = {}
    65     self.adjusted_slots = {}
    69     self.adjusted_slots = {}
    66     self.adjusted_orgss = []
    70     self.adjusted_orgs = []
    67     self.locked_orgs = []
    71     self.locked_orgs = []
    68     self.unlocked_applications = []
    72     self.unlocked_applications = []
    69     self.slots = slots
    73     self.slots = slots
    70     self.max_slots_per_org = max_slots_per_org
    74     self.max_slots_per_org = max_slots_per_org
       
    75     self.min_slots_per_org = min_slots_per_org
    71     self.orgs = set(orgs)
    76     self.orgs = set(orgs)
    72     self.applications = applications
    77     self.applications = applications
       
    78     self.mentors = mentors
    73     self.all_applications = set(all_applications)
    79     self.all_applications = set(all_applications)
       
    80     self.iterative = iterative
    74 
    81 
    75   def allocate(self, locked_slots, adjusted_slots):
    82   def allocate(self, locked_slots, adjusted_slots):
    76     """Allocates the slots and returns the result.
    83     """Allocates the slots and returns the result.
    77 
    84 
    78     Args:
    85     Args:
    99     # set a and b
   106     # set a and b
   100     locked_orgs = set(locked_slots.keys())
   107     locked_orgs = set(locked_slots.keys())
   101     adjusted_orgs = set(adjusted_slots.keys())
   108     adjusted_orgs = set(adjusted_slots.keys())
   102 
   109 
   103     # set a' and b'
   110     # set a' and b'
   104     # unlocked_orgs = self.orgs.difference(locked_orgs)
   111     unlocked_orgs = self.orgs.difference(locked_orgs)
   105     # unadjusted_orgs = self.orgs.difference(adjusted_orgs)
   112     # unadjusted_orgs = self.orgs.difference(adjusted_orgs)
   106 
   113 
   107     # set a*b and a'*b'
   114     # set a*b and a'*b'
   108     locked_and_adjusted_orgs = locked_orgs.intersection(adjusted_orgs)
   115     locked_and_adjusted_orgs = locked_orgs.intersection(adjusted_orgs)
   109     
   116     
   127 
   134 
   128     # set l and l'
   135     # set l and l'
   129     locked_applications = set(itertools.chain(*locked_slots.keys()))
   136     locked_applications = set(itertools.chain(*locked_slots.keys()))
   130     unlocked_applications = all_applications.difference(locked_applications)
   137     unlocked_applications = all_applications.difference(locked_applications)
   131 
   138 
   132     self.adjusted_orgss = adjusted_orgs
   139     self.adjusted_orgs = adjusted_orgs
       
   140     self.unlocked_orgs = unlocked_orgs
   133     self.locked_orgs = locked_orgs
   141     self.locked_orgs = locked_orgs
   134     self.unlocked_applications = unlocked_applications
   142     self.unlocked_applications = unlocked_applications
       
   143 
       
   144     popularity = ((k, len(v)) for k, v in self.applications.iteritems())
       
   145     self.popularity = dict(popularity)
   135 
   146 
   136   def iterativeAllocation(self):
   147   def iterativeAllocation(self):
   137     """A simple iterative algorithm.
   148     """A simple iterative algorithm.
   138     """
   149     """
   139 
   150 
   140     adjusted_orgs = self.adjusted_orgss
   151     adjusted_orgs = self.adjusted_orgs
   141     adjusted_slots = self.adjusted_slots
   152     adjusted_slots = self.adjusted_slots
   142     locked_orgs = self.locked_orgs
   153     locked_orgs = self.locked_orgs
   143     locked_slots = self.locked_slots
   154     locked_slots = self.locked_slots
   144     unlocked_applications = self.unlocked_applications
   155     unlocked_applications = self.unlocked_applications
   145 
   156 
   150     allocations = {}
   161     allocations = {}
   151 
   162 
   152     for org in self.orgs:
   163     for org in self.orgs:
   153       org_applications = self.applications[org]
   164       org_applications = self.applications[org]
   154       org_applications_count = len(org_applications)
   165       org_applications_count = len(org_applications)
       
   166       mentors = self.mentors[org]
   155 
   167 
   156       if org in locked_orgs:
   168       if org in locked_orgs:
   157         slots = locked_slots[org]
   169         slots = locked_slots[org]
   158       else:
   170       else:
   159         weight = float(org_applications_count) / unallocated_applications_count
   171         weight = float(org_applications_count) / unallocated_applications_count
   161 
   173 
   162       if org in adjusted_orgs:
   174       if org in adjusted_orgs:
   163         slots += adjusted_slots[org]
   175         slots += adjusted_slots[org]
   164 
   176 
   165       slots = min(slots, self.max_slots_per_org)
   177       slots = min(slots, self.max_slots_per_org)
   166       slots = min(slots, org_applications_count)
   178       slots = min(slots, mentors)
   167       slots = min(slots, available_slots)
   179       slots = min(slots, available_slots)
   168 
   180 
   169       allocations[org] = slots
   181       allocations[org] = slots
   170       available_slots -= slots
   182       available_slots -= slots
   171       unallocated_applications_count -= org_applications_count
   183       unallocated_applications_count -= org_applications_count