/*! Find a zero (Z) in the resulting matrix. If there is no starred zero in its row or column, star Z. Repeat for each element in the matrix. Go to STEP3. */ nextstep Step2(const gsl_matrix * const M, gsl_matrix_uint * const mask, gsl_vector_uint * const rowCov, gsl_vector_uint * const colCov) { unsigned int i, j; for(i = 0; i < M->size1; i++) { for(j = 0; j < M->size2; j++) { if(gsl_vector_uint_get(rowCov, i) == COVERED) break; if(gsl_vector_uint_get(colCov, j) == UNCOVERED && gsl_matrix_get(M, i, j) == (float) 0 ) { gsl_matrix_uint_set(mask, i, j, STAR); #ifdef VERBOSE fprintf(stderr, "Covering col %d\n", j); #endif gsl_vector_uint_set(colCov, j, COVERED); #ifdef VERBOSE fprintf(stderr, "Covering row %d\n", i); #endif gsl_vector_uint_set(rowCov, i, COVERED); } } } gsl_vector_uint_set_all(rowCov, UNCOVERED); gsl_vector_uint_set_all(colCov, UNCOVERED); return STEP3; }
nextstep Step5(gsl_matrix_uint * const mask, gsl_matrix_int * const path, gsl_vector_uint * const rowCov, gsl_vector_uint * const colCov, unsigned int z0_r, unsigned int z0_c) { unsigned int count = 0; int row, col; gsl_matrix_int_set_all(path, -1); // Begin with 0' from Step 4 gsl_matrix_int_set(path, count, 0, z0_r); gsl_matrix_int_set(path, count, 1, z0_c); while(count < (path->size1-1)) { // Find 0* in col FindStarInCol(mask, &row, gsl_matrix_int_get(path, count, 1)); if(row == -1) break; count++; gsl_matrix_int_set(path, count, 0, row); gsl_matrix_int_set(path, count, 1, gsl_matrix_int_get(path, count-1, 1)); if(count < (path->size1-1)) { // Find 0' in row FindPrimeInRow(mask, gsl_matrix_int_get(path, count, 0), &col); count++; gsl_matrix_int_set(path, count, 0, gsl_matrix_int_get(path, count-1, 0)); gsl_matrix_int_set(path, count, 1, col); } } count++; ConvertPath(path, count, mask); gsl_vector_uint_set_all(rowCov, UNCOVERED); gsl_vector_uint_set_all(colCov, UNCOVERED); ErasePrimes(mask); return STEP3; }
/*! Computes assignment matrix for M. */ int Hungarian(const gsl_matrix * const M, const bool convToMinAsg, gsl_matrix * const Assignment) { int res, z0_r, z0_c; bool done = false; unsigned int next = STEP1; gsl_vector_uint *rowCov, *colCov; gsl_matrix_uint *mask; gsl_matrix_int *path; gsl_matrix *MCopy; MCopy = gsl_matrix_alloc(M->size1, M->size2); gsl_matrix_memcpy(MCopy, M); if(convToMinAsg == true) { res = ConvertToMinAsg(MCopy); if(res != GSL_SUCCESS) return res; } // Allocate memory rowCov = gsl_vector_uint_alloc(M->size1); colCov = gsl_vector_uint_alloc(M->size2); mask = gsl_matrix_uint_alloc(M->size1, M->size2); path = gsl_matrix_int_calloc(ceil(((float)(mask->size1*mask->size2))/2), 2 ); // Initialize gsl_vector_uint_set_all(rowCov, UNCOVERED); gsl_vector_uint_set_all(colCov, UNCOVERED); gsl_matrix_uint_set_all(mask, UNMASKED); while(done == false) { switch(next) { case STEP1: next = Step1(MCopy); #ifdef VERBOSE Matrix_print_with_mask(MCopy, mask, rowCov, colCov, "Post Step 1"); PrintCover( rowCov, colCov, "Post Step 1 Cover"); #endif break; case STEP2: next = Step2(MCopy, mask, rowCov, colCov); #ifdef VERBOSE Matrix_print_with_mask(MCopy, mask, rowCov, colCov, "Post Step 2"); PrintCover( rowCov, colCov, "Post Step 2 Cover"); #endif break; case STEP3: next = Step3(MCopy, mask, colCov); #ifdef VERBOSE Matrix_print_with_mask(MCopy, mask, rowCov, colCov, "Post Step 3"); PrintCover( rowCov, colCov, "Post Step 3 Cover"); #endif break; case STEP4: next = Step4(MCopy, mask, rowCov, colCov, &z0_r, &z0_c); #ifdef VERBOSE Matrix_print_with_mask(MCopy, mask, rowCov, colCov, "Post Step 4"); PrintCover( rowCov, colCov, "Post Step 4 Cover"); #endif break; case STEP5: next = Step5(mask, path, rowCov, colCov, z0_r, z0_c); #ifdef VERBOSE Matrix_print_with_mask(MCopy, mask, rowCov, colCov, "Post Step 5"); PrintCover( rowCov, colCov, "Post Step 5 Cover"); #endif break; case STEP6: next = Step6(MCopy, rowCov, colCov); #ifdef VERBOSE Matrix_print_with_mask(MCopy, mask, rowCov, colCov, "Post Step 6"); PrintCover( rowCov, colCov, "Post Step 6 Cover"); #endif break; case DONE: #ifdef VERBOSE Matrix_print_with_mask(MCopy, mask, rowCov, colCov, "DONE"); #endif UpdateAssignment(mask, Assignment); done = true; break; default: done = true; fprintf(stderr, "Error!\n"); } } // Release memory gsl_matrix_free(MCopy); gsl_vector_uint_free(rowCov); gsl_vector_uint_free(colCov); gsl_matrix_uint_free(mask); gsl_matrix_int_free(path); return GSL_SUCCESS; }
void MAIAllocator::Run() { // fetch channel matrix gsl_matrix_complex hmm = min1.GetDataObj(); // hmm : channel coeffs matrix h(n) (M**2xN) // ij // ch matrix structure // // +- -+ // | h(0) . . . . h(n) | | // | 11 11 | | // | | | Rx1 // | h(0) . . . . h(n) | | // | 12 12 | | // | | // | h(0) . . . . h(n) | | // | 21 21 | | // | | | Rx2 // | h(0) . . . . h(n) | | // | 22 22 | | // +- -+ // // where h(n) represents the channel impulse response // ij // // at time n, from tx_i to rx_j // the matrix has MxM rows and N comumns. // The (i,j) channel is locater at row i*M+j // with i,j in the range [0,M-1] and rows counting from 0 // // // fetch error report // e(u) = errors for user u in the last ERROR_REPORT_INTERVAL (ERI) frames gsl_vector_uint temperr = vin2.GetDataObj(); // update error reports at receiver rx_m every ERI if (ericount % ERROR_REPORT_INTERVAL == 0) { // once every ERU if (temperr.size == M()) { gsl_vector_uint_memcpy(errs,&temperr); } ericount = 0; } // // every DECISION_INTERVAL frames we updates the CSI knowledge // if (framecount % DECISION_INTERVAL == 0) { for (int u=0;u<M();u++) { // user loop // extract time domain response from hmm corresponding to txn-->rxn channel gsl_vector_complex_const_view hii = gsl_matrix_complex_const_row(&hmm,u*M()+u); // copy the N-sized vector hii into u-th column of huu gsl_matrix_complex_set_col(huu,u,&hii.vector); } // user loop //cout << "maiallocator:453 - CSI update received" << endl; // huu matrix structure // // +- -+ // | h(0) . . . . h(n) | // | 11 uu | // | | // | h(n) . . . . h(n) | // | 11 uu | // +- -+ // // where h(n) represents the channel impulse response // ii // // at time n, from tx_u to rx_u // the matrix has N rows and M columns. // // ATTENTION! user_0 channel response is the first column // // Hmat(NxM) = Fourier( huu(NxM) ) // gsl_blas_zgemm(CblasNoTrans, CblasNoTrans, gsl_complex_rect(1,0), transform_mat, huu, gsl_complex_rect(0,0), Hmat); #ifdef SHOW_MATRIX cout << "Hmat(freq,user) (frame:" << framecount << ") = " << endl; gsl_matrix_complex_show(Hmat); #endif // // *********************************************************** // CARRIER ALLOCATION STRATEGIES // *********************************************************** // switch (Mode()) { case 0: // FIXED_ALLOCATION break; case 1: // GIVE_BEST_CARR // // SORT CARRIERS OF EACH USERS // // uses Hmat: the frequency responses of channel tx_n --> rx_n // // starting from user u ... // find the best (in u ranking) unused carrier and assign it to u // next user until no more available carriers for(int u=0; u<M(); u++) { // cycle through users gsl_vector_complex_const_view huser = gsl_matrix_complex_const_column(Hmat,u); gsl_vector_uint_view sortindu = gsl_matrix_uint_column(Hperm,u); for (int j=0; j<N(); j++) { double currpower = gsl_complex_abs2(gsl_vector_complex_get(&huser.vector,j)); gsl_vector_set(huserabs,j,currpower); } // sort over c using abs(h(u,c)) gsl_sort_vector_index(p,huserabs); for (int j=0; j<N(); j++) { uint currindex = p->data[j]; gsl_vector_uint_set(&sortindu.vector,j,currindex); } } // // FIND INITIAL USER RANDOMLY // curruser = gsl_rng_uniform_int(ran,M()); // // ASSIGN FREQUENCIES // gsl_vector_uint_set_all(nextcarr,0); gsl_vector_uint_set_all(usedcarr,0); for (int j=0; j<J(); j++) { for (int uu=0; uu<M(); uu++) { int u = (uu+curruser) % M(); int isassigned = 0; while (! isassigned) { int tag = gsl_vector_uint_get(nextcarr,u); gsl_vector_uint_set(nextcarr,u,++tag); int carrier = gsl_matrix_uint_get(Hperm,N()-tag,u); if (! gsl_vector_uint_get(usedcarr,carrier)) { isassigned = 1; gsl_vector_uint_set(usedcarr,carrier,isassigned); gsl_matrix_uint_set(signature_frequencies,u,j,carrier); } else if (tag==N()) { cerr << "Block: " << BlockName << " allocation problem." << endl; exit(1); } } } } // // show channels and permutations // // gsl_matrix_complex_show(Hmat); //gsl_matrix_uint_show(Hperm); //gsl_matrix_uint_show(signature_frequencies); break; case 2: // SWAP_BAD_GOOD // // SWAP_BAD_GOOD // // sort carriers for each user // choose randomly a starting user u // for each user starting with u // swap worst carrier used by u with best carrier if used by others // sort carriers for(int u=0; u<M(); u++) { gsl_vector_complex_const_view huser = gsl_matrix_complex_const_column(Hmat,u); gsl_vector_uint_view sortindu = gsl_matrix_uint_column(Hperm,u); gsl_vector_view huserabs = gsl_matrix_column(habs,u); for (int j=0; j<N(); j++) { double currpower = gsl_complex_abs2(gsl_vector_complex_get(&huser.vector,j)); gsl_vector_set(&huserabs.vector,j,currpower); } // // sort channels for user <u> // gsl_sort_vector_index(p,&huserabs.vector); for (int j=0; j<N(); j++) { uint currindex = p->data[j]; gsl_vector_uint_set(&sortindu.vector,j,currindex); } } // // Hperm(N,USERS) contains sorted channels index for each users // habs(N,USERS) contains channel energy per each user // // // FIND INITIAL USER RANDOMLY for fairness // curruser = gsl_rng_uniform_int(ran,M()); // // ASSIGN FREQUENCIES // // // for each user ... // for (int uu=0; uu<M(); uu++) { int u = (uu+curruser) % M(); // // worst allocated channel for user u // double worstvalue=GSL_POSINF; unsigned int worstjindex; for (int j=0; j<J(); j++) { unsigned int chind = gsl_matrix_uint_get(signature_frequencies,u,j); double currh = gsl_matrix_get(habs,chind,u); if (currh < worstvalue) { worstvalue = currh; worstjindex = j; } } // // find best channel allocated by other users // // double bestvalue=0; unsigned int bestuser, bestjindex; for (int uuu=0; uuu<M()-1; uuu++) { unsigned int otheru = (uuu+u) % M(); for (int j=0; j<J(); j++) { unsigned int chind = gsl_matrix_uint_get(signature_frequencies,otheru,j); double currh = gsl_matrix_get(habs,chind,otheru); if (currh > bestvalue) { bestvalue = currh; bestjindex = j; bestuser = otheru; } } } // // finally the swap ! // unsigned int chind = gsl_matrix_uint_get(signature_frequencies,u,worstjindex); gsl_matrix_uint_set(signature_frequencies,u,worstjindex, gsl_matrix_uint_get(signature_frequencies, bestuser,bestjindex)); gsl_matrix_uint_set(signature_frequencies,bestuser,bestjindex,chind); // cout << "\n\nProcessing user " << u << endl // << "\tSwapped " << u << "." << worstjindex // << " <-> " << bestuser << "." << bestjindex << endl; } break; case 3: // BEST_OVERLAP // // SORT CARRIERS OF EACH USERS // gsl_matrix_uint_memcpy(signature_frequencies, signature_frequencies_init); for(int u=0; u<M(); u++) { gsl_vector_complex_const_view huser = gsl_matrix_complex_const_column(Hmat,u); gsl_vector_uint_view sortindu = gsl_matrix_uint_column(Hperm,u); for (int j=0; j<N(); j++) { double currpower = gsl_complex_abs2(gsl_vector_complex_get(&huser.vector, j)); gsl_vector_set(huserabs,j,currpower); } gsl_sort_vector_index(p,huserabs); for (int j=0; j<N(); j++) { uint currindex = p->data[j]; gsl_vector_uint_set(&sortindu.vector,j,currindex); } } // // each user take his best carriers allowing carrier overlap // for (int u=0; u<M(); u++) { for (int j=0; j<J(); j++) { int carrier = gsl_matrix_uint_get(Hperm,N()-j-1,u); gsl_matrix_uint_set(signature_frequencies,u,j,carrier); } } // // show channels and permutations // //gsl_matrix_complex_show(Hmat); //gsl_matrix_uint_show(Hperm); //gsl_matrix_uint_show(signature_frequencies); break; case 4: // SOAR_AI // // SOAR // // agent crai5 // bases the decisions on the frequency response tx_m --> rx_m in Hmat(N,M) // for each user it proposes a swap between carriers if the instantaneous impulse channel response // is better // // agent crai6 // for each user it proposes a swap of allocated carriers with one other users // error report is the metric for correct decisions (RL) #ifdef PAUSED // keypress cout << "pause maillocator: before decision loop ... (press ENTER key)" << endl; cin.ignore(); #endif // Every DECISION_INTERVAL we increase the input-time and allow decisions if (framecount % DECISION_INTERVAL == 0) { pAgent->Update(inputTime,++input_time); pAgent->Commit(); } // run agent till output noDecisions = 0; numberCommands=0; while (! (noDecisions) ) { // main decisional loop // // INPUT LINK Update // UpdateInputLink(); //pAgent->RunSelf(1); pAgent->RunSelfTilOutput(); numberCommands = pAgent->GetNumberCommands() ; #ifdef PAUSED // keypress cout << "pause maillocator: after RunSelfTilOutput() ... (press ENTER key)" << endl; cin.ignore(); #endif // loop through received commands for (int cmd = 0 ; cmd < numberCommands ; cmd++) { Identifier* pCommand = pAgent->GetCommand(cmd) ; string name = pCommand->GetCommandName() ; if (name == "assign-free") { std::string sUid = pCommand->GetParameterValue("uid"); std::string sDeassign = pCommand->GetParameterValue("deassign"); std::string sAssign = pCommand->GetParameterValue("assign"); #ifdef SHOW_SOAR cout << "assign-free command received [ u:" << sUid << " , -" << sDeassign << " , +" << sAssign << " ]" << endl; #endif AssignFree(sUid,sDeassign,sAssign); pCommand->AddStatusComplete(); } else if (name == "swap-carriers") { std::string sU1 = pCommand->GetParameterValue("u1"); std::string sC1 = pCommand->GetParameterValue("c1"); std::string sU2 = pCommand->GetParameterValue("u2"); std::string sC2 = pCommand->GetParameterValue("c2"); #ifdef SHOW_SOAR cout << "swap-carriers command received [ u1:" << sU1 << " , c1:" << sC1 << " , u2:" << sU2 << " , c2:" << sC2 << " ]" << endl; #endif SwapCarriers(sU1,sC1,sU2,sC2); pCommand->AddStatusComplete(); } else if (name == "increase-power") { std::string sUid = pCommand->GetParameterValue("uid"); std::string sCid = pCommand->GetParameterValue("cid"); #ifdef SHOW_SOAR cout << "increase-power command received [ u:" << sUid << " , c:" << sCid << " ]" << endl; #endif IncreasePower(sUid,sCid); pCommand->AddStatusComplete(); break; } else if (name == "no-choices") { #ifdef SHOW_SOAR cout << "no-choices command received" << endl; #endif noDecisions = 1; pCommand->AddStatusComplete(); break; } else { #ifdef SHOW_SOAR cout << "ignoring unknown output command from SOAR" << endl; #endif break; } // cout << "framecount = " << framecount << endl; } // end command loop } // while (! (noDecisions) ) break; } // switch (Mode()) } // if DECISION_INTERVAL % 0 // // every 10s dump frame count // time(&nowtime); if (difftime(nowtime,reporttime) > TIMEDELTA) { reporttime = nowtime; cout << "frame:" << framecount << "\r"; cout.flush(); } //////// production of data framecount++; ericount++; mout1.DeliverDataObj( *signature_frequencies ); mout2.DeliverDataObj( *signature_powers ); #ifdef SHOW_MATRIX cout << "signature frequencies (frame:" << framecount-1 << ") = " << endl; gsl_matrix_uint_show(signature_frequencies); #endif }