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 }