In [1]:
#ランダムな選考の作成
from matching_tools import random_prefs

In [2]:
import numpy as np

In [6]:
m_prefs, f_prefs = random_prefs(15, 3)

In [8]:
m_prefs


Out[8]:
array([[2, 3, 1, 0],
       [0, 2, 3, 1],
       [2, 3, 0, 1],
       [0, 2, 1, 3],
       [0, 1, 3, 2],
       [0, 1, 2, 3],
       [1, 3, 2, 0],
       [0, 1, 2, 3],
       [0, 1, 3, 2],
       [0, 2, 3, 1],
       [2, 1, 3, 0],
       [1, 2, 3, 0],
       [1, 2, 0, 3],
       [3, 2, 1, 0],
       [0, 1, 3, 2]])

In [81]:
b=[]
for i in m_prefs[3]:
    print i
    b.append(i)
    print b


1
[1]
2
[1, 2]
0
[1, 2, 0]
3
[1, 2, 0, 3]

In [9]:
f_prefs


Out[9]:
array([[ 6,  1,  5,  2, 14,  3,  0, 15,  9, 12,  8, 11,  4, 13, 10,  7],
       [ 9, 10, 15,  4,  5,  0,  2,  7,  3, 11, 13, 14, 12,  1,  6,  8],
       [ 8, 12,  3,  9,  2,  5, 11,  6, 13,  0, 10,  7, 14,  1, 15,  4]])

In [21]:
np.argsort(f_prefs)


Out[21]:
array([[0, 1, 2, 4, 3],
       [1, 3, 4, 0, 2],
       [3, 2, 0, 4, 1]])

In [108]:
#many-to-one matching をやってみる前に,遅かったのでone-to-oneを改善
#辞書はあくまで使わない方針で
#変数名はわかりやすいほうがいいので面倒くさがらず書く
#argsortはすごい便利
#できればリスト内包表記に

def da0(m_pref_input,f_pref_input):
    
    #まずはnumpy のarrayに変換する
    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()
        print applyman
        apply_prefs=m_pref_array[applyman]
        
        #apply側の選考をみる
        for prefered in apply_prefs:

            print prefered
            print m_match
            print f_match
            
            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
    return [m_match,f_match]

In [87]:
a=np.array([[0,1,2,3],[2,0,1,3],[1,2,0,3],[2,0,1,3]])
b=np.array([[2,0,1,3,4],[0,1,2,3,4],[2,4,1,0,3]])

In [88]:
a


Out[88]:
array([[0, 1, 2, 3],
       [2, 0, 1, 3],
       [1, 2, 0, 3],
       [2, 0, 1, 3]])

In [93]:
np.argsort(b)


Out[93]:
array([[1, 2, 0, 3, 4],
       [0, 1, 2, 3, 4],
       [3, 2, 0, 4, 1]])

In [109]:
#テスト成功
da0(a,b)


3
2
[-1 -1 -1 -1]
[-1 -1 -1]
0
[-1 -1 -1 -1]
[-1 -1 -1]
2
1
[-1 -1 -1  0]
[ 3 -1 -1]
1
2
[-1 -1  1  0]
[ 3  2 -1]
0
[-1 -1  1  0]
[ 3  2 -1]
3
2
[-1  0  1 -1]
[ 1  2 -1]
0
[-1  0  1 -1]
[ 1  2 -1]
1
[-1  0  1 -1]
[ 1  2 -1]
3
[-1  0  1 -1]
[ 1  2 -1]
0
0
[-1  0  1  3]
[ 1  2 -1]
1
2
[ 0 -1  1  3]
[ 0  2 -1]
0
[ 0 -1  1  3]
[ 0  2 -1]
1
[ 0 -1  1  3]
[ 0  2 -1]
2
1
[ 0  1 -1  3]
[ 0  1 -1]
2
[ 0  1 -1  3]
[ 0  1 -1]
Out[109]:
[array([0, 1, 2, 3]), array([0, 1, 2])]

In [110]:
import time

In [120]:
#時間をはかれるようにする
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 [121]:
da0(a,b)


0.000125885009766
Out[121]:
[array([0, 1, 2, 3]), array([0, 1, 2])]

