In [1]:
#とりあえずone-to-one改良しました。
#時間をはかれるようにする
def da0(m_pref_input,f_pref_input):
    start=time.time()
 
    m_pref_array=np.array(m_pref_input)
    f_pref_array=np.array(f_pref_input)
    
    #受け入れ側の選考リストを申し込み側の番号の場所に申し込み側の被選考順序が書いてある状態にする
    f_prefsort=np.argsort(f_pref_array)
    
    m_popu=m_pref_array.shape[0]
    f_popu=f_pref_array.shape[0]
    
    #未マッチのリスト
    free=list(range(m_popu))
    
    #マッチングリストを作成。-1が初期値
    m_match=np.tile([-1],m_popu)
    f_match=np.tile([-1],f_popu)
    
    #こっからメインのループ
    while len(free) > 0:
        applyman = free.pop()
      
        apply_prefs=m_pref_array[applyman]
        
        #apply側の選考をみる
        for prefered in apply_prefs:

          
            if prefered == f_popu:
                m_match[applyman]=f_popu
                break
            
            else:
                prefered_pref = f_prefsort[prefered]
                rank_apply = prefered_pref[applyman]
                rank_non_match = prefered_pref[m_popu]
                
                if rank_non_match < rank_apply:
                    continue
                
                else:
                    
                    matched_man=f_match[prefered]
            
                    if matched_man==-1:
                        m_match[applyman]=prefered
                        f_match[prefered]=applyman
                        break
                
                    else:
                        rank_matched=prefered_pref[matched_man]
                
                        if rank_apply < rank_matched:
                            m_match[applyman]=prefered
                            f_match[prefered]=applyman
                            m_match[matched_man]=-1
                            free.append(matched_man)
                            break
                    
                #for文を入れればelseはいらない
    
    for i in range(f_popu):
        if f_match[i] == -1:
            f_match[i]=m_popu
    
    elapsed_time = time.time() - start        
    print elapsed_time

    return [m_match,f_match]

In [ ]:


