예제 #1
0
static PyObject* selNSGA2(PyObject *self, PyObject *args){
    /* Args[0] : Individual list
     * Args[1] : Number of individuals wanted in output
     * Return : k selected individuals from input individual list
     */
    PyObject *lListIndv = PyTuple_GetItem(args, 0);
#ifdef PY3K
    unsigned long k = (unsigned long)PyLong_AS_LONG(PyTuple_GetItem(args, 1));
#else
    unsigned int k = (unsigned int)PyInt_AS_LONG(PyTuple_GetItem(args, 1));
#endif
    
    PyObject *lListSelect = PyList_New(0);
    
    unsigned int lLenListIndv = (unsigned int)PyList_Size(lListIndv);
    unsigned int lNbrObjectives = (unsigned int)PyTuple_Size(PyObject_GetAttrString(PyObject_GetAttrString(PyList_GetItem(lListIndv,0), "fitness"), "values"));
    
    if(k == 0)
        return lListSelect;
    
    // First : copy fitness values into an std::vector<std::vector<double> >
    // First vector index is used to identify individuals
    // Second vector index represents an objective
    std::vector<std::vector<double> > lPopFit(lLenListIndv, std::vector<double>(lNbrObjectives,0.));
    for(unsigned int i = 0; i < lLenListIndv; i++){
        for(unsigned int j = 0; j < lNbrObjectives; j++)
            lPopFit[i][j] = PyFloat_AS_DOUBLE(PyTuple_GetItem(PyObject_GetAttrString(PyObject_GetAttrString(PyList_GetItem(lListIndv,i), "fitness"), "wvalues"), j));
    }
    
    
    unsigned int lParetoSorted = 0;
    unsigned int lFrontIndex = 0;
    std::vector<std::vector<unsigned int> > lParetoFront(1, std::vector<unsigned int>(0));
    std::vector<unsigned int> lDominating(lLenListIndv, 0);
    std::vector<std::vector<unsigned int> > lDominatedInds(lLenListIndv, std::vector<unsigned int>(0));
    
    // Rank first pareto front
    for(unsigned int i = 0; i < lLenListIndv; i++){
        for(unsigned int j = i+1; j < lLenListIndv; j++){
            
            if(isDominated(lPopFit[j], lPopFit[i])){
                lDominating[j]++;
                lDominatedInds[i].push_back(j);
            }
            else if(isDominated(lPopFit[i], lPopFit[j])){
                lDominating[i]++;
                lDominatedInds[j].push_back(i);
            }
        }
        if(lDominating[i] == 0){
            lParetoFront[lFrontIndex].push_back(i);
            lParetoSorted++;
        }
    }

    // Rank other pareto fronts, until we reach the *k* limit
    while(lParetoSorted < k && lParetoSorted < lLenListIndv){
        lFrontIndex++;
        lParetoFront.push_back(std::vector<unsigned int>(0));
        for(unsigned int i = 0; i < lParetoFront[lFrontIndex-1].size(); i++){
            unsigned int lIndiceP = lParetoFront[lFrontIndex-1][i];
            for(unsigned int j = 0; j < lDominatedInds[lIndiceP].size(); j++){
                unsigned int lIndiceD = lDominatedInds[lIndiceP][j];
                if(--lDominating[lIndiceD] == 0){
                    lParetoFront[lFrontIndex].push_back(lIndiceD);
                    lParetoSorted++;
                }
            }
        }
    }
    
    // Append individuals from pareto ranking until we reach the limit
    for(unsigned int i = 0; i < lParetoFront.size(); i++){
        if(PyList_Size(lListSelect)+lParetoFront[i].size() <= k){
            for(unsigned int j = 0; j < lParetoFront[i].size(); j++)
                PyList_Append(lListSelect, PyList_GetItem(lListIndv,lParetoFront[i][j]));
        }
        else{
            break;
        }
    }

    // Crowding distance on the last front
    if(PyList_Size(lListSelect) == k)
        return lListSelect;
    
    FitComp lCmpIndvObj;
    std::vector<unsigned int> lLastParetoFront = lParetoFront.back();
    std::vector<std::pair<double, unsigned int> > lDistances(0);
    std::vector<std::pair<std::vector<double>, unsigned int> > lCrowdingList(0);
    double lInfinity = std::numeric_limits<double>::infinity();
    
    // Reserve sufficient memory for the subsequent push_back
    lDistances.reserve(lLastParetoFront.size());
    lCrowdingList.reserve(lLastParetoFront.size());
    
    for(unsigned int i = 0; i < lLastParetoFront.size(); i++){
        // Push initial distance (0.0) and individual index in lPopFit and lListIndv for each individual
        lDistances.push_back(std::pair<double, unsigned int>(0., lLastParetoFront[i]));
        
        // Push fitness and individual index in lDistances for each individual
        lCrowdingList.push_back(std::pair<std::vector<double>, unsigned int>(lPopFit[lLastParetoFront[i]],i));
    }
    
    for(unsigned int i = 0; i < lNbrObjectives; i++){
        // For each objective
        // Set the current objective in the comparison class
        lCmpIndvObj.mCompIndex = i;
        // Sort (stable, in order to keep the same order for equal fitness values)
        stable_sort(lCrowdingList.begin(), lCrowdingList.end(), lCmpIndvObj);
        
        // Set an infinite distance to the extremums
        lDistances[lCrowdingList[0].second].first = lInfinity;
        lDistances[lCrowdingList.back().second].first = lInfinity;

        for(unsigned int j = 1; j < lCrowdingList.size()-1; j++){
            if(lDistances[lCrowdingList[j].second].first < lInfinity)
                lDistances[lCrowdingList[j].second].first += lCrowdingList[j+1].first[i]-lCrowdingList[j-1].first[i];
        }
    }
    
    // Final sorting (again, must be stable)
    stable_sort(lDistances.begin(), lDistances.end(), crowdDistComp);
   
    // Pick the last individuals (with the higher crowding distance) first
    for(unsigned int i = lDistances.size()-1; i >= 0; i--){
        if(PyList_Size(lListSelect) >= k)
            break;
        // While the size of the return list is lesser than *k*, append the next individual
        PyList_Append(lListSelect, PyList_GetItem(lListIndv,lDistances[i].second));  
    }
    
    return lListSelect;
}
예제 #2
0
//------------------------------------------------------------------------------
BranchInst *findOutermostBranch(BranchSet &branches, const DominatorTree *dt) {
  for (auto branch : branches)
    if (!isDominated(branch, branches, dt))
      return branch;
  return nullptr;
}