In [127]:
#たくさんでやってみる
c,d = random_prefs(1000,1000)

In [128]:
da0(c,d) #速いのか?


0.119740962982
Out[128]:
[array([  59,  622,  868,  671,  880, 1000,  421,   84,  519,  317,   78,
         476,    4,  529,  128,  342,  369,  871, 1000,   39,  178,  378,
         620,  654,  980,  380,  764,  576,  812,  176,  381,  828,  384,
         933,  104,  670,   47,  243,  907,  766,  164,  840,  214,  417,
         971,  595,  850,  839,  834,  873,  617,  961,  631,  557,  861,
         333,  144,  824,  516,  266,  626,  641,   73,  830,  723,  526,
         409,  931,  188,  147,  615,  591,   86,  685,   65,  724,   27,
         913,  145,   31,  141,  245,  212,  646,  510,  956,  944,  572,
         899,  777,  833,  551,  320,  463,  383,  387,  660,  474,  170,
         763,   66,  694,  583,  847,  829,  368,  431,  509,   34,  458,
         379,  962,  280,  475,  491,  413,  539, 1000,  774,  351,  113,
         497,  584,  661,  793,  682,  156,  657,  878,  848, 1000,  352,
         891,  716,  392,  821,  874,  299,  752,  459,  181,  401,  689,
         471,  699,  756,  863,  930,  747,  225,  149,  580,  158,  179,
         316,  986,  393,  536,   14,   30,  701,  466,  100,  787,  326,
         711,  894,  197, 1000,   24,  408,  311,  610,  760,  721,  434,
         867,  356,  635,   12,  148,  121,  772,  742,  118,  922,  728,
         782,  545,  412,  301,  722,  346,  217,  588,  209,  738,  137,
         967,  858,  811,  645,  490,  285,  875,   92,   72,  904,  310,
         122,  304,   16,  131,  273,  105,  797,  555,  806,  604,  982,
         427,  769,  575,  691,   18,  678,  832,  403,  634,   55,  423,
         274,  110,  743,  255,  322, 1000,  932,  532,  644,  884,  210,
         315,  517,  488,  248,  707,  837,  552,  538, 1000,  359,  911,
         327,  720,   52,   46,  744,  808,   58,  550,  771,  195,  440,
         196,  438,  482,  561,  442,  504,  233,  261,   32,  296,  492,
        1000,  603, 1000,  366,  713,  866,  165,  375,  469,  372,   68,
         749,  252,  598,  949,  397,  189,   25,  251,  173,  445,  114,
         505,  391,  642,  124,  813,   64,    3,  361,  246,  200,  339,
         318,  651,  242,  292,  775,  674,  842,  477,  496, 1000,  712,
         690,  966,  546,  879,   89,  424,  328,  735, 1000,  649,  751,
         542,  247,  597,  725,  810,  590,  730,  973,  988,  436,  271,
         159,  759,   40,  940,  910,  223,  602,  335,  792,  870,  688,
         826,  347,  945,  172,   71,  437,  773,  309,  746,  715,  410,
           1,  855,  185,   81,  544,  845,  948,  184,  934,  441,  239,
         460,  683,   77,  918,  853,   96,  457,  503,  789,  495,  935,
          85,  444,  183,   41,  564,   49,  675,  219,   82,  718,  257,
         719,   56,  865,  362,  639,  479,  653,  611,  890,  543,   44,
         363,  190,  406,  276,  924,  658,  883,  753,  881,   17,  382,
         621,  358,  864,  687,  553,  705,  230,  755,  695,  605,  638,
         736,  560,  581,  355,  263,  241,  129,  964,  135,  579,  220,
         130,  465,  249, 1000,  983,  464, 1000,  494,  222,  709,  632,
         106,  664,  485,  338,  337, 1000,  609,  291,  126,  268,  454,
         633,  435,  959,  679,   42,  420,  914,  520,   51,  825,   93,
         155,  513,  425,  449,  374,  916,  348,  915,  991,  993,  447,
         429,  960,  254,  290,  656,  278,   80,  606,  612,  985,  394,
        1000,  152,  388,  710,  323,  186,  954,  895,   69,  628,  704,
         253,  139,  297,  288,  240,  650,  729,   38,  927,  324,  216,
          75,   67,   22,  862,  138,  207,  175,  228,  802,  630,   99,
         836,  666,  235,  169,  371,  616,  726, 1000,  686,  101,    6,
         527,  486,  762,  618,  370,  456,  995,  523,  211, 1000,  655,
         943,  731,  669,  852,  287,  886,  202,  600,  161,  818,  896,
         267,  331,  215,  521,  530,  116,   11,   87,  115,  677,  809,
         582,  354,  838,  298,  573,  360,  854,  357,  714,  978,   35,
         917,   15,   29,  400,  593,  909, 1000,  415,  841,   45,  955,
         733,  132,  340,  376,  540,  783,  136, 1000,  433,  414,  404,
         587,  877,  332,  443,  191,  938,  941,  706,  998,  662,    5,
         353,  171,  450,  697,  981,  946,  418,  451,  499,  472,  123,
         483,  208,  467,  996,  286,  308,  999,  302,  537,  205,  153,
         979,  119,  925,  684,  232,  305,  758,  306,  468,  989,  193,
         608,  108,  702,  778,  936,  448,  807,  502,  804, 1000,  727,
         284,  892,  846,  192,  748,   13,  364,  636,  589,  453,  926,
         851,  231,   36,  112,  134,  784,   54,  680,  791,  566, 1000,
         204,  977,  426,  562,  390,  399,  912,  897,  236,   43,  668,
         224,  312,  313,  939,  405,  820,  607,  734,  160,  957,  578,
         577,  336,  258,  289,  293,  950,  888, 1000,  614, 1000,  819,
          10,  512,  244,  484,  717,  750,  473,   63,  761,  518, 1000,
         535,   91,  740,  676,  187,  102, 1000,  887,  419,  902,    0,
         201,  480,  321,  969,  262,  385,  958, 1000,  533,  140,  277,
         270,  162,  976,  524,  849,  265,  237,  489,  229,  780,  501,
         799,  446,  259,  624,  416,  984,  659,  571,  900,  307,  844,
         461,  146,  569,  898,  377,  592,  199,  574,  768,  250,  470,
         972,  640,  681,  549,   79,  596,  556,  765,  814,  554,  120,
         942,  334,  767, 1000,  754,  430,  952,  396,  739, 1000,  109,
         843,  970,  563,   28,  319,  487,  920,  508,  567,  613,  585,
         947,  180,  365,   62,  428,  514,  103,  652,  795,  953,  238,
         167,   94,  154,   37,  325,  218,  869,  994,   70,  703,  901,
         559,  350,  275,  402,  629, 1000,    8,  127,  345,  700,  330,
         568,  166,  522,  498,  329,  974,  786,  565,  965,  481,  198,
          88,  997,  860,  531,  111,  411,  117,  264,  570,  889,  367,
         260,  831,  805,  928,   57,  872,  558,  963,  919,  992,  893,
         975,  817,  341,  586,  194,  732,  163,  177, 1000,  990,  859,
         905,  203,  623,  937, 1000,  757,  234,  294,  174,  349,  601,
          19,  856,  667,  643,  541,   23, 1000, 1000,  835,  798,  619,
        1000,    7,  226,  107,  827, 1000,  455,   50,  923,  673,  903,
         929,  344,  507,   90,  303,   21,  493,  801,  478,  534,  439,
         968,  279,  213,  779,  637,  781,    2,  548,   53,   60,  882,
         823,  547,  816,  921,   83,  693,  665,  745,   26,   61,  269,
         462,  300,  386,  151,  221,   48,  528,  708,  515,  776,  432,
         506,  672,  906,  737,  627,  647,  648, 1000,  182,  389,  125,
          20,   98,  295,  133,  398,   74,  256,  770,  511,  788,  696,
         143,  803,   33,  373,  794,   97,  885,  422,  857,   76]),
 array([ 736,  363,  941,  303,   12,  615,  538,  914,  842, 1000,  715,
         567,  179,  665,  158,  584,  211,  416,  224,  902,  979,  929,
         519,  907,  169,  292,  954,   76,  806,  585,  159,   79,  272,
         992,  108,  582,  673,  828,  513,   19,  343,  388,  466,  691,
         406,  592,  256,   36,  962,  390,  920,  470,  255,  943,  677,
         229,  397,  873,  259,    0,  944,  955,  817,  722,  302,   74,
         100,  518,  285,  503,  833,  356,  206,   62,  984,  517,  999,
         376,   10,  785,  490,  366,  393,  950,    7,  385,   72,  568,
         858,  323,  927,  727,  205,  472,  826, 1000,  379,  995,  980,
         527,  162,  537,  731,  820,   34,  214,  451,  916,  650,  802,
         232,  862,  674,  120,  296,  569,  566,  864,  184,  639,  791,
         181,  209,  626,  300,  978,  459,  843,   14,  435,  440,  212,
         595,  982,  675,  437,  600,  197,  521,  507,  746,   80, 1000,
         990,   56,   78,  771,   69,  180,  150, 1000,  960,  496,  637,
         827,  473,  126, 1000,  152,  341,  701,  558,  749,  886,   40,
         281,  848,  825, 1000,  531,   98,  617,  355,  294,  899,  523,
          29,  887,   20,  153,  815,  140,  976,  387,  370,  365,  500,
         730,   68,  291,  408,  609,  663,  648,  884,  262,  264,  167,
         857,  776,  306,  737,  556,  892,  682,  636, 1000,  522,  628,
         195,  241,  547,   82,  937,   42,  563,  516,  193,  830,  392,
         439,  961,  448,  346,  693,  149,  915, 1000,  524,  756,  424,
         672,  642,  270,  897,  530,  690,  754,  824,  373,  510,  434,
         310,   37,  717,   81,  305,  331,  245,  442,  779,  293,  287,
         506,  486,  234,  985,  395,  706,  761,  869,  271,  741,  433,
         865,  753,   59,  561,  460,  956,  748,  340, 1000,  213,  231,
         838,  410,  747,  489,  936,  112, 1000, 1000, 1000,  660,  203,
         631,  554,  509,  707,  487,  458,  311,  708,  898,  981,  273,
         508,  575,  137,  958,  190,  634,  928,  210,  643,  645,  768,
         632,  359,  208,  171,  694,  695, 1000,  242,  154,    9,  308,
         807,   92,  739,  235,  499,  515,  829,  164,  253,  325,  851,
         846,  562,  607,   55,  793,  348,  705,  455,  454,  307,  596,
         882,   15, 1000,  925,  844,  192,  353,  479,  900,  837,  119,
         131,  616,  573,  432,  177,  579,  419,  251,  577,  304,  399,
         407,  666,  816,  278,  868,  105,   16,  543,  532,  284,  993,
         477,  282,  597,  774,   21,  110,   25,   30,  417,   94,   32,
         742,  959,   95,  497,  977,  686,  298,  134,  156,  494, 1000,
         799,  290,  983,  687,  586,  141,  839,  227,  604,  697,  409,
        1000,  170,   66,  362,  863,  189,  115,  603,  590,  763,   43,
         622,  734,  467,    6,  997,  230,  324,  475,  684,  220,  818,
         484,  797,  106,  967,  602,  175,  463,  339,  357,  265,  934,
         263,  372,  268,  608,  386,  295,  760,  483,  654,  476,  618,
         623, 1000,  669,  461,  919,  544,  380,  109,  139,  374,  770,
         957,   93,  445,  441,  161,  629,  646,  283,  780,  143,  625,
         721,   97,  113,   11,  315,  932,  401,  738,  856,  266,  627,
         718,  453,  540,  808,  244,  755,  202,  114,  274,  930,  447,
         383,  316,  121,  850,  624, 1000,  758,  656,  381,  269,  297,
         968,  926,  810,  107,   84,  987,  716,  474,  819,  965,   58,
         243,  724,    8,  469,  564,  849,  546,  751, 1000,   65,  539,
         963,   13,  565,  861,  238,  745,  933,  726,  157,  635,  249,
         116,  598,  906,  330,  405,  367,  188,  321,  947,  942,  784,
         260,   91,  248,  422,  790,  216,  787,   53,  875,  836,  430,
         267,  685,  805,  389,  854,  680,  811,  847,  772,  866,  766,
          87,  576,  777,  222,   27,  704,  703,  438,  151,  431,  572,
         102,  122,  813,  883,  605,  194,  668,  335,   71,  775,  587,
        1000,   45,  786,  332,  288, 1000,  557,  901,  347,  276,  218,
         427,  491,  699,  649,  457,  172,  403,  492,  812,  712,   70,
         533,   50,  542,  912,   22,  418,    1,  893,  762, 1000,   60,
         972,  504,  840,  526,   52,  450,  462,  228,  178,  667,  939,
         428,  400,  782,   61,  299,  905,  239,  201,   83,  973,  974,
         328,  511,  309,  821,  402,   23,  549,  488,  127,  412,  765,
          96,  123,  614, 1000,  452,  952,  529,  904,  692,  552,   35,
           3,  969,  922,  313,  391,  729,  570,  225,  465,  678,  783,
         125,  375,  641,   73,  536,  421,  351,  142,  319,  223, 1000,
         951,  101,  426,  989,  619, 1000,  144,  845,  160,  651,  834,
         505,  423,  612,  246,  964,  449,  498,  165,  318,  279,  580,
         361,  133,  719,  394,  396,  254,  174,  191,   64,   75,  333,
         534,  659,  186,  512,  336,  551,  885,  594,  700,  326,  429,
         971,  196,  800,  728, 1000,  183,  233,  257,  953,  360,  148,
         664,  286,  720,  329,  138,  414,  796,  425,  145,  896,  644,
         342,  173,  723,  541,   99,   26,  788,   39,  794,  778,  221,
         986,  261,  182,  358,  118,  312,  966,   89,  652,  938,  757,
         940,  187,  599,  676, 1000,  853,  163,  988,  382, 1000,  679,
         349,  124,  994,  822, 1000,  215,  911,  759, 1000,  931,  525,
         991,  657,  871,  217,  655,  258,  571,  334,  200,   28,  301,
         789, 1000,  948,  881,  559,  714,  698,  135, 1000,  946,   57,
         471,  352,  917,   31,  104,   63,  870,  226,   90,   48,  910,
         528,  247,  574,   47,   41,  591,  314,  803,  769,  368,  662,
         103,  129,  752,   46,  671,  553,  378,  578,  364,  903,  998,
         199,  890,  860,   54,  520,  146,  420,  398,  280,  176,    2,
         831,  350,   17,  874,   49,  136,  204, 1000,  606,  128,  322,
           4,  415,  945,  413,  240,  996,  555,  733,  710,  867,  404,
         132,  661,  879,  166,  502,  560,  689,  773,   88,  767,  835,
         735,  923,  207,  891,  970,   38, 1000,  588,  345,  252,  688,
          77,  468,  480,  478,  583,  377,  877,  809,  949,  185,  921,
         411,  640,  670,  514,  872,  924,  147,   67,  237,   33,  371,
         384,  653,  894,  610,  696,  344,  611,  792,  550,   86,  354,
         621,  814,  369,  289,  709, 1000,  798,  823,  501,  593,   85,
         702,  743,  464,  485,   51,  111,  876,  436,  855,  320,  198,
         935,  740,  804,   44,  781,  337,  852,  880,  750,  683,  581,
         638,   24,  620,  219,  444,  764,  493,  155, 1000,  338,  647,
         889,  481,  878,  482,  832,  545,  630,  859,  613,  633])]