In [ ]:
#とりあえずmany-to-oneのコードに変更する。
#capsは長さnの一次元配列(i番目がfemale_iの受け入れ人数)
#別にcapsの要素に制限はない
#出力はmatching_list二つと、i番目までのfemaleが受け入れたmaleの数を累積で記し、冒頭に0を加えたindptrの三つ
#方針は二つ。①最初から長さlのリストを作っておいて、indptrと関連させながら動かす
#②各femaleでcaps分のlistを作り、呼び出しながら使う
#とりあえず②の方針で
import numpy as np
import time
def deferred_acceptance(m_pref_input,f_pref_input,caps):
    start=time.time()
 
    #とりまnp_arrayに変換
    m_pref_array=np.array(m_pref_input)
    f_pref_array=np.array(f_pref_input)
    caps_array=np.array(caps)
    
    #受け入れ側の選考リストを申し込み側の番号の場所に申し込み側の被選考順序が書いてある状態にする
    f_prefsort=np.argsort(f_pref_array)
    
    m_popu=m_pref_array.shape[0]
    f_popu=f_pref_array.shape[0]
    
    #未マッチのリスト
    free=list(range(m_popu))
    
    #マッチングリストを作成。-1が初期値
    m_match=np.tile([-1],m_popu)

    #n個の空のリストを辞書にくっつける
    f_accept = {}
    for i in range(f_popu):
        f_accept[i] = []

    
    #こっからメインのループ
    while len(free) > 0:
        applyman = free.pop()
      
        apply_prefs=m_pref_array[applyman]
        
        #apply側の選考をみる
        for prefered in apply_prefs:

            if prefered == f_popu:
                m_match[applyman]=f_popu
                break
            
            else:
                prefered_pref = f_prefsort[prefered]
                rank_apply = prefered_pref[applyman]
                rank_non_match = prefered_pref[m_popu]
                
                if rank_non_match < rank_apply:
                    continue
                
                #ここまでのループ処理はone-to-oneと同じ
                
                else:
                   
                    #もしpreferedのcapsがオーバーしていなかったら
                    prefered_accept = f_accept[prefered]
                    
                    if len(prefered_accept) < caps[prefered]:
                        m_match[applyman]=prefered
                        
                        #prefered_acceptの中は右に行くほどpreferedに取って望ましくない奴がいるようにしたい
                        if len(prefered_accept) == 0:
                            prefered_accept.append(applyman)
                        
                        else:
                            for i in range(len(prefered_accept)):
                                
                                rank_already = prefered_pref[prefered_accept[i]]
                            
                                if rank_already < rank_apply:
                                    break
                                    
                                else:
                                    prefered_accept.insert(i,applyman)
                        break
                    
                    #もしpreferedのcapsいっぱいに人が入っていたら
                    else:
                        last_man = prefered_accept[-1]
                        rank_last_man=prefered_pref[last_man]
                
                        if rank_apply < rank_last_man:
                            m_match[applyman]=prefered
                            for i in range(len(prefered_accept)):
                                
                                rank_already = prefered_pref[prefered_accept[i]]
                            
                                if rank_already < rank_apply:
                                    break
                                    
                                else:
                                    prefered_accept.insert(i,applyman)
                        
                        m_match[last_man]=-1
                        free.append(last_man)
                        break
    
    #capsに満たなかったfのacceptに不足分だけのunmatch番号を加える
    for i in range(f_popu):
        f_indi = f_accept[i]
        gap = caps[i] - len(f_indi)
        
        if gap > 0:
            residual = [m_popu] * gap
            f_indi.extend(residual)
            continue
    
    #f_acceptの各リストを結合してf_matchにする
    f_match = []
    for i in range(f_popu):
        f_match.extend(f_accept[i])
        
    #最後にindptrの作成
    indptr = np.cumsum(caps)
    l_indptr = list(indptr)
    l_indptr.insert(0,0)
    
    
    elapsed_time = time.time() - start        
    print elapsed_time

    return [list(m_match),f_match,l_indptr]

#一応出力はできますが、テスト通らないので直します。

In [ ]:
#many-to-one完成版
def deferred_acceptance(m_pref_input,f_pref_input,caps):
  

    m_pref_array=np.array(m_pref_input)
    f_pref_array=np.array(f_pref_input)
    caps_array=np.array(caps)
    
    
    f_prefsort=np.argsort(f_pref_array)
    
    m_popu=m_pref_array.shape[0]
    f_popu=f_pref_array.shape[0]
    
    
    free=list(range(m_popu))
    
    
    m_match=np.tile([f_popu],m_popu)

   
    f_accept = {}
    for i in range(f_popu):
        f_accept[i] = []
            
    
    
    while len(free) > 0:
        applyman = free.pop()
        print applyman
        apply_prefs=m_pref_array[applyman]
        print apply_prefs
       
        for prefered in apply_prefs:
            print prefered
            if prefered == f_popu:
                m_match[applyman]=f_popu
                print m_match
                break
            
            else:
                prefered_pref = f_prefsort[prefered]
                print prefered_pref
                rank_apply = prefered_pref[applyman]
                rank_non_match = prefered_pref[m_popu]
                
                if rank_non_match > rank_apply:
                    prefered_accept = f_accept[prefered]
                    print prefered_accept
                    
                    if len(prefered_accept) < caps[prefered]:
                        
                        if len(prefered_accept) == 0:
                            prefered_accept.append(applyman)
                            print prefered_accept
                            m_match[applyman] = prefered
                            print m_match
                            break
                        
                
                        else:
                            for i in range(len(prefered_accept)):
                                
                                rank_already = prefered_pref[prefered_accept[i]]
                                m_match[applyman] = prefered
                                print m_match
                                
                                if rank_already > rank_apply:
                                    prefered_accept.insert(i,applyman)
                                    print prefered_accept
                                    break
                                    
                                else:
                                    if i == len(prefered_accept)-1:
                                        prefered_accept.append(applyman)
                                        print prefered_accept
                            break
                     
                 
                    else:
                        for i in range(len(prefered_accept)): 
                            rank_already = prefered_pref[prefered_accept[i]]
                            
                            if rank_already > rank_apply: 
                                
                                prefered_accept.insert(i,applyman)
                                
                                unmatch_man = prefered_accept.pop()
                                print unmatch_man
                                m_match[unmatch_man]=f_popu
                                m_match[applyman] = prefered
                                print m_match
                                free.append(unmatch_man)
                                print free
                                print prefered_accept
                                break
                                    
                                
                        if applyman in prefered_accept:
                            break
                        
                        else:
                            continue
                            
                
    for i in range(f_popu):
        f_indi = f_accept[i]
        gap = caps[i] - len(f_indi)
        
        if gap > 0:
            residual = [m_popu] * gap
            f_indi.extend(residual)
    
 
    f_match = []
    for i in range(f_popu):
        f_match.extend(f_accept[i])
        
    
    indptr = np.cumsum(caps)
    l_indptr = list(indptr)
    l_indptr.insert(0,0)

    return [list(m_match),f_match,l_indptr]

