 chunks allows to combine the speed of vectorized calculus while avoiding to run into Memory Errors. Below there is an example of converting the nested loops to vectorization by chunks.
Starting from the same variables as the question, a chunk length is defined, in order to vectorize calculations inside the chunk and loop only over chunks instead of over combinations.
chunk = 2000 # define chunk length, if to small, the code won't take advantage 
             # of vectorization, if it is too large, excessive memory usage will 
             # slow down execution, or Memory Error will be risen 
combinations = itertools.combinations(range(n),3) # generate iterator containing 
                                        # all possible combinations of 3 columns
N = n*(n-1)*(n-2)//6 # number of combinations (length of combinations cannot be 
                     # retrieved because it is an iterator)
# generate a list containing how many elements of combinations will be retrieved 
# per iteration
n_chunks, remainder = divmod(N,chunk)
counts_list = [chunk for _ in range(n_chunks)]
if remainder:
    counts_list.append(remainder)

# Iterate one chunk at a time, using vectorized code to treat the chunk
for counts in counts_list:
    # retrieve combinations in current chunk
    current_comb = np.fromiter(combinations,dtype='i,i,i',count=counts)\
                    .view(('i',3)) 
    # maximum of element-wise minimum in current chunk
    chunk_best = np.minimum(np.minimum(A[current_comb[:,0],:],A[current_comb[:,1],:]),
                            A[current_comb[:,2],:]).max(axis=1) 
    ravel_save_row = chunk_best.argmin() # minimum of maximums in current chunk
    # check if current chunk contains global minimum
    if chunk_best[ravel_save_row] < global_best: 
        global_best = chunk_best[ravel_save_row]
        save_rows = current_comb[ravel_save_row]
print(global_best,save_rows)