In [21]:
#とりあえず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:
                                    continue
                                    
                                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 [22]:
caps = [4,3,5]
deferred_acceptance(m_prefs,f_prefs,caps)


0.000154972076416
Out[22]:
[[2, 0, 2, 0, 3, 0, 3, 2, 3, 2, 2, 2, 2, 3, 0],
 [1, 1, 5, 14, 15, 15, 15, 12, 15, 15, 15, 15],
 [0, 4, 7, 12]]

In [3]:
#テストが通らないので直す
#直せない
import numpy as np

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
                        
                
                        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)
                                    #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]]
                            
                            if rank_already > rank_apply:
                                prefered_accept.insert(i,applyman)
                                #print prefered_accept
                                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
                                break
                    break
                            
    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 [4]:
s_unmatched=5
s_prefs =np.array( [[2, 0, 4, 3, s_unmatched, 1],
                        [0, 2, 3, 1, 4, s_unmatched],
                        [3, 4, 2, 0, 1, s_unmatched],
                        [2, 3, 0, 4, s_unmatched, 1],
                        [0, 3, 1, s_unmatched, 2, 4],
                        [3, 2, 1, 0, 4, s_unmatched],
                        [1, 4, 0, 2, s_unmatched, 3],
                        [0, 2, 1, 4, 3, s_unmatched],
                        [3, 0, 4, s_unmatched, 1, 2],
                        [2, 0, 4, 1, 3, s_unmatched],
                        [4, 3, 0, 2, 1, s_unmatched]])