In [ ]:
#Noneに対応?
#時間を図れるように
#各シャープをとれば経過が観れます
import time
def deferred_acceptance(m_pref_input,f_pref_input,caps):
    
    start = time.time()
    m_pref_array=np.array(m_pref_input)
    f_pref_array=np.array(f_pref_input)
    f_prefsort=np.argsort(f_pref_array)
    m_popu=m_pref_array.shape[0]
    f_popu=f_pref_array.shape[0]
    
    if caps == None:
        caps = [1] * f_popu
    
    caps_array=np.array(caps)
    
    
    free=list(range(m_popu))
    
    
    m_match=np.tile([f_popu],m_popu)

   
    f_accept = {}
    for i in range(f_popu):
        f_accept[i] = []
            
    
    
    while len(free) > 0:
        applyman = free.pop()
        #print applyman
        apply_prefs=m_pref_array[applyman]
        #print apply_prefs
       
        for prefered in apply_prefs:
            #print prefered
            if prefered == f_popu:
                m_match[applyman]=f_popu
                #print m_match
                break
            
            else:
                prefered_pref = f_prefsort[prefered]
                #print prefered_pref
                rank_apply = prefered_pref[applyman]
                rank_non_match = prefered_pref[m_popu]
                
                if rank_non_match > rank_apply:
                    prefered_accept = f_accept[prefered]
                    #print prefered_accept
                    
                    if len(prefered_accept) < caps[prefered]:
                        
                        if len(prefered_accept) == 0:
                            prefered_accept.append(applyman)
                            #print prefered_accept
                            m_match[applyman] = prefered
                            #print m_match
                            break
                        
                
                        else:
                            for i in range(len(prefered_accept)):
                                
                                rank_already = prefered_pref[prefered_accept[i]]
                                m_match[applyman] = prefered
                                #print m_match
                                
                                if rank_already > rank_apply:
                                    prefered_accept.insert(i,applyman)
                                    #print prefered_accept
                                    break
                                    
                                else:
                                    if i == len(prefered_accept)-1:
                                        prefered_accept.append(applyman)
                                        #print prefered_accept
                            break
                     
                 
                    else:
                        for i in range(len(prefered_accept)): 
                            rank_already = prefered_pref[prefered_accept[i]]
                            
                            if rank_already > rank_apply: 
                                
                                prefered_accept.insert(i,applyman)
                                
                                unmatch_man = prefered_accept.pop()
                                #print unmatch_man
                                m_match[unmatch_man]=f_popu
                                m_match[applyman] = prefered
                                #print m_match
                                free.append(unmatch_man)
                                #print free
                                #print prefered_accept
                                break
                                    
                                
                        if applyman in prefered_accept:
                            break
                        
                        else:
                            continue
                            
                
    for i in range(f_popu):
        f_indi = f_accept[i]
        gap = caps[i] - len(f_indi)
        
        if gap > 0:
            residual = [m_popu] * gap
            f_indi.extend(residual)
    
 
    f_match = []
    for i in range(f_popu):
        f_match.extend(f_accept[i])
        
    
    indptr = np.cumsum(caps)
    l_indptr = list(indptr)
    l_indptr.insert(0,0)
    
    end = time.time()
    lapse = end - start

    if caps == [1] * f_popu:
        print lapse
        return [list(m_match),f_match]
    
    else:
        print lapse
        return [list(m_match),f_match,l_indptr]

