14.21 stableMarriage

7PublicSchoolLads utilised a stable marriage algorithm approach to match important locations on the field to the available players in an globally optimal fashion. The idea was if we can define important formational locations on the field relative to the ball could we then optimally assign different players to go to those locations so that each location was allocated to a unique player in a way in which the overall distance traveled to get to those locations was minimized. In order to use this function though you need to first determine each players preference to for each position. This was handled in GeneratePreferenceArray


vector<int> NaoBehavior::stableMarriage(vector<vector<pair<double,int > > > PreferenceToPointArray)
{
    // Convert vector to 2D array
    int prefer[2*NUM_AGENTS][NUM_AGENTS];

    for(int i=0;i<NUM_AGENTS;i++){
        for(int j=0;j<NUM_AGENTS;j++){
            prefer[i][j] = PreferenceToPointArray[i][j].second;
            prefer[i+NUM_AGENTS][j] = j;
        }
    }
    
    // Stores partner of Points. This is our output array that
    // stores paring information.  The value of wPartner[i]
    // indicates the partner assigned to Point N+i.  Note that
    // the Points number between N and 2*N-1. The value -1
    // indicates that (N+i)'th point is free
    int wPartner[NUM_AGENTS];
  
    // An array to store availability of Players.  If mFree[i] is
    // false, then player 'i' is free, otherwise engaged.
    bool mFree[NUM_AGENTS];
  
    // Initialize all players and points as free
    memset(wPartner, -1, sizeof(wPartner));
    memset(mFree, false, sizeof(mFree));
    int freeCount = NUM_AGENTS;
  
    //for (int p=0;p<NUM_AGENTS;p++){
    //    cout << wPartner[p] << "\n";
    //}


    // While there are free players
    while (freeCount > 0)
    {
        // Pick the first free player (we could pick any)
        int m;
        for (m = 0; m < NUM_AGENTS; m++)
            if (mFree[m] == false)
                break;
  
        // One by one go to all points according to m's preferences.
        // Here m is the picked free player
        for (int i = 0; i < NUM_AGENTS && mFree[m] == false; i++)
        {
            int w = prefer[m][i];

            // The point of preference is free, w and m become
            // partners (Note that the partnership maybe changed
            // later). So we can say they are engaged not married

            if (wPartner[w] == -1)
            {
                wPartner[w] = m;
                mFree[m] = true;
                freeCount--;
            }
            else  // If w is not free
            {
                // Find current engagement of w
                int m1 = wPartner[w];
  
                // If w prefers m over her current engagement m1,
                // then break the engagement between w and m1 and
                // engage m with w.
                if (wPrefersM1OverM(prefer, w, m, m1) == false)
                {
                    wPartner[w] = m;
                    mFree[m] = true;
                    mFree[m1] = false;
                }
            } // End of Else
        } // End of the for loop that goes to all points in m's list
    } // End of main while loop
  
  
    // Print the solution
    /* cout << "Point   Player" << endl;
    for (int i = 0; i < NUM_AGENTS; i++)
       cout << " " << i << "\t" << wPartner[i] << endl; */


    vector<int> v(std::begin(wPartner), std::end(wPartner));
    return v;   
}