Gale-Shapley实现(Python)导致的内存错误

时间:2018-11-04 07:58:13

标签: python algorithm dictionary optimization out-of-memory

这是基于Gale Shapley算法的代码。在此,我试图找出所有可能的首选项组合的所有稳定匹配。但这花费了太长时间而无法运行,并且给了我一个内存错误。我了解其中涉及数百万个计算,但是有人可以帮助我进行优化或采用其他方法进行优化。

import copy

from itertools import permutations, product


def sensitivity_analysis(dic1,dic2): #gives all the possible combinations of the preferences 
    a=copy.deepcopy(dic1)
    b=copy.deepcopy(dic2)
    length_a=len(a.keys())
    length_b=len(b.keys())
    items_a=list(a.keys())
    items_b=list(b.keys())
    a_variants = [dict(zip(items_a, values)) 
                 for values in product(permutations(items_b), repeat=length_a)]
    b_variants = [dict(zip(items_b, values)) 
                 for values in product(permutations(items_a), repeat=length_b)]

    all_variants = product(a_variants, b_variants)
    contains_a=[]
    contains_b=[]
    for i,j in all_variants:
        contains_a.append(i)
        contains_b.append(j)
    return contains_a,contains_b

def insert_dummies(a,b): #insert dummies into the dictionary to square up the participants on both sides
  length_a=len(a.keys())
  length_b=len(b.keys())
  items_a=list(a.keys())
  items_b=list(b.keys())
  dummy_list=[]
  if length_a>length_b:
    dummy_number=length_a-length_b
    nummer=1
    while nummer<dummy_number+1:
        dummy_list.append("Dummy%d" %nummer)
        nummer=nummer+1
    for i in items_a:
      f=0
      while dummy_number>f:
        a.setdefault(i,[]).append(dummy_list[f])
        f=f+1
    n=0    
    while n<(dummy_number):
      for z in dummy_list:
        b[z]=items_a
        n=n+1
  if length_a<length_b:
    dummy_number=length_b-length_a
    nummer=1
    while nummer<dummy_number+1:
        dummy_list.append("Dummy%d" %nummer)
        nummer=nummer+1
    for i in items_b:
      f=0
      while dummy_number>f:
        b.setdefault(i,[]).append(dummy_list[f])
        f=f+1
    n=0    
    while n<(dummy_number):
      for z in dummy_list:
        a[z]=items_b
        n=n+1
    else:
        return

  return a,b



#This function returns the result of the algorithm. Parameter 'a' refers to the preferences of the gender
#that we want to find the optimized solution for, while the parameter 'b' refers to the preferences of the other gender.
def StableMatching(a, b):
    #this function returns a stable matching
    dict_a = a.keys()  #This list contains the names of the group for we are optimizing.
    names1 = list(dict_a)
    dict_b = b.keys() #This list contains the names of the other group.
    names2 = list(dict_b)
    i = 0
    engaged = []
    #This dictionary contains the names of the gender for which we attempt to find the optimized solution.
    times = {}
    t = 0
    position_existing = 0
    position_potential = 0
    counter = 0
    #Can have the values 'free' or 'not free'.
    a_p = {}
    while(counter < len(names1)):
        a_p.update({names1[counter]: 'free'})
        counter = counter + 1

    counter = 0
    #Can have the values 'free' or 'not free'.
    b_p = {}
    while(counter < len(names2)):
        b_p.update({names2[counter]: 'free'})
        counter = counter + 1

    counter = 0
    #Initialization of times dictionary.
    while(counter < len(names1)):
        times.update({names1[counter]: 0})
        counter = counter + 1

    #The value -1 has the meaning that when all men or women are paired, the loop stops;
    while((i != -1) and (a_p[names1[i]] == 'free') and (times[names1[i]] < len(names2))):
        #The man/woman who is next in the ranking of the proposals.
        w = a[names1[i]][times[names1[i]]]
        if(b_p[w] == 'free'):
            a_p[names1[i]] = 'not free'
            b_p[w] = 'not free'
            t = (names1[i], w)
            engaged.append(t)
            times[names1[i]] = times[names1[i]] + 1
        else:
            q = 0
            while(q < (len(engaged))):
                  if(w in engaged[q]):
                      t1 = engaged[q]
                      l = 0
                      while(l < len(names1)):
                          if(names1[i] == b[w][l]):
                              position_potential = l
                              l = len(names1)
                          l = l + 1
                      l = 0
                      while(l < len(names1)):
                          if(t1[0] == b[w][l]):
                              position_existing = l
                              l = len(names1)
                          l = l + 1
                      if(position_potential < position_existing):
                          t = (names1[i], w)
                          engaged.append(t)
                          del(engaged[q])
                          a_p[names1[i]] = 'not free'
                          a_p[t1[0]] = 'free'
                          q = len(engaged)
                  q = q + 1

            times[names1[i]] = times[names1[i]] + 1
        i = i + 1
        #If the variable i has passed from all the men/women then it starts from the beginning
        #in order to check the ones who remain single.
        if(i == len(names1)):
            i = 0
        if(a_p[names1[i]] == 'not free'):
            k = 0
            z = False
            while((k < len(names1)) and (z == False)):
                if(a_p[names1[k]] == 'free'):
                    i = k
                    z = True
                k = k + 1
            if((k == len(names1)) and (z == False)):
                i = -1
    engaged_dict = dict(engaged)
    return engaged_dict