In [ ]:
#un_match人数の出力

def deferred_acceptance(m_pref_input,f_pref_input,caps):
    

    m_pref_array=np.array(m_pref_input)
    f_pref_array=np.array(f_pref_input)
    f_prefsort=np.argsort(f_pref_array)
    m_popu=m_pref_array.shape[0]
    f_popu=f_pref_array.shape[0]
    
    if caps == None:
        caps = [1] * f_popu
    
    caps_array=np.array(caps)
    
    
    free=list(range(m_popu))
    
    
    m_match=np.tile([f_popu],m_popu)

   
    f_accept = {}
    for i in range(f_popu):
        f_accept[i] = []
            
    
    
    while len(free) > 0:
        applyman = free.pop()
        #print applyman
        apply_prefs=m_pref_array[applyman]
        #print apply_prefs
       
        for prefered in apply_prefs:
            #print prefered
            if prefered == f_popu:
                m_match[applyman]=f_popu
                #print m_match
                break
            
            else:
                prefered_pref = f_prefsort[prefered]
                #print prefered_pref
                rank_apply = prefered_pref[applyman]
                rank_non_match = prefered_pref[m_popu]
                
                if rank_non_match > rank_apply:
                    prefered_accept = f_accept[prefered]
                    #print prefered_accept
                    
                    if len(prefered_accept) < caps[prefered]:
                        
                        if len(prefered_accept) == 0:
                            prefered_accept.append(applyman)
                            #print prefered_accept
                            m_match[applyman] = prefered
                            #print m_match
                            break
                        
                
                        else:
                            for i in range(len(prefered_accept)):
                                
                                rank_already = prefered_pref[prefered_accept[i]]
                                m_match[applyman] = prefered
                                #print m_match
                                
                                if rank_already > rank_apply:
                                    prefered_accept.insert(i,applyman)
                                    #print prefered_accept
                                    break
                                    
                                else:
                                    if i == len(prefered_accept)-1:
                                        prefered_accept.append(applyman)
                                        #print prefered_accept
                            break
                     
                 
                    else:
                        for i in range(len(prefered_accept)): 
                            rank_already = prefered_pref[prefered_accept[i]]
                            
                            if rank_already > rank_apply: 
                                
                                prefered_accept.insert(i,applyman)
                                
                                unmatch_man = prefered_accept.pop()
                                #print unmatch_man
                                m_match[unmatch_man]=f_popu
                                m_match[applyman] = prefered
                                #print m_match
                                free.append(unmatch_man)
                                #print free
                                #print prefered_accept
                                break
                                    
                                
                        if applyman in prefered_accept:
                            break
                        
                        else:
                            continue
                            
                
    for i in range(f_popu):
        f_indi = f_accept[i]
        gap = caps[i] - len(f_indi)
        
        if gap > 0:
            residual = [m_popu] * gap
            f_indi.extend(residual)
    
 
    f_match = []
    for i in range(f_popu):
        f_match.extend(f_accept[i])
        
    
    indptr = np.cumsum(caps)
    l_indptr = list(indptr)
    l_indptr.insert(0,0)
    
  

    if caps == [1] * f_popu:
        count = 0
        for i in m_match:
            if m_match[i] == f_popu:
                count += 1
        return count
        #print lapse
        #return [list(m_match),f_match]
    
    else:
        count = 0
        for i in m_match:
            if m_match[i] == f_popu:
                count += 1
        return count
        #print lapse
        #return [list(m_match),f_match,l_indptr]