In [5]:
c_unmatched = 11
c_prefs = [[2, 6, 8, 10, 4, 3, 9, 7, 5, 0, 1, c_unmatched],
                        [4, 6, 9, 5, 7, 1, 2, 10, c_unmatched, 0, 3, 8],
                        [10, 5, 7, 2, 1, 3, 6, 0, 9, c_unmatched, 4, 8],
                        [9, 0, 1, 10, 3, 8, 4, 2, 5, 7, c_unmatched, 6],
                        [1, 3, 9, 6, 5, 0, 7, 2, 10, 8, c_unmatched, 4]]

In [11]:
c=np.array(c_prefs)

In [13]:
d=c.argsort()
d


Out[13]:
array([[ 9, 10,  0,  5,  4,  8,  1,  7,  2,  6,  3, 11],
       [ 9,  5,  6, 10,  0,  3,  1,  4, 11,  2,  7,  8],
       [ 7,  4,  3,  5, 10,  1,  6,  2, 11,  8,  0,  9],
       [ 1,  2,  7,  4,  6,  8, 11,  9,  5,  0,  3, 10],
       [ 5,  0,  7,  1, 11,  4,  3,  6,  9,  2,  8, 10]])

In [6]:
caps = [4, 1, 3, 2, 1]
deferred_acceptance(s_prefs,c_prefs,caps)


