GallaghersGaussian21hiPeaksFunction::GallaghersGaussian21hiPeaksFunction(
        const arma::uword numberOfDimensions)
        : BlackBoxOptimisationBenchmark(numberOfDimensions),
          weight_(arma::join_cols(arma::Col<double>({10.0}), arma::linspace<arma::Col<double>>(1.1, 9.1, 20))),
          localParameterConditionings_(getRandomLocalParameterHighConditionings(21)),
          localParameterTranslations_(arma::randu<arma::Mat<double>>(numberOfDimensions_, 21) * 9.8 - 4.9),
          rotationQ_(randomRotationMatrix(numberOfDimensions_)) {
      localParameterTranslations_.col(0) = 0.8 * localParameterTranslations_.col(0);

#if defined(SUPPORT_MPI)
      MPI_Bcast(localParameterConditionings_.memptr(), static_cast<int>(localParameterConditionings_.n_elem), MPI_DOUBLE, 0, MPI_COMM_WORLD);
      MPI_Bcast(localParameterTranslations_.memptr(), static_cast<int>(localParameterTranslations_.n_elem), MPI_DOUBLE, 0, MPI_COMM_WORLD);
      MPI_Bcast(rotationQ_.memptr(), static_cast<int>(rotationQ_.n_elem), MPI_DOUBLE, 0, MPI_COMM_WORLD);
#endif

      setObjectiveFunction(
          [this](
              const arma::Col<double>& parameter_) {
            assert(parameter_.n_elem == numberOfDimensions_);
              
            double maximalValue = std::numeric_limits<double>::lowest();
            for (arma::uword n = 0; n < 21; ++n) {
              const arma::Col<double>& localParameterTranslation = parameter_ - localParameterTranslations_.col(n);
              maximalValue = std::max(maximalValue, weight_(n) * std::exp(-0.5 / static_cast<double>(numberOfDimensions_) * arma::dot(localParameterTranslation, rotationQ_.t() * arma::diagmat(localParameterConditionings_.col(n)) * rotationQ_ * localParameterTranslation)));
            }

            return std::pow(getOscillatedValue(10.0 - maximalValue), 2.0);
          },
          "BBOB Gallagher's Gaussian 21-hi Peaks Function (f22)");
    }
// Initialize state.
node_impl::node_impl (const char * name)
{
        name_ (name);
        weight_ (0);
        degree_ (0);
        neighbors_ ().length (0);
}
void
node_impl::print (void)
{
  cout << "  Name: " << name_ () << endl;
  cout << "    Weight: " << weight_ () << endl;
  cout << "    Degree: " << degree_ () << endl;
  cout << "    Neighbors: " << endl;
  for (size_t i = 0; i < neighbors_ ().length (); i++)
    cout << "      " << neighbors_ ()[i]->name_ () << endl;
}
    double GallaghersGaussian21hiPeaksFunction<T>::getObjectiveValueImplementation(
        const arma::Col<T>& parameter) const noexcept {
      double maximalValue = std::numeric_limits<double>::lowest();
      for (std::size_t k = 0; k < 21; ++k) {
        const arma::Col<T>& locallyTranslatedParameter = parameter - localParameterTranslations_.col(k);
        maximalValue = std::max(maximalValue, weight_(k) * std::exp(-0.5 / static_cast<double>(this->numberOfDimensions_) * static_cast<double>(arma::dot(locallyTranslatedParameter, rotationQ_.t() * arma::diagmat(localParameterConditionings_.col(k)) * rotationQ_ * locallyTranslatedParameter))));
      }

      return std::pow(this->getOscillatedValue(10.0 - maximalValue), 2.0);
    }
    double GallaghersGaussian101mePeaksFunction::getObjectiveValueImplementation(
        const arma::Col<double>& parameter) const {
      assert(parameter.n_elem == numberOfDimensions_);

      double maximalValue = std::numeric_limits<double>::lowest();
      for (arma::uword n = 0; n < 101; ++n) {
        const arma::Col<double>& locallyTranslatedParameter = parameter - localParameterTranslations_.col(n);
        maximalValue = std::max(maximalValue, weight_(n) * std::exp(-0.5 / static_cast<double>(numberOfDimensions_) * arma::dot(locallyTranslatedParameter, rotationQ_.t() * arma::diagmat(localParameterConditionings_.col(n)) * rotationQ_ * locallyTranslatedParameter)));
      }

      return std::pow(getOscillatedValue(10.0 - maximalValue), 2.0);
    }
void
node_impl::change_weight (CORBA::Long new_weight)
{
  weight_ (new_weight);
}