Exemplo n.º 1
0
optimise_result<T1, N> optimise(
    const T2<T1, N>& problem,
    const T3<T1, N>& optimiser,
    std::vector<std::array<T1, N>> initial_parameters) {
  static_assert(std::is_floating_point<T1>::value, "");
  static_assert(N > 0, "");
  static_assert(std::is_base_of<mant::problem<T1, N>, T2<T1, N>>::value, "");
  static_assert(std::is_base_of<mant::optimiser<T1, N>, T3<T1, N>>::value, "");

  assert(static_cast<bool>(problem.objective_function));
  assert(static_cast<bool>(optimiser.optimisation_function));
  assert(initial_parameters.size() > 0);

  // Maps the parameter's bounds from [*problem.lower_bounds*, *problem.upper_bounds*] to [0, 1] and places all active dimensions (in-order) upfront.
  for (auto& parameter : initial_parameters) {
    for (std::size_t n = 0; n < optimiser.active_dimensions.size(); ++n) {
      parameter.at(n) = (
          parameter.at(optimiser.active_dimensions.at(n)) -
          problem.lower_bounds.at(n)
        ) / (problem.upper_bounds.at(n) - problem.lower_bounds.at(n));
    }
  }

  mant::problem<T1, N> mapped_problem;
  mapped_problem.objective_function = [&problem, &optimiser](const auto& parameter) {
    std::array<T1, N> mapped_parameter = problem.lower_bounds;
    for (std::size_t n = optimiser.active_dimensions.size(); n > 0; --n) {
      mapped_parameter.at(optimiser.active_dimensions.at(n - 1)) =
        problem.lower_bounds.at(n - 1) +
        parameter.at(n - 1) * (
          problem.upper_bounds.at(n - 1) - problem.lower_bounds.at(n - 1)
        );
    }

    return problem.objective_function(mapped_parameter);
  };
  assert(std::all_of(
    mapped_problem.lower_bounds.cbegin(), std::next(mapped_problem.lower_bounds.cbegin(), optimiser.active_dimensions.size()),
    std::bind(std::equal_to<T1>{}, std::placeholders::_1, T1(0.0))
  ));
  assert(std::all_of(
    mapped_problem.upper_bounds.cbegin(), std::next(mapped_problem.upper_bounds.cbegin(), optimiser.active_dimensions.size()),
    std::bind(std::equal_to<T1>{}, std::placeholders::_1, T1(1.0))
  ));

  auto&& result = optimiser.optimisation_function(mapped_problem, initial_parameters);

  // Remaps the parameter's bounds back from [0, 1] to [*lower_bounds*, *upper_bounds*] and permutes the parameter to match the active dimensions.
  for (std::size_t n = optimiser.active_dimensions.size(); n > 0; --n) {
    result.parameter.at(optimiser.active_dimensions.at(n - 1)) =
      problem.lower_bounds.at(n - 1) +
      result.parameter.at(n - 1) * (
        problem.upper_bounds.at(n - 1) - problem.lower_bounds.at(n - 1)
      );
  }

  return result;
}