Out[6]:
[[2, 5, 5, 2, 0, 5, 1, 0, 3, 2, 4],
 [4, 7, 11, 11, 6, 3, 0, 9, 8, 11, 10],
 [0, 4, 5, 8, 10, 11]]

In [90]:
a=[0,1,2]
a


Out[90]:
[0, 1, 2]

In [97]:
b=a.reverse()
print b


None

In [85]:
#修正する
#とりあえずok
def da_00(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 [86]:
caps = [4, 1, 3, 2, 1]
da_00(s_prefs,c_prefs,caps)


10
[4 3 0 2 1 5]
4
[ 5  0  7  1 11  4  3  6  9  2  8 10]
[]
[10]
[5 5 5 5 5 5 5 5 5 5 4]
9
[2 0 4 1 3 5]
2
[ 7  4  3  5 10  1  6  2 11  8  0  9]
[]
[9]
[5 5 5 5 5 5 5 5 5 2 4]
8
[3 0 4 5 1 2]
3
[ 1  2  7  4  6  8 11  9  5  0  3 10]
[]
[8]
[5 5 5 5 5 5 5 5 3 2 4]
7
[0 2 1 4 3 5]
0
[ 9 10  0  5  4  8  1  7  2  6  3 11]
[]
[7]
[5 5 5 5 5 5 5 0 3 2 4]
6
[1 4 0 2 5 3]
1
[ 9  5  6 10  0  3  1  4 11  2  7  8]
[]
[6]
[5 5 5 5 5 5 1 0 3 2 4]
5
[3 2 1 0 4 5]
3
[ 1  2  7  4  6  8 11  9  5  0  3 10]
[8]
[5 5 5 5 5 3 1 0 3 2 4]
[8, 5]
4
[0 3 1 5 2 4]
0
[ 9 10  0  5  4  8  1  7  2  6  3 11]
[7]
[5 5 5 5 0 3 1 0 3 2 4]
[4, 7]
3
[2 3 0 4 5 1]
2
[ 7  4  3  5 10  1  6  2 11  8  0  9]
[9]
[5 5 5 2 0 3 1 0 3 2 4]
[3, 9]
2
[3 4 2 0 1 5]
3
[ 1  2  7  4  6  8 11  9  5  0  3 10]
[8, 5]
5
[5 5 3 2 0 5 1 0 3 2 4]
[0, 1, 5]
[8, 2]
5
[3 2 1 0 4 5]
3
[ 1  2  7  4  6  8 11  9  5  0  3 10]
[8, 2]
2
[ 7  4  3  5 10  1  6  2 11  8  0  9]
[3, 9]
[5 5 3 2 0 2 1 0 3 2 4]
[5, 3, 9]
1
[0 2 3 1 4 5]
0
[ 9 10  0  5  4  8  1  7  2  6  3 11]
[4, 7]
[5 0 3 2 0 2 1 0 3 2 4]
[5 0 3 2 0 2 1 0 3 2 4]
[4, 7, 1]
0
[2 0 4 3 5 1]
2
[ 7  4  3  5 10  1  6  2 11  8  0  9]
[5, 3, 9]
9
[2 0 3 2 0 2 1 0 3 5 4]
[9]
[5, 3, 0]
9
[2 0 4 1 3 5]
2
[ 7  4  3  5 10  1  6  2 11  8  0  9]
[5, 3, 0]
0
[ 9 10  0  5  4  8  1  7  2  6  3 11]
[4, 7, 1]
[2 0 3 2 0 2 1 0 3 0 4]
[2 0 3 2 0 2 1 0 3 0 4]
[4, 9, 7, 1]
Out[86]:
[[2, 0, 3, 2, 0, 2, 1, 0, 3, 0, 4],
 [4, 9, 7, 1, 6, 5, 3, 0, 8, 2, 10],
 [0, 4, 5, 8, 10, 11]]

In [91]:
#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 [90]:
#caps==NOneに対応・・・できない
def deferred_acceptance(m_pref_input,f_pref_input,caps)
    if caps==None:
        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))

        m_match=np.tile([-1],m_popu)
        f_match=np.tile([-1],f_popu)

        while len(free) > 0:
            applyman = free.pop()
            print applyman
            apply_prefs=m_pref_array[applyman]

            for prefered in apply_prefs:

                print prefered
                print m_match
                print f_match

                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 i in range(f_popu):
            if f_match[i] == -1:
                f_match[i]=m_popu
        return [m_match,f_match]
            
    else:
        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]


  File "<ipython-input-90-dfa978139e4b>", line 2
    def deferred_acceptance(m_pref_input,f_pref_input,caps)
                                                           ^
