Commit 6c878249 authored by Dmitry Bagaev's avatar Dmitry Bagaev
Browse files

Refactoring. Improvments.

parent e946a749
......@@ -171,19 +171,19 @@ int main(int argc, char **argv) {
if (rank == 0) std::cout << "Solving with " << solverName << std::endl;
TTSP::OptimizationParameter tau("tau", {3e-2, 5e-2, 6e-2, 7e-2, 8e-2, 9e-2, 1e-1, 2e-1, 3e-1, 5e-1, 7e-1, 9e-1}, 1e-3);
TTSP::OptimizationParameter tau("tau", std::make_pair(-4, -1), 0.1, 1e-3, TTSP::OptimizationParameterType::EXPONENT);
//TTSP::OptimizationParameter q("q", {0, 1, 2, 3, 4}, 2);
TTSP::OptimizationParameter eps("eps", {1e-7, 1e-6, 1e-5, 1e-4, 1e-3}, 1e-5);
//TTSP::OptimizationParameter eps("eps", {1e-7, 1e-6, 1e-5, 1e-4, 1e-3}, 1e-5);
TTSP::OptimizationParameterEntries entries;
entries.emplace_back(std::make_pair(eps, eps.GetDefaultValue()));
//entries.emplace_back(std::make_pair(eps, eps.GetDefaultValue()));
entries.emplace_back(std::make_pair(tau, tau.GetDefaultValue()));
//entries.emplace_back(std::make_pair(q, q.GetDefaultValue()));
TTSP::OptimizerProperties properties;
properties["tau:use_closest"] = "false";
properties["tau:strict_bound"] = "false";
properties["tau:strict_bound"] = "true";
properties["eps:use_closest"] = "false";
properties["eps:strict_bound"] = "false";
......@@ -204,7 +204,7 @@ int main(int argc, char **argv) {
TTSP::OptimizerInterface *optimizer = TTSP::OptimizerInterface::GetOptimizer(optimizerType, parameters, properties, 50);
optimizer->SetVerbosityLevel(TTSP::OptimizerVerbosityLevel::Level1);
optimizer->SetVerbosityLevel(TTSP::OptimizerVerbosityLevel::Level3);
while (!series.end()) {
......@@ -236,7 +236,7 @@ int main(int argc, char **argv) {
void *data) -> TTSP::OptimizationFunctionInvokeResult {
std::for_each(after.begin(), after.end(), [&solver](const TTSP::OptimizationParameterPoint &point) {
solver.SetParameter(point.first, INMOST::to_string(point.second));
solver.SetParameter(point.GetName(), INMOST::to_string(point.GetValue()));
});
INMOST::Sparse::Vector SOL("SOL", rhs.GetFirstIndex(), rhs.GetLastIndex());
......@@ -252,7 +252,7 @@ int main(int argc, char **argv) {
double time = Timer() - tmp_time;
std::for_each(before.begin(), before.end(), [&solver](const TTSP::OptimizationParameterPoint &point) {
solver.SetParameter(point.first, INMOST::to_string(point.second));
solver.SetParameter(point.GetName(), INMOST::to_string(point.GetValue()));
});
return std::make_pair(is_solved, time);
......@@ -273,7 +273,7 @@ int main(int argc, char **argv) {
if (rank == 0 && verbosity > TTSP::OptimizerVerbosityLevel::Level0) {
std::string metadata = solver.SolutionMetadataLine("\t");
std::for_each(suggestion.GetPointsAfter().begin(), suggestion.GetPointsAfter().end(), [&metadata](const TTSP::OptimizationParameterPoint &p) {
metadata += ("\t" + INMOST::to_string(p.second));
metadata += ("\t" + INMOST::to_string(p.GetValue()));
});
std::cout << metadata << std::endl;
}
......@@ -283,7 +283,7 @@ int main(int argc, char **argv) {
std::cout << std::endl << "Next optimization parameters found for current iteration:" << std::endl;
const TTSP::OptimizationParameterPoints &points = optimizer->GetPoints();
std::for_each(points.begin(), points.end(), [](const TTSP::OptimizationParameterPoint &p) {
std::cout << "\t" << p.first << " = " << p.second << std::endl;
std::cout << "\t" << p.GetName() << " = " << p.GetValue() << std::endl;
});
}
......@@ -293,19 +293,19 @@ int main(int argc, char **argv) {
const TTSP::OptimizationParameterResultsBuffer &results = optimizer->GetResults();
int index = 1;
std::for_each(results.begin(), results.end(), [&index](const TTSP::OptimizationParameterResult &result) {
std::for_each(results.cbegin(), results.cend(), [&index](const TTSP::OptimizationParameterResult &result) {
std::cout << "\t" << index++ << "\t" << " [";
const TTSP::OptimizationParameterPoints &pbefore = result.GetPointsBefore();
std::for_each(pbefore.begin(), pbefore.end(), [](const TTSP::OptimizationParameterPoint &point) {
std::cout << " " << point.first << "=" << point.second << " ";
std::cout << " " << point.GetName() << "=" << point.GetValue() << " ";
});
std::cout << "] -> [";
const TTSP::OptimizationParameterPoints &pafter = result.GetPointsAfter();
std::for_each(pafter.begin(), pafter.end(), [](const TTSP::OptimizationParameterPoint &point) {
std::cout << " " << point.first << "=" << point.second << " ";
std::cout << " " << point.GetName() << "=" << point.GetValue() << " ";
});
std::cout << "]\t\t(" << result.GetMetricsBefore() << " -> " << result.GetMetricsAfter() << ")" << std::endl;
......
......@@ -16,15 +16,24 @@ namespace TTSP {
/// Usage: OptimizationParameterRange range = std::make_pair(0.0, 1.0)
typedef std::pair<double, double> OptimizationParameterRange;
/// This class is used to defined a type of a parameter
/// - DEFAULT - parameter values should be used as is
/// - EXPONENT - parameter values should be converted to 10^v
enum class OptimizationParameterType {
DEFAULT,
EXPONENT
};
/// This class is used to define a solver parameter for optimization algortihms
/// Usage:
/// 1. OptimizationParameter tau("tau", range, 0.1, 1e-3);
/// 2. OptimizationParameter kovl("kovl", { 0, 1, 2, 3 }, 0);
class OptimizationParameter {
private:
std::string name; /// A name of a parameter
std::vector<double> values; /// List of possible values for a paramater
double default_value; /// Default value for this parameter
std::string name; /// A name of a parameter
std::vector<double> values; /// List of possible values for a parameter
double default_value; /// Default value for this parameter
OptimizationParameterType type; /// Parameter type
static void swap(OptimizationParameter &left, OptimizationParameter &right);
......@@ -34,14 +43,17 @@ namespace TTSP {
/// @param range - Range of possible values for this parameter
/// @param step - Step associated with the range (used to split up values in a list)
/// @param default_value - Default value for this parameter
OptimizationParameter(const std::string &name, const OptimizationParameterRange &range,
double step, double default_value);
/// @param type - Parameter type
OptimizationParameter(const std::string &name, const OptimizationParameterRange &range, double step,
double default_value, OptimizationParameterType type = OptimizationParameterType::DEFAULT);
/// Default constructor to define an OptimizationParameter with list of possible values
/// @param name - Name of a parameter
/// @param values - List of possible values for this parameter
/// @param default_value - Default value for this parameter
OptimizationParameter(const std::string &name, const std::vector<double> &values, double default_value);
/// @param type - Parameter type
OptimizationParameter(const std::string &name, const std::vector<double> &values,
double default_value, OptimizationParameterType type = OptimizationParameterType::DEFAULT);
/// Copy constructor
/// @param other - OptimizationParameter to make copy of
......@@ -75,33 +87,62 @@ namespace TTSP {
/// Getter for default_value of a parameter
double GetDefaultValue() const noexcept;
/// Getter for type of a parameter
OptimizationParameterType GetType() const noexcept;
};
/// This class is used to store an OptimizationParameter and associated current value
/// @see OptimizationParameter
typedef std::pair<OptimizationParameter, double> OptimizationParametersEntry;
/// This class is used to store a list of OptimizationParameter and associated current value
/// This class is used to store a list of OptimizationParameterEntry
/// @see OptimizationParameter
/// @see OptimizationParametersEntry
typedef std::vector<OptimizationParametersEntry> OptimizationParameterEntries;
/// This class is used to store a slice of OptimizationParametersSpace for some optimization parameter
/// This class is used to store a slice of OptimizationParameters for some optimization parameter
/// @see OptimizationParameter
/// @see OptimizationParametersSpace
typedef std::pair<std::string, double> OptimizationParameterPoint;
class OptimizationParameterPoint {
private:
std::string name;
double value;
OptimizationParameterPoint(const std::string &name, double value, OptimizationParameterType type);
static void swap(OptimizationParameterPoint &left, OptimizationParameterPoint &right);
static double convert(double value, OptimizationParameterType type);
public:
OptimizationParameterPoint(const OptimizationParameterPoint &other);
OptimizationParameterPoint(OptimizationParameterPoint &&other) noexcept;
OptimizationParameterPoint &operator=(const OptimizationParameterPoint &other);
/// This class is used to store a slice of OptimizationParametersSpace for all optimization parameters
const std::string& GetName() const noexcept;
double GetValue() const noexcept;
~OptimizationParameterPoint();
friend class OptimizationParameters;
};
/// This class is used to store a slice of OptimizationParameters for all optimization parameters
/// @see OptimizationParameter
/// @see OptimizationParameterPoint
/// @see OptimizationParametersSpace
typedef std::vector<OptimizationParameterPoint> OptimizationParameterPoints;
typedef std::pair<std::size_t, double> OptimizationAlgorithmSuggestion;
/// This class is used to store a result of optimization iterations with suggested points and changed parameter
/// @see OptimizationParameter
/// @see OptimizationParameterPoint
/// @see OptimizationParameterPoints
/// @see OptimizationParametersSpace
/// @see OptimizationParameters
class OptimizationParametersSuggestion {
private:
const OptimizationParameter &changed;
......@@ -158,6 +199,9 @@ namespace TTSP {
/// Getter for parameter reference of this space by index
const OptimizationParameter &GetParameter(std::size_t index) const;
/// Getter for parameters count
std::size_t Size() const;
/// Getter for slice of parameters of this space
const OptimizationParameterPoints GetPoints() const noexcept;
......@@ -248,12 +292,12 @@ namespace TTSP {
OptimizationParameterResultsBuffer &operator=(const OptimizationParameterResultsBuffer &other);
/// Begin iterator of the buffer
std::deque<OptimizationParameterResult>::const_reverse_iterator begin() const noexcept;
std::deque<OptimizationParameterResult>::const_reverse_iterator cbegin() const noexcept;
const OptimizationParameterResult &at(std::size_t index) const;
/// End iterator of the buffer
std::deque<OptimizationParameterResult>::const_reverse_iterator end() const noexcept;
std::deque<OptimizationParameterResult>::const_reverse_iterator cend() const noexcept;
/// Utility method to push result to the start of ring buffer
/// @param result - Result to store
......@@ -296,13 +340,17 @@ namespace TTSP {
virtual void UpdateSpaceWithLatestResults();
virtual OptimizationAlgorithmSuggestion AlgorithmMakeSuggestion(const std::function<OptimizationFunctionInvokeResult(const OptimizationParameterPoints &,
const OptimizationParameterPoints &,
void *)> &invoke, void *data) const = 0;
public:
OptimizerInterface(const OptimizationParameters &parameters, const OptimizerProperties &properties, std::size_t buffer_capacity) :
parameters(parameters), properties(properties), results(buffer_capacity) {};
virtual OptimizationParametersSuggestion Suggest(const std::function<OptimizationFunctionInvokeResult(const OptimizationParameterPoints &,
const OptimizationParameterPoints &,
void *)> &invoke, void *data) const = 0;
OptimizationParametersSuggestion Suggest(const std::function<OptimizationFunctionInvokeResult(const OptimizationParameterPoints &,
const OptimizationParameterPoints &,
void *)> &invoke, void *data) const;
void SaveResult(const OptimizationParameter &changed,
const OptimizationParameterPoints &before, double metrics_before,
......
......@@ -68,26 +68,16 @@ namespace TTSP {
OptimizerInterface(space, properties, buffer_capacity), current_handler_index(0) {
const OptimizationParameterEntries &parameters = space.GetParameterEntries();
handlers.reserve(parameters.size());
std::for_each(parameters.begin(), parameters.end(), [this](const OptimizationParametersEntry &entry) {
std::for_each(parameters.cbegin(), parameters.cend(), [this](const OptimizationParametersEntry &entry) {
handlers.emplace_back(AlternatingParameterHandler(entry.first));
});
}
OptimizationParametersSuggestion AlternatingOptimizer::Suggest(const std::function<OptimizationFunctionInvokeResult(const OptimizationParameterPoints &,
const OptimizationParameterPoints &,
void *)> &invoke, void *data) const {
OptimizationParameterPoints points(parameters.GetParameterEntries().size());
int i = 0;
std::transform(handlers.begin(), handlers.end(), points.begin(), [this, &i](const AlternatingParameterHandler &h) {
return std::make_pair(
h.GetParameter().GetName(),
h.GetParameter().GetValues().at(i++ == current_handler_index ? h.NextIndex() : h.GetCurrentIndex())
);
});
return OptimizationParametersSuggestion(handlers.at(current_handler_index).GetParameter(), parameters.GetPoints(), parameters.GetMetrics(), points);
OptimizationAlgorithmSuggestion AlternatingOptimizer::AlgorithmMakeSuggestion(const std::function<OptimizationFunctionInvokeResult(const OptimizationParameterPoints &,
const OptimizationParameterPoints &,
void *)> &invoke, void *data) const {
const AlternatingParameterHandler &handler = handlers.at(current_handler_index);
return std::make_pair(current_handler_index, handler.GetParameter().GetValues().at(handler.NextIndex()));
}
void AlternatingOptimizer::UpdateSpaceWithLatestResults() {
......
......@@ -46,13 +46,13 @@ namespace TTSP {
protected:
void UpdateSpaceWithLatestResults() override;
OptimizationAlgorithmSuggestion AlgorithmMakeSuggestion(const std::function<OptimizationFunctionInvokeResult(const OptimizationParameterPoints &,
const OptimizationParameterPoints &,
void *)> &invoke, void *data) const override;
public:
AlternatingOptimizer(const OptimizationParameters &space, const OptimizerProperties &properties, std::size_t buffer_capacity);
OptimizationParametersSuggestion Suggest(const std::function<OptimizationFunctionInvokeResult(const OptimizationParameterPoints &,
const OptimizationParameterPoints &,
void *)> &invoke, void *data) const override;
virtual ~AlternatingOptimizer();
};
......
......@@ -36,7 +36,6 @@ namespace TTSP {
return distribution(generator);
}
AnnealingParameterOptimizationType AnnealingParameterHandler::DEFAULT_OPTIMIZATION_TYPE = STRICT;
double AnnealingParameterHandler::DEFAULT_TEMP0 = 0.0010037;
double AnnealingParameterHandler::DEFAULT_DECREMENT = 2;
bool AnnealingParameterHandler::DEFAULT_ALLOW_OSCILLATION = false;
......@@ -45,8 +44,7 @@ namespace TTSP {
bool AnnealingParameterHandler::DEFAULT_USE_CLOSEST = true;
AnnealingParameterHandler::AnnealingParameterHandler(const OptimizationParameter &parameter, const OptimizerInterface &optimizer) :
count(0), parameter(parameter), current_value(parameter.GetDefaultValue()),
optimization_type(AnnealingParameterHandler::DEFAULT_OPTIMIZATION_TYPE),
count(0), parameter(parameter), value(parameter.GetDefaultValue()),
temp0(AnnealingParameterHandler::DEFAULT_TEMP0),
decrement(AnnealingParameterHandler::DEFAULT_DECREMENT),
allow_oscillation(AnnealingParameterHandler::DEFAULT_ALLOW_OSCILLATION),
......@@ -54,16 +52,6 @@ namespace TTSP {
strict_bound(AnnealingParameterHandler::DEFAULT_STRICT_BOUND),
use_closest(AnnealingParameterHandler::DEFAULT_USE_CLOSEST) {
const std::string &optimization_type_property = parameter.GetName() + ":optimization_type";
if (optimizer.HasProperty(optimization_type_property)) {
const std::string &type = optimizer.GetProperty(optimization_type_property);
if (type == "strict") {
optimization_type = STRICT;
} else if (type == "exponent") {
optimization_type = EXPONENT;
}
}
const std::string &temp0_property = parameter.GetName() + ":temp0";
if (optimizer.HasProperty(temp0_property)) {
temp0 = std::atof(optimizer.GetProperty(temp0_property).c_str());
......@@ -111,8 +99,8 @@ namespace TTSP {
}
AnnealingParameterHandler::AnnealingParameterHandler(const AnnealingParameterHandler &other) :
count(other.count), current_value(other.current_value),
parameter(other.parameter), optimization_type(other.optimization_type), temp0(other.temp0), decrement(other.decrement),
count(other.count), value(other.value),
parameter(other.parameter), temp0(other.temp0), decrement(other.decrement),
allow_oscillation(other.allow_oscillation), oscillation_temp(other.oscillation_temp), strict_bound(other.strict_bound),
use_closest(other.use_closest) {}
......@@ -120,10 +108,6 @@ namespace TTSP {
return parameter;
}
AnnealingParameterOptimizationType AnnealingParameterHandler::GetOptimizationType() const {
return optimization_type;
}
double AnnealingParameterHandler::GetTemp0() const {
return temp0;
}
......@@ -185,50 +169,35 @@ namespace TTSP {
next = parameter.GetClosestTo(next);
}
if (optimization_type == EXPONENT) {
return std::pow(10, -next);
} else {
return next;
}
return next;
}
double AnnealingParameterHandler::GetRandom() const {
return random.next();
}
void AnnealingParameterHandler::SetValue(double value) {
current_value = value;
count += 1;
double AnnealingParameterHandler::GetCurrentValue() const {
return value;
}
double AnnealingParameterHandler::GetCurrentValue() const {
return current_value;
void AnnealingParameterHandler::SetValue(double value) {
this->count += 1;
this->value = value;
}
AnnealingOptimizer::AnnealingOptimizer(const OptimizationParameters &space, const OptimizerProperties &properties, std::size_t buffer_capacity) :
OptimizerInterface(space, properties, buffer_capacity), current_handler_index(0), values(space.GetParameterEntries().size()) {
OptimizerInterface(space, properties, buffer_capacity), current_handler_index(0) {
const OptimizationParameterEntries &parameters = space.GetParameterEntries();
handlers.reserve(parameters.size());
std::for_each(parameters.begin(), parameters.end(), [this](const OptimizationParametersEntry &entry) {
std::for_each(parameters.cbegin(), parameters.cend(), [this](const OptimizationParametersEntry &entry) {
handlers.emplace_back(AnnealingParameterHandler(entry.first, *this));
});
std::transform(parameters.begin(), parameters.end(), values.begin(), [](const OptimizationParametersEntry &entry) {
return entry.first.GetDefaultValue();
});
}
OptimizationParametersSuggestion AnnealingOptimizer::Suggest(const std::function<OptimizationFunctionInvokeResult(const OptimizationParameterPoints &,
const OptimizationParameterPoints &,
void *)> &invoke, void *data) const {
OptimizationParameterPoints points(parameters.GetParameterEntries().size());
int i = 0;
std::transform(handlers.begin(), handlers.end(), points.begin(), [this, &i](const AnnealingParameterHandler &h) {
return std::make_pair(h.GetParameter().GetName(), i++ == current_handler_index ? h.GetNextValue() : h.GetCurrentValue());
});
return OptimizationParametersSuggestion(handlers.at(current_handler_index).GetParameter(), parameters.GetPoints(), parameters.GetMetrics(), points);
OptimizationAlgorithmSuggestion AnnealingOptimizer::AlgorithmMakeSuggestion(const std::function<OptimizationFunctionInvokeResult(const OptimizationParameterPoints &,
const OptimizationParameterPoints &,
void *)> &invoke, void *data) const {
return std::make_pair(current_handler_index, handlers.at(current_handler_index).GetNextValue());
}
void AnnealingOptimizer::UpdateSpaceWithLatestResults() {
......@@ -241,7 +210,7 @@ namespace TTSP {
double alpha = h.GetRandom();
if (last.IsGood() && (last.GetMetricsBefore() < 0.0 || ((delta_e < 0.0) || alpha < et))) {
double update_value = last.GetPointsAfter().at(current_handler_index).second;
double update_value = last.GetPointsAfter().at(current_handler_index).GetValue();
h.SetValue(update_value);
parameters.Update(current_handler_index, update_value, last.GetMetricsAfter());
}
......
......@@ -20,34 +20,27 @@ namespace TTSP {
double next();
};
enum AnnealingParameterOptimizationType {
STRICT,
EXPONENT
};
class AnnealingParameterHandler {
private:
static AnnealingParameterOptimizationType DEFAULT_OPTIMIZATION_TYPE;
static double DEFAULT_TEMP0;
static double DEFAULT_DECREMENT;
static bool DEFAULT_ALLOW_OSCILLATION;
static double DEFAULT_OSCILLATION_TEMP;
static bool DEFAULT_STRICT_BOUND;
static bool DEFAULT_USE_CLOSEST;
static double DEFAULT_TEMP0;
static double DEFAULT_DECREMENT;
static bool DEFAULT_ALLOW_OSCILLATION;
static double DEFAULT_OSCILLATION_TEMP;
static bool DEFAULT_STRICT_BOUND;
static bool DEFAULT_USE_CLOSEST;
double value;
std::size_t count;
double current_value;
mutable AnnealingUniformDistribution random;
const OptimizationParameter &parameter;
AnnealingParameterOptimizationType optimization_type;
double temp0;
double decrement;
bool allow_oscillation;
double oscillation_temp;
bool strict_bound;
bool use_closest;
const OptimizationParameter &parameter;
double temp0;
double decrement;
bool allow_oscillation;
double oscillation_temp;
bool strict_bound;
bool use_closest;
public:
explicit AnnealingParameterHandler(const OptimizationParameter &parameter, const OptimizerInterface &optimizer);
......@@ -55,8 +48,6 @@ namespace TTSP {
const OptimizationParameter &GetParameter() const;
AnnealingParameterOptimizationType GetOptimizationType() const;
double GetTemp0() const;
double GetCurrentTemp() const;
......@@ -75,25 +66,25 @@ namespace TTSP {
double GetRandom() const;
void SetValue(double value);
double GetCurrentValue() const;
void SetValue(double v);
};
class AnnealingOptimizer : public OptimizerInterface {
private:
std::size_t current_handler_index;
std::vector<AnnealingParameterHandler> handlers;
std::vector<double> values;
protected:
void UpdateSpaceWithLatestResults() override;
OptimizationAlgorithmSuggestion AlgorithmMakeSuggestion(const std::function<OptimizationFunctionInvokeResult(const OptimizationParameterPoints &,
const OptimizationParameterPoints &,
void *)> &invoke, void *data) const override;
public:
AnnealingOptimizer(const OptimizationParameters &space, const OptimizerProperties &properties, std::size_t buffer_capacity);
OptimizationParametersSuggestion Suggest(const std::function<OptimizationFunctionInvokeResult(const OptimizationParameterPoints &,
const OptimizationParameterPoints &,
void *)> &invoke, void *data) const override;
virtual ~AnnealingOptimizer();
};
......
......@@ -8,45 +8,43 @@ namespace TTSP {
BruteforceOptimizer::BruteforceOptimizer(const OptimizationParameters &space, const OptimizerProperties &properties, std::size_t buffer_capacity) :
OptimizerInterface(space, properties, buffer_capacity) {}
OptimizerInterface(space, properties, buffer_capacity), current_index(0) {}
OptimizationParametersSuggestion BruteforceOptimizer::Suggest(const std::function<OptimizationFunctionInvokeResult(const OptimizationParameterPoints &,
const OptimizationParameterPoints &,
void *)> &invoke, void *data) const {
OptimizationAlgorithmSuggestion BruteforceOptimizer::AlgorithmMakeSuggestion(const std::function<OptimizationFunctionInvokeResult(const OptimizationParameterPoints &,
const OptimizationParameterPoints &,
void *)> &invoke, void *data) const {
const OptimizationParameterPoints &before = parameters.GetPoints();
const OptimizationParameter &parameter = parameters.GetParameter(current_index);
const OptimizationParameterEntries &entries = parameters.GetParameterEntries();
const OptimizationParameterPoints &before = parameters.GetPoints();
double best_metrics = -1.0;
double best_value = 0.0;
OptimizationParameterPoints output(entries.size());
std::for_each(parameter.GetValues().cbegin(), parameter.GetValues().cend(), [&](double value) {
std::cout << "[TTSP] [Bruteforce] Solving with " << parameter.GetName() << " = " << value << "\t\t";
std::transform(entries.begin(), entries.end(), output.begin(), [&](const OptimizationParametersEntry &entry) {
const std::vector<double> &values = entry.first.GetValues();
const OptimizationParameterPoints &after = parameters.GetPointsWithChangedParameter(parameter, value);
double best_metrics = -1.0;
double best_value = 0.0;
OptimizationFunctionInvokeResult result = invoke(before, after, data);
std::for_each(values.begin(), values.end(), [&](double value) {
std::cout << "[TTSP] [Bruteforce] Solving with " << entry.first.GetName() << " = " << value << "\t\t";
bool is_solved = result.first;
double metrics = result.second;
const OptimizationParameterPoints &after = parameters.GetPointsWithChangedParameter(entry.first, value);
if (is_solved && (best_metrics < 0 || metrics < best_metrics)) {
best_metrics = metrics;
best_value = value;
}
OptimizationFunctionInvokeResult result = invoke(before, after, data);
bool is_solved = result.first;
double metrics = result.second;
if (is_solved && (best_metrics < 0 || metrics < best_metrics)) {
best_metrics = metrics;
best_value = value;
}
std::cout << "| Metrics = " << metrics << "\t" << is_solved << std::endl;
});
return std::make_pair(entry.first.GetName(), best_value);