In [ ]:
#unmatch_numberは平均15人もいる。
caps = [8,8,8,8,8]
unmatch_number = []
for i in range(1000):

    m_prefs, f_prefs = random_prefs(40, 5)
    unmatch_number.append(deferred_acceptance(m_prefs,f_prefs,caps))

np.array(unmatch_number)
np.average(unmatch_number)

In [ ]:
#Noneに対応しました
import time
def deferred_acceptance(m_pref_input,f_pref_input,caps=None):
    
    #start = time.time()
    m_pref_array=np.array(m_pref_input)
    f_pref_array=np.array(f_pref_input)
    f_prefsort=np.argsort(f_pref_array)
    m_popu=m_pref_array.shape[0]
    f_popu=f_pref_array.shape[0]
    
    if caps == None:
        caps = [1] * f_popu
    
    caps_array=np.array(caps)
    
    
    free=list(range(m_popu))
    
    
    m_match=np.tile([f_popu],m_popu)

   
    f_accept = {}
    for i in range(f_popu):
        f_accept[i] = []
            
    
    
    while len(free) > 0:
        applyman = free.pop()
        #print applyman
        apply_prefs=m_pref_array[applyman]
        #print apply_prefs
       
        for prefered in apply_prefs:
            #print prefered
            if prefered == f_popu:
                m_match[applyman]=f_popu
                #print m_match
                break
            
            else:
                prefered_pref = f_prefsort[prefered]
                #print prefered_pref
                rank_apply = prefered_pref[applyman]
                rank_non_match = prefered_pref[m_popu]
                
                if rank_non_match > rank_apply:
                    prefered_accept = f_accept[prefered]
                    #print prefered_accept
                    
                    if len(prefered_accept) < caps[prefered]:
                        
                        if len(prefered_accept) == 0:
                            prefered_accept.append(applyman)
                            #print prefered_accept
                            m_match[applyman] = prefered
                            #print m_match
                            break
                        
                
                        else:
                            for i in range(len(prefered_accept)):
                                
                                rank_already = prefered_pref[prefered_accept[i]]
                                m_match[applyman] = prefered
                                #print m_match
                                
                                if rank_already > rank_apply:
                                    prefered_accept.insert(i,applyman)
                                    #print prefered_accept
                                    break
                                    
                                else:
                                    if i == len(prefered_accept)-1:
                                        prefered_accept.append(applyman)
                                        #print prefered_accept
                            break
                     
                 
                    else:
                        for i in range(len(prefered_accept)): 
                            rank_already = prefered_pref[prefered_accept[i]]
                            
                            if rank_already > rank_apply: 
                                
                                prefered_accept.insert(i,applyman)
                                
                                unmatch_man = prefered_accept.pop()
                                #print unmatch_man
                                m_match[unmatch_man]=f_popu
                                m_match[applyman] = prefered
                                #print m_match
                                free.append(unmatch_man)
                                #print free
                                #print prefered_accept
                                break
                                    
                                
                        if applyman in prefered_accept:
                            break
                        
                        else:
                            continue
                            
                
    for i in range(f_popu):
        f_indi = f_accept[i]
        gap = caps[i] - len(f_indi)
        
        if gap > 0:
            residual = [m_popu] * gap
            f_indi.extend(residual)
    
 
    f_match = []
    for i in range(f_popu):
        f_match.extend(f_accept[i])
        
    
    indptr = np.cumsum(caps)
    l_indptr = list(indptr)
    l_indptr.insert(0,0)
    
    #end = time.time()
    #lapse = end - start

    if caps == [1] * f_popu:
        #print lapse
        return [list(m_match),f_match]
    
    else:
        #print lapse
        return [list(m_match),f_match,l_indptr]