SyntaxError: invalid syntax

In [13]:
#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 [29]:
m_prefs, f_prefs = random_prefs(40, 5)

In [30]:
caps = [8,8,8,8,8]
deferred_acceptance(m_prefs,f_prefs,caps)


0.000578165054321
Out[30]:
[[2,
  5,
  3,
  5,
  0,
  5,
  5,
  4,
  5,
  3,
  5,
  2,
  5,
  2,
  3,
  4,
  5,
  0,
  4,
  2,
  3,
  4,
  0,
  0,
  2,
  0,
  5,
  3,
  5,
  3,
  3,
  0,
  2,
  5,
  0,
  5,
  0,
  5,
  2,
  2],
 [34,
  25,
  4,
  31,
  23,
  22,
  17,
  36,
  40,
  40,
  40,
  40,
  40,
  40,
  40,
  40,
  24,
  38,
  19,
  11,
  13,
  39,
  32,
  0,
  27,
  30,
  14,
  2,
  9,
  20,
  29,
  40,
  18,
  7,
  21,
  15,
  40,
  40,
  40,
  40],
 [0, 8, 16, 24, 32, 40]]

In [60]:
#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 [61]:
m_prefs, f_prefs = random_prefs(40, 5)

In [73]:
#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)


Out[73]:
14.69

In [10]:
#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]

In [7]:
m_prefs, f_prefs = random_prefs(15, 3)

In [9]:
caps=[2,3,8]
deferred_acceptance(m_prefs,f_prefs,caps)


0.000240802764893
Out[9]:
[[0, 1, 3, 3, 2, 1, 3, 2, 3, 3, 3, 3, 0, 1, 2],
 [0, 12, 13, 5, 1, 7, 4, 14, 15, 15, 15, 15, 15],
 [0, 2, 5, 13]]

In [ ]: