Example #1
0
  double fitnessDistanceCorrelation(
      const std::unordered_map<arma::vec, double, Hash, IsEqual>& samples) {
    if (samples.size() < 2) {
      throw std::invalid_argument("fitnessDistanceCorrelation: The number of samples must be greater than 2.");
    } else if (!isDimensionallyConsistent(samples)) {
      throw std::invalid_argument("fitnessDistanceCorrelation: The samples must be dimensionally consistent");
    }

    // Converts the set of samples into a matrix of parameters (each row is a dimension and each column a parameter) and a row vector of objective values, such that we can use Armadillo C++ to manipulate them.
    arma::mat parameters(samples.cbegin()->first.n_elem, samples.size());
    arma::rowvec objectiveValues(parameters.n_cols);

    arma::uword n = 0;
    for (const auto& sample : samples) {
      parameters.col(n) = sample.first;
      objectiveValues(n) = sample.second;

      ++n;
    }

    // Determines one parameter having a minimal objective value within the set of samples.
    // The best parameter is then subtracted from all other parameters, so that we can later calculated the distance towards the best one.
    arma::uword bestParameterIndex;
    objectiveValues.min(bestParameterIndex);
    parameters.each_col() -= parameters.col(bestParameterIndex);

    // Excludes the best/reference parameter from the correlation, as it will always perfectly correlate with itself and therefore bias the correlation coefficient.
    parameters.shed_col(bestParameterIndex);
    objectiveValues.shed_col(bestParameterIndex);

    // Uses `arma::sum(arma::square(...))` to emulate a column-wise vector norm operator that Armadillo C++ does not have (and this is not likely to change, as it interferes with matrix norms).
    return arma::as_scalar(arma::cor(arma::sqrt(arma::sum(arma::square(parameters))), objectiveValues));
  }
  void FitnessDistanceCorrelationAnalysis::analyseImplementation() {
    assert(samples_.size() > 1);

    arma::Mat<double> parameters(numberOfDimensions_, samples_.size());
    arma::Row<double> objectiveValues(parameters.n_cols);

    arma::uword n = 0;
    for (const auto& parameterToObjectiveValueMapping : samples_) {
      parameters.col(n) = parameterToObjectiveValueMapping.first;
      objectiveValues(n) = parameterToObjectiveValueMapping.second;
      ++n;
    }

    arma::uword bestParameterIndex;
    objectiveValues.min(bestParameterIndex);

    parameters.each_col() -= parameters.col(bestParameterIndex);

    parameters.shed_col(bestParameterIndex);
    objectiveValues.shed_col(bestParameterIndex);

    correlationCoefficient_ = arma::as_scalar(arma::cor(arma::sqrt(arma::sum(arma::square(parameters))), objectiveValues));
  }