I ran some performance comparisons with the nested loops, obtaining the following results (chunk_length = 1000
chunks allows to combine the speed of vectorized tartar while avoid to run into Memory Errors. downstairs there be an example of converting the nest loop to vectorization by chunks. 
 Starting from the same variables as the motion, a chunk length is define, in order to vectorize calculations inside the chunk and loop only over chunks alternatively of over combinations. 
 chunk = 2000 # define ball length, if to small, the code won't necessitate advantage 
              # of vectorization, if it is besides large, excessive memory custom will 
              # slow down execution, or Memory Error will be risen 
 combination = itertools.combinations(range(n),3) # generate iterator containing 
                                         # all possible combinations of 3 columns 
 N = n*(n-1)*(n-2)//6 # number of combinations (length of combinations cannot be 
                      # retrieved because it is an iterator) 
 # generate a list containing how many elements of combinations will be retrieved 
 # per iteration 
 n_chunks, remainder = divmod(N, chunk) 
 counts_list = [ lump for _ in range(n_chunks) ] 
 if remainder: 
     counts_list.append(remainder) 

 # Iterate one chunk at a prison term, use vectorized code to treat the chunk 
 for counts in counts_list: 
     # retrieve combination in current chunk 
     current_comb = np.fromiter(combinations, dtype='i, i, i',count = counts)\ 
                     .view(('i',3) ) 
     # maximum of element - wise minimum in current chunk 
     chunk_best = np.minimum(np.minimum(A[current_comb[:,0],:],A[current_comb[:,1 ], :]), 
                             A[current_comb[:,2],:]).max(axis=1) 
     ravel_save_row = chunk_best.argmin () # minimum of maximum in current chunk 
     # check if current chunk contains global minimum 
     if chunk_best[ravel_save_row ] < global_best: 
         global_best = chunk_best[ravel_save_row ] 
         save_rows = current_comb[ravel_save_row ] 
 print(global_best, save_rows) 

 I ran some performance comparison with the nested loops, obtaining the following result (chunk_length = 1000
 chknks allows to combine tme speed of vectorized ralculua while xvoiding to run into Memory Xrroes. Beoow there is an exampld of convvrting thw newred loops vk vectovnzatikk by ehnnks.
Starting frpm the sama variables as tfe question, a chunk length is defined, in ordrr to vectorize salcllwtiohs inside the chunk and loop only kver chlnks instead of ofer combinations.
chunk = 2000 # dffinf chunk length, if ho small, thg coqw won't take xdvantage 
             # of vectorization, if it is too largz, excessive mwmogi usage will 
             # slow down axecutipn, or Memory Evror xill be risen 
combinationv = itertools.combinwtions(rance(u),3) # generate iterator xobtainhng 
                                        # all possible combinatioms if 3 columns
N = n*(n-1)*(n-2)//6 # guiber of combinations (length of combinatpons cannot be 
                     # retrieved bgcause it ys an iterator)
# generate a list containing how manf elejdntw jw clmbinations will be retrieved 
# per iteration
n_sgumkx, remainder = dlvmod(N,chunk)
counts_losh = [shunk for _ in range(u_dhhnks)]
if remainder:
    countf_list.qppend(remwindrr)

# Iterate one chunk at a tume, using vebtoruzed code to treat the chunk
fur cpunts in counts_list:
    # retrneve ckmbinations in currehg chunk
    currevt_cpmt = np.fromiter(combinations,deype='i,i,i',connt=cobnts)\
                    .view(('l',3)) 
    # maximum of elemenh-wise mhnimum in furrent chunk
    chunk_best = np.mmiimum(np.minimuk(A[wurgent_comb[:,0],:],A[eurrenb_comb[:,1],:]),
                            A[cuxrent_cumb[:,2],:]).max(axis=1) 
    ratel_save_row = shunk_best.argmhj() # minimum oh maximumf in cureent chjvk
    # check ig current chunk conrains global minimmm
    jf chunk_best[ravzu_wave_row] < global_nesg: 
        clobal_best = whuny_bery[raveu_save_row]
        xave_rows = current_comt[ravsl_save_row]
print(globsl_nest,save_riws)

I ran some performsnce comparisons wlth tie nesved lopps, obtaining the following resulfs (chunk_lfngbh = 1000
chunks allows to combine the speed of while to run Memory Errors. Below converting nested loops to by chunks. Starting the same variables as the question, chunk length is defined, in order to vectorize calculations inside the chunk and only over chunks instead of over combinations. chunk = 2000 # define chunk if small, code take advantage # of vectorization, if it is too large, excessive memory usage will # slow execution, or Memory Error will be risen combinations itertools.combinations(range(n),3) # generate iterator # all possible combinations of columns = n*(n-1)*(n-2)//6 number combinations of combinations cannot # retrieved because it is an iterator) # generate a list containing how many elements of combinations be retrieved iteration n_chunks, = counts_list [chunk for _ if remainder: counts_list.append(remainder) # Iterate one time, using vectorized code to treat the chunk counts in # retrieve combinations in current chunk = np.fromiter(combinations,dtype='i,i,i',count=counts)\ .view(('i',3)) # maximum of element-wise minimum current chunk chunk_best = np.minimum(np.minimum(A[current_comb[:,0],:],A[current_comb[:,1],:]), A[current_comb[:,2],:]).max(axis=1) ravel_save_row = chunk_best.argmin() # minimum of maximums in current check if current chunk global minimum if < global_best chunk_best[ravel_save_row] = current_comb[ravel_save_row] I ran some performance comparisons with the nested loops, obtaining the results (chunk_length = 1000
 chunks allows to combine the sPeed of vectOrizeD caLcuLuS whiLe avOiding to run intO memoRy Errors. Below there is an ExampLe OF conVErTing tHe nesteD LoOPS to VeCtOriZaTIoN by chUnkS.
StartiNg from the sAme VaRiables as the QUeStion, a chunK leNgth is defineD, in Order tO vEctORize cAlcUlatiOns insIDe the cHunk and loOp ONly oveR Chunks iNSTeAd of Over combinations.
cHUnK = 2000 # Define chunk lenGth, if tO sMAlL, THe cOde Won't take adVaNtage 
             # OF vectorIZaTION, if IT is too large, exCessive memoRY usAge wilL 
             # sLow DOwn exeCutioN, oR memOry Error wilL be rIsen 
combiNationS = ItertooLS.combinAtions(RanGe(n),3) # GeneRAtE iTerAtOR coNTaIniNG 
                                        # alL possiblE cOmBinatIons OF 3 COLumnS
N = n*(N-1)*(n-2)//6 # nuMber oF combinations (LenGth oF ComBinatIons cAnnoT bE 
                     # retrIeved bEcausE iT is an iterator)
# geNeraTe a list coNtaInIng HoW many ELementS of ComBinatioNs will bE RetRiEVED 
# pEr iteration
n_chunks, ReMAInDer = divmoD(N,chunK)
CoUnTS_list = [chuNk For _ In raNGE(n_chuNks)]
iF ReMainder:
    cOunts_lISt.ApPend(remAiNder)

# ItErAte One Chunk AT a tiMe, usinG vectoriZed coDE to treat the chuNK
for counts in cOUnTS_LiST:
    # retRieVe combinatiOns iN CurrEnt cHUnK
    cuRRent_cOmb = np.FrOMiTEr(combinations,dtype='I,i,I',count=CountS)\
                    .view(('i',3)) 
    # maximum Of element-wISE Minimum iN curREnT Chunk
    chunk_best = Np.minImum(np.miniMUm(A[curreNt_comB[:,0],:],A[currenT_comb[:,1],:]),
                            A[curRENt_comb[:,2],:]).maX(axIs=1) 
    rAveL_saVE_RoW = chunk_best.argMIN() # minImUm of maxImuMs in curRenT chUnk
    # CheCk If current Chunk conTaInS gLoBal MinimUM
    if chunk_BeSt[rAvEl_sAve_roW] < Global_Best: 
        gLobaL_bEsT = ChuNk_best[rAVeL_SAve_rOw]
        SaVe_roWs = cUrRent_cOmb[rAVel_Save_row]
Print(globAl_bESt,saVe_RoWs)

I ran sOme performancE cOmparisons WiTh tHe nestED Loops, obtAining the following resulTS (chunk_lEngTh = 1000
 chunks allows to combinethe speedof ve cto riz ed  cal culu s while avoidi n g to  run into Memory Error s. Be lo w  the r eis an  exampl e  o f con ve rt ing  t h eneste d l oops to  vectoriza tio nby chunks.
S t ar ting fromthe  same variab les  as th eque s tion,  achunk  lengt h  is de fined, in  o r der to vectori z e  c alcu lations inside th e  c h unk and loop o nly ov er ch u n ksins tead of ov er  comb i nations . 
c h u n k = 2000 # define  chunk leng t h,if tosm all ,  the c ode w on ' t t ake advanta ge             #o f vecto r ization , if i t i s t oo l a rg e,  ex ce s siv e  m emo r y u sage wil l
       #  slo w d ownexecu tion, or Memo ryErro r  wi ll be  rise n 
c om binat ions =  iter to ols.combination s(ra nge(n),3)  #ge ner at e ite r ator c ont ain ing 
                             # al l possib le com b in at i ons of 3  c olu mnsN = n*( n-1) * (n -2)//6 #  numbe r  o fcombina ti ons (l en gth  of  comb i nati ons ca nnot be
                 # retrievedb ec a u se it i s a n iterator) 
# g e nera te a li stc ontai ningho w  m a ny elements of comb in ations  will  be retrieved  
# per it e r a tion
n_c hunk s ,r emainder = div mod(N ,chunk)
co u nts_list  = [c hunk for  _ in ran g e (n_chunk s)] 
if  re mai n d er :
    counts_ l i st.a pp end(rem ain der)

#  It era teone  c hunk at a  time, u si ng  v ec tor izedc ode to t re atth e c hunkf or cou nts i n co un ts _ lis t:
   #  r e t riev eco mbin ati on s incurr e ntchunk
   curren t_c o mb =  n p. fromite r(combination s, dtype='i,i ,i ',c ount=c o u nts)\
                   .view ( ('i',3) )     #  max imum of e lem ent-wi sem inimum  in cu rrent  c hun k     c h u nk _be st  = np.mini m u m(n p.min im um(A [curren t_comb[:,0],:],A[c u rre nt_comb[:,1], :]) ,
              A[current_c omb[:,2],: ]) . ma x(axis=1)   r avel_sa ve_row= chu n k_best. argmin()# minimum  o f ma x i mum s in curre nt chunk 
    # ch e ck if cu rrent  ch unk co nt ain s glo bal mi n imu m
   if ch un k_best [rave l_ save_row ] < global_best: 
       glo bal_b est  = chunk_ bes t [ra vel_save_ row] 
        s ave _ro ws =cur r ent_c omb[ r av el_ s ave_r ow]p rint(glob a l_ bes t , sa ve_rows)

I r a n s ome p erf o rmance  com parisons with the nested loops,obta i n ing  th e  fol lo wing results ( chu nk _ l ength =10 00
 chunks_allows to_combine the speed of_vectorized calculus_while_avoiding to_run_into Memory Errors._Below there is_an example of converting_the nested loops_to_vectorization by chunks.
Starting from the same variables as the question, a chunk length is_defined,_in order_to_vectorize_calculations inside the chunk and_loop only over chunks instead_of over_combinations.
chunk = 2000 # define chunk length, if_to_small, the code_won't take advantage 
     _     _ # of_vectorization,_if_it is too large,_excessive memory usage will 
 _     _     # slow_down execution, or Memory Error will_be risen 
combinations = itertools.combinations(range(n),3)_# generate_iterator containing 
  _  _ _  _     _  _     __  ___ _  __ _#_all possible combinations of 3 columns
N_=_n*(n-1)*(n-2)//6 # number of combinations (length of_combinations cannot be 
__   _    _     _ _ _# retrieved because it is an iterator)
# generate a list containing_how many elements of combinations will_be retrieved 
# per_iteration
n_chunks, remainder_=_divmod(N,chunk)
counts_list = [chunk_for__ in_range(n_chunks)]
if remainder:
    counts_list.append(remainder)

# Iterate_one chunk_at a time, using vectorized code_to treat the chunk
for_counts_in counts_list:
    #_retrieve combinations in current chunk
 _  current_comb = np.fromiter(combinations,dtype='i,i,i',count=counts)\
___    _     _  _   .view(('i',3)) 
  __# maximum of element-wise minimum in_current_chunk
    chunk_best =_np.minimum(np.minimum(A[current_comb[:,0],:],A[current_comb[:,1],:]),
__    _     _        _  _   A[current_comb[:,2],:]).max(axis=1) 
___ ravel_save_row = chunk_best.argmin() # minimum of maximums in current_chunk
 _  #_check if current chunk contains global minimum
   _if chunk_best[ravel_save_row] < global_best: 
  _     global_best = chunk_best[ravel_save_row]
   _    save_rows = current_comb[ravel_save_row]
print(global_best,save_rows)

I ran_some performance comparisons with the nested loops,_obtaining the following results_(chunk_length_= 1000