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; }