def check(engaged,a,b):
    inverseengaged = dict((v,k) for k,v in engaged.items())
    for she, he in engaged.items():
        shelikes = a[she]
        shelikesbetter = shelikes[:shelikes.index(he)]
        helikes = b[he]
        helikesbetter = helikes[:helikes.index(she)]
        for guy in shelikesbetter:
            guysgirl = inverseengaged[guy]
            guylikes = b[guy]
            if guylikes.index(guysgirl) > guylikes.index(she):
                print("%s and %s like each other better than "
                      "their present partners: %s and %s, respectively"
                      % (she, guy, he, guysgirl))
                return False
        for gal in helikesbetter:
            girlsguy = engaged[gal]
            gallikes = a[gal]
            if gallikes.index(girlsguy) > gallikes.index(he):
                print("%s and %s like each other better than "
                      "their present partners: %s and %s, respectively"
                      % (he, gal, she, girlsguy))
                return False
    return True

ra_position_preferences = {"yoder3":["J","E","T","S","M"],
                           "yoder4":["J","E","S","T","M"],
                           "kratz3":["M","J","S","E","T"],
                           "miller3":["S","M","J","E","T"]}

applicants_floor_prefernce ={"J":["yoder3","yoder4","kratz3","miller3"],
                             "E":["yoder3","yoder4","kratz3","miller3"],
                             "S":["kratz3","miller3","yoder3","yoder4"],
                             "M":["kratz3","miller3","yoder3","yoder3"],
                             "T":["nofloor","yoder4","yoder3","kratz3"]
                             }



list1=copy.deepcopy(sensitivity_analysis(ra_position_preferences,applicants_floor_prefernce)[0]) #contains list of all the dominant prefernces
list2=copy.deepcopy(sensitivity_analysis(ra_position_preferences,applicants_floor_prefernce)[1]) #contains list of all the other group prefernces
new_dic=[]
stabe=[]
i=0
while i<len(list1):
    newdic1 = {k:v[:] for k, v in list1[i].items()}
    newdic2 = {k:v[:] for k, v in list2[i].items()}
    almaty=insert_dummies(newdic1,newdic2)
    z=StableMatching(almaty[0], almaty[1])
    stab=check(z,almaty[0], almaty[1])
    new_dic.append(z)
    stabe.append(stab)
    i=i+1

result = [dict(tupleized) for tupleized in set(tuple(item.items()) for item in new_dic)]
d1=copy.deepcopy(ra_position_preferences)
d2=copy.deepcopy(applicants_floor_prefernce)
length_d1=len(d1.keys())
length_d2=len(d2.keys())
items_d1=list(d1.keys())
items_d2=list(d2.keys())
final_dic={}
for popo in items_d1:
    final_dic[popo]=[d[popo] for d in result]

0 个答案:

没有答案