Commit 00460ae8 authored by Dmitry Bagaev's avatar Dmitry Bagaev
Browse files

update ttsp configuration reader

parent 6f354eeb
......@@ -8,6 +8,7 @@
#include <inmost_optimizer.h>
#include "series.h"
#include <Source/Misc/utils.h>
#include <Source/Solver/ttsp/ttsp_configuration.h>
using namespace INMOST;
......@@ -34,7 +35,6 @@ int main(int argc, char **argv) {
std::string databaseFilePath = "";
std::string parametersFilePath = "";
std::string solverName = "fcbiilu2";
std::string optimizerType = "bruteforce";
bool seriesFound = false;
bool parametersFound = false;
......@@ -59,7 +59,6 @@ int main(int argc, char **argv) {
std::cout << "-b, --bvector <RHS vector file name>" << std::endl;
std::cout << "-d, --database <Solver parameters file name>" << std::endl;
std::cout << "-t, --type <Solver type name>" << std::endl;
std::cout << "-o, --optt <Optimizer type name>" << std::endl;
std::cout << "-w, --wait " << std::endl;
std::cout << " Available solvers:" << std::endl;
Solver::Initialize(NULL, NULL, NULL);
......@@ -141,15 +140,6 @@ int main(int argc, char **argv) {
i++;
continue;
}
//Optimizer type found with -o ot --optt options
if (strcmp(argv[i], "-o") == 0 || strcmp(argv[i], "--optt") == 0) {
if (rank == 0) {
std::cout << "Optimizer type index found: " << argv[i + 1] << std::endl;
}
optimizerType = std::string(argv[i + 1]);
i++;
continue;
}
//Wait for each iteration
if (strcmp(argv[i], "-w") == 0 || strcmp(argv[i], "--wait") == 0) {
waitNext = true;
......@@ -200,36 +190,10 @@ int main(int argc, char **argv) {
if (rank == 0) std::cout << "Solving with " << solverName << std::endl;
if (!INMOST::Optimizers::IsOptimizerAvailable(optimizerType)) {
if (rank == 0) {
std::cout << "Optimizer " << optimizerType << " not found" << std::endl;
std::cout << " Available optimizers:" << std::endl;
std::vector<std::string> availableOptimizers = INMOST::Optimizers::GetAvailableOptimizers();
for (auto it = availableOptimizers.begin(); it != availableOptimizers.end(); ++it) {
std::cout << " " << *it << std::endl;
}
}
std::exit(0);
}
INMOST::OptimizersConfiguration::FromFile(parametersFilePath);
INMOST::OptimizerProperties properties;
properties["tau:use_closest"] = "false";
properties["tau:strict_bound"] = "false";
properties["eps:use_closest"] = "false";
properties["eps:strict_bound"] = "false";
INMOST::TTSP::Initialize(parametersFilePath);
INMOST::TTSP::Enable(solver.SolverName(), solver.SolverPrefix());
INMOST::Optimizers::SaveOptimizerOrReplace("test", optimizerType, properties, 9);
INMOST::OptimizerInterface *topt = INMOST::Optimizers::GetSavedOptimizer("test");
topt->SetVerbosityLevel(INMOST::OptimizerVerbosityLevel::Level1);
topt->SetRestartStrategy(INMOST::OptimizerRestartStrategy::RESTART_STRATEGY_WITH_BEST, 7);
double metrics_total = 0.0;
double total_time = 0.0;
while (!series.end()) {
......@@ -256,44 +220,23 @@ int main(int argc, char **argv) {
for (int k = mbeg; k < mend; ++k) rhs[k] = 1.0;
}
auto invoke = [&solver, &matrix, &rhs, &x](const INMOST::OptimizationParameterPoints &before, const INMOST::OptimizationParameterPoints &after,
void *data) -> INMOST::OptimizationFunctionInvokeResult {
std::for_each(after.begin(), after.end(), [&solver](const INMOST::OptimizationParameterPoint &point) {
solver.SetParameter(point.GetName(), INMOST::to_string(point.GetValue()));
});
INMOST::Sparse::Vector SOL("SOL", rhs.GetFirstIndex(), rhs.GetLastIndex());
std::fill(SOL.Begin(), SOL.End(), 0.0);
INMOST::MPIBarrier();
INMOST::TTSP::SolverOptimize(solver);
double tmp_time = Timer();
solver.SetMatrix(matrix);
bool is_solved = solver.Solve(rhs, SOL);
INMOST::MPIBarrier();
INMOST::Sparse::Vector SOL("SOL", rhs.GetFirstIndex(), rhs.GetLastIndex());
std::fill(SOL.Begin(), SOL.End(), 0.0);
double time = Timer() - tmp_time;
std::for_each(before.begin(), before.end(), [&solver](const INMOST::OptimizationParameterPoint &point) {
solver.SetParameter(point.GetName(), INMOST::to_string(point.GetValue()));
});
return std::make_pair(is_solved, time);
};
INMOST::OptimizerInterface *optimizer = INMOST::Optimizers::GetSavedOptimizer("test");
const INMOST::OptimizationParametersSuggestion &suggestion = optimizer->Suggest();
INMOST::MPIBarrier();
const INMOST::OptimizationFunctionInvokeResult &result = invoke(suggestion.GetPointsBefore(), suggestion.GetPointsAfter(), nullptr);
double tmp_time = Timer();
solver.SetMatrix(matrix);
bool is_solved = solver.Solve(rhs, SOL);
INMOST::MPIBarrier();
bool is_good = result.first;
double metrics = result.second;
double time = Timer() - tmp_time;
metrics_total += metrics;
total_time += time;
optimizer->SaveResult(suggestion, metrics, is_good);
INMOST::TTSP::SolverOptimizeSaveResult(solver, time, is_solved);
if (rank == 0 && waitNext) {
std::cin.get();
......@@ -302,7 +245,7 @@ int main(int argc, char **argv) {
INMOST::MPIBarrier();
}
std::cout << "Metrics total from " << series.size() << " iterations: " << metrics_total << " (mean = " << metrics_total / series.size() << ")" << std::endl;
std::cout << "Metrics total from " << series.size() << " iterations: " << total_time << " (mean = " << total_time / series.size() << ")" << std::endl;
}
Solver::Finalize(); // Finalize solver and close MPI activity
......
<SolverOptimization>
<parameter ref="tau" name="tau" from="-3.0" to="-0.9" step="0.1" type="log10" initial="-2" />
<parameter ref="q" name="q" initial="0">
<value>0</value>
<value>1</value>
<value>2</value>
<value>3</value>
</parameter>
<fcbiilu2 enabled="true">
<test optimizer="alternating" enabled="true" verbosity="3" buffer="15">
<parameter ref="tau" />
<parameter ref="q" />
</test>
</fcbiilu2>
</SolverOptimization>
\ No newline at end of file
......@@ -461,19 +461,21 @@ namespace INMOST {
/// Helper functions for Optimizer module and Solver
namespace TTSP {
void Enable(const std::string &name, const std::string &type = "alternating");
void Initialize(const std::string &path);
void Disable(const std::string &name);
void Enable(const std::string &solver_name, const std::string &solver_prefix);
bool isEnabled(const std::string &name);
void Disable(const std::string &solver_name, const std::string &solver_prefix);
bool isDisabled(const std::string &name);
bool isEnabled(const std::string &solver_name, const std::string &solver_prefix);
void SolverOptimize(const std::string &name, Solver &solver, bool use_last_suggestion = false);
bool isDisabled(const std::string &solver_name, const std::string &solver_prefix);
void SolverOptimizeSaveResult(const std::string &name, double metrics, bool is_good);
void SolverOptimize(Solver &solver, bool use_last_suggestion = false);
void DestroySavedOptimizer(const std::string &name);
void SolverOptimizeSaveResult(Solver &solver, double metrics, bool is_good);
void DestroySavedOptimizer(Solver &solver);
}
......
set(SOURCE ${SOURCE} ${CMAKE_CURRENT_SOURCE_DIR}/ttsp.cpp)
set(HEADER ${HEADER}
${CMAKE_CURRENT_SOURCE_DIR}/ttsp_configuration.h)
set(SOURCE ${SOURCE}
${CMAKE_CURRENT_SOURCE_DIR}/ttsp.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ttsp_configuration.cpp)
set(HEADER ${HEADER} PARENT_SCOPE)
set(SOURCE ${SOURCE} PARENT_SCOPE)
\ No newline at end of file
......@@ -2,49 +2,66 @@
#include "inmost_solver.h"
#include "inmost_optimizer.h"
#include "../../Misc/utils.h"
#include "ttsp_configuration.h"
namespace INMOST {
namespace TTSP {
#if defined(USE_OPTIMIZER)
struct TTSPParameters {
bool disabled;
std::string type;
// TODO add array of specific parameters here, like tau and so on
struct TTSPOptions {
bool enabled;
};
static std::map<std::string, TTSPParameters> g_parameters = std::map<std::string, TTSPParameters>();
static std::map<std::string, INMOST::OptimizerInterface *> g_optimizers = std::map<std::string, INMOST::OptimizerInterface *>();
static TTSPConfiguration *configuration = nullptr;
static std::map<std::string, TTSPOptions> g_options = std::map<std::string, TTSPOptions>();
static std::map<std::string, INMOST::OptimizerInterface *> g_optimizers = std::map<std::string, INMOST::OptimizerInterface *>();
#endif
void Enable(const std::string &name, const std::string &type) {
void Initialize(const std::string &path) {
#if defined(USE_OPTIMIZER)
if (g_parameters.find(name) == g_parameters.end()) {
TTSPParameters p;
p.disabled = false;
p.type = type;
if (INMOST::TTSP::configuration != nullptr) {
delete INMOST::TTSP::configuration;
}
INMOST::TTSP::configuration = new TTSPConfiguration(path);
std::for_each(INMOST::TTSP::configuration->GetSolvers().cbegin(), INMOST::TTSP::configuration->GetSolvers().cend(), [](const TTSPConfigurationSolverEntry &s) {
if (s.IsEnabled()) {
std::for_each(s.GetPrefixes().cbegin(), s.GetPrefixes().cend(), [&s](const TTSPConfigurationSolverPrefixEntry &p) {
if (p.IsEnabled()) {
Enable(s.GetSolver(), p.GetPrefix());
}
});
}
});
#endif
}
g_parameters[name] = p;
void Enable(const std::string &solver_name, const std::string &solver_prefix) {
#if defined(USE_OPTIMIZER)
const std::string &key = solver_name + ":" + solver_prefix;
if (g_options.find(key) == g_options.end()) {
g_options[key] = {.enabled = true};
} else {
g_parameters[name].disabled = false;
g_options[key].enabled = true;
}
#endif
}
void Disable(const std::string &name, const std::string &type) {
void Disable(const std::string &solver_name, const std::string &solver_prefix) {
#if defined(USE_OPTIMIZER)
if (g_parameters.find(name) != g_parameters.end()) {
g_parameters[name].disabled = true;
const std::string &key = solver_name + ":" + solver_prefix;
if (g_options.find(key) != g_options.end()) {
g_options[key].enabled = false;
}
#endif
}
bool isEnabled(const std::string &name) {
bool isEnabled(const std::string &solver_name, const std::string &solver_prefix) {
#if defined(USE_OPTIMIZER)
if (g_parameters.find(name) != g_parameters.end()) {
return !g_parameters[name].disabled;
const std::string &key = solver_name + ":" + solver_prefix;
if (g_options.find(key) != g_options.end()) {
return g_options[key].enabled;
} else {
return false;
}
......@@ -53,10 +70,11 @@ namespace INMOST {
#endif
}
bool isDisabled(const std::string &name) {
bool isDisabled(const std::string &solver_name, const std::string &solver_prefix) {
#if defined(USE_OPTIMIZER)
if (g_parameters.find(name) != g_parameters.end()) {
return g_parameters[name].disabled;
const std::string &key = solver_name + ":" + solver_prefix;
if (g_options.find(key) != g_options.end()) {
return !g_options[key].enabled;
} else {
return true;
}
......@@ -67,67 +85,72 @@ namespace INMOST {
#if defined(USE_OPTIMIZER)
OptimizerInterface *GetOrCreateOptimizer(const std::string &name) {
OptimizerInterface *GetOrCreateOptimizer(Solver &solver) {
OptimizerInterface *optimizer = nullptr;
const std::string &key = solver.SolverName() + ":" + solver.SolverPrefix();
if (g_optimizers.find(key) == g_optimizers.end()) {
if (g_optimizers.find(name) == g_optimizers.end()) {
// TODO Here parameters for fcbiilu2 only
OptimizationParameter tau("tau", std::make_pair(-3, -1.0), 0.05, -2.0, OptimizationParameterType::PARAMETER_TYPE_EXPONENT);
OptimizationParameterEntries entries;
entries.emplace_back(std::make_pair(tau, tau.GetDefaultValue()));
OptimizerProperties properties;
properties["tau:use_closest"] = "false";
properties["tau:strict_bound"] = "false";
const TTSPConfigurationSolverPrefixEntry &entry = INMOST::TTSP::configuration->FindForSolverAndPrefix(solver.SolverName(), solver.SolverPrefix());
std::cout << "gere" << std::endl;
std::for_each(entry.GetParameters().cbegin(), entry.GetParameters().cend(), [&entries](const TTSPConfigurationParameterEntry &e) {
OptimizationParameter o(e.GetName(), e.GetValues(), e.GetInitial(), e.GetParameterType());
entries.emplace_back(std::make_pair(o, o.GetDefaultValue()));
});
OptimizationParameters optparams(entries, -1.0);
optimizer = Optimizers::GetOptimizer(name, g_parameters[name].type, optparams, properties, 15);
OptimizerProperties properties;
optimizer = Optimizers::GetOptimizer(key, entry.GetOptimizer(), optparams, properties, 15);
optimizer->SetVerbosityLevel(OptimizerVerbosityLevel::Level3);
optimizer->SetRestartStrategy(OptimizerRestartStrategy::RESTART_STRATEGY_WITH_BEST, 15);
g_optimizers[name] = optimizer;
g_optimizers[key] = optimizer;
} else {
optimizer = g_optimizers[name];
optimizer = g_optimizers[key];
}
return optimizer;
}
#endif
void SolverOptimize(const std::string &name, Solver &solver, bool use_last_suggestion) {
void SolverOptimize(Solver &solver, bool use_last_suggestion) {
#if defined(USE_OPTIMIZER)
if (isEnabled(name)) {
OptimizerInterface *optimizer = GetOrCreateOptimizer(name);
if (isEnabled(solver.SolverName(), solver.SolverPrefix())) {
OptimizerInterface *optimizer = GetOrCreateOptimizer(solver);
const OptimizationParametersSuggestion &suggestion = use_last_suggestion ? optimizer->GetLastSuggestion() : optimizer->Suggest();
if (optimizer != nullptr) {
const OptimizationParametersSuggestion &suggestion = use_last_suggestion ? optimizer->GetLastSuggestion() : optimizer->Suggest();
std::for_each(suggestion.GetPointsAfter().begin(), suggestion.GetPointsAfter().end(), [&solver](const OptimizationParameterPoint &point) {
solver.SetParameter(point.GetName(), INMOST::to_string(point.GetValue()));
});
std::for_each(suggestion.GetPointsAfter().begin(), suggestion.GetPointsAfter().end(), [&solver](const OptimizationParameterPoint &point) {
solver.SetParameter(point.GetName(), INMOST::to_string(point.GetValue()));
});
}
}
#endif
}
void SolverOptimizeSaveResult(const std::string &name, double metrics, bool is_good) {
void SolverOptimizeSaveResult(Solver &solver, double metrics, bool is_good) {
#if defined(USE_OPTIMIZER)
if (isEnabled(name)) {
OptimizerInterface *optimizer = GetOrCreateOptimizer(name);
auto last_suggestion = optimizer->GetLastSuggestion();
optimizer->SaveResult(last_suggestion, metrics, is_good);
if (isEnabled(solver.SolverName(), solver.SolverPrefix())) {
OptimizerInterface *optimizer = GetOrCreateOptimizer(solver);
if (optimizer != nullptr) {
auto last_suggestion = optimizer->GetLastSuggestion();
optimizer->SaveResult(last_suggestion, metrics, is_good);
}
}
#endif
}
void DestroySavedOptimizer(const std::string &name) {
void DestroySavedOptimizer(Solver &solver) {
#if defined(USE_OPTIMIZER)
if (g_optimizers.find(name) != g_optimizers.end()) {
delete g_optimizers[name];
g_optimizers.erase(name);
const std::string &key = solver.SolverName() + ":" + solver.SolverPrefix();
if (g_optimizers.find(key) != g_optimizers.end()) {
delete g_optimizers[key];
g_optimizers.erase(key);
}
#endif
}
......
//
// Created by Dmitri Bagaev on 2019-07-09.
//
#include <Source/Misc/utils.h>
#include "ttsp_configuration.h"
namespace INMOST {
namespace TTSP {
void TTSPConfigurationParameterEntry::swap(INMOST::TTSP::TTSPConfigurationParameterEntry &left, INMOST::TTSP::TTSPConfigurationParameterEntry &right) {
std::swap(left.ref, right.ref);
std::swap(left.name, right.name);
std::swap(left.initial, right.initial);
std::swap(left.values, right.values);
std::swap(left.type, right.type);
}
TTSPConfigurationParameterEntry::TTSPConfigurationParameterEntry(const TTSPConfigurationParameterEntry &other) :
ref(other.ref), name(other.name), initial(other.initial), values(other.values),
type(other.type) {
}
TTSPConfigurationParameterEntry::TTSPConfigurationParameterEntry(TTSPConfigurationParameterEntry &&other) noexcept {
TTSPConfigurationParameterEntry::swap(*this, other);
}
TTSPConfigurationParameterEntry &TTSPConfigurationParameterEntry::operator=(const TTSPConfigurationParameterEntry &other) {
TTSPConfigurationParameterEntry tmp(other);
TTSPConfigurationParameterEntry::swap(*this, tmp);
return *this;
}
TTSPConfigurationParameterEntry::TTSPConfigurationParameterEntry(const XMLReader::XMLTree &entry) {
int num_attrib = entry.NumAttrib();
int namei = entry.FindAttrib("name");
if (namei == num_attrib) {
throw "Bad parameter in XML solver optimization configuration file: Missing 'name' property!";
}
int initiali = entry.FindAttrib("initial");
if (initiali == num_attrib) {
throw "Bad parameter in XML solver optimization configuration file: Missing 'initial' property!";
}
this->name = entry.GetAttrib(namei).value;
this->initial = atof(entry.GetAttrib(initiali).value.c_str());
int refi = entry.FindAttrib("ref");
if (refi != num_attrib) {
this->ref = entry.GetAttrib(refi).value;
}
int typei = entry.FindAttrib("type");
if (typei != num_attrib) {
this->type = (entry.GetAttrib(typei).value == "log10" ? OptimizationParameterType::PARAMETER_TYPE_EXPONENT
: OptimizationParameterType::PARAMETER_TYPE_DEFAULT);
} else {
this->type = OptimizationParameterType::PARAMETER_TYPE_DEFAULT;
}
if (entry.children.size() != 0) {
for (std::vector<const XMLReader::XMLTree>::iterator value = entry.children.begin(); value != entry.children.end(); ++value) {
if ((*value).tag.name == "value") {
this->values.push_back(atof((*value).contents.c_str()));
} else {
throw "Bad parameter in XML solver optimization configuration file: Missing 'value' tag!";
}
}
} else {
double from = 0.0;
double to = 0.0;
double step = 0.0;
int fromi = entry.FindAttrib("from");
if (fromi != num_attrib) {
from = atof(entry.GetAttrib(fromi).value.c_str());
}
int toi = entry.FindAttrib("to");
if (toi != num_attrib) {
to = atof(entry.GetAttrib(toi).value.c_str());
}
int stepi = entry.FindAttrib("step");
if (stepi != num_attrib) {
step = atof(entry.GetAttrib(stepi).value.c_str());
}
if (from >= to) {
throw "Bad parameter in XML solver optimization configuration file: Invalid 'from' and 'to' properties!";
} else if (step <= 0) {
throw "Bad parameter in XML solver optimization configuration file: Invalid 'step' property!";
} else {
double v = from;
while (v <= to) {
this->values.push_back(v);
v += step;
}
}
}
}
TTSPConfigurationParameterEntry::~TTSPConfigurationParameterEntry() {}
std::ostream &operator<<(std::ostream &out, const TTSPConfigurationParameterEntry &c) {
out << " -------------------------------" << std::endl;
out << " name: " << c.name << std::endl;
out << " ref: " << c.ref << std::endl;
out << " type: " << (c.type == OptimizationParameterType::PARAMETER_TYPE_EXPONENT ? "log10" : "default") << std::endl;
out << " initial: " << c.initial << std::endl;
out << " values: " << "[";
std::for_each(c.values.cbegin(), c.values.cend(), [&out](double v) {
out << v << ",";
});
out << "]" << std::endl;
return out;
}
const std::string &TTSPConfigurationParameterEntry::GetRef() const noexcept {
return ref;
}
const std::string &TTSPConfigurationParameterEntry::GetName() const noexcept {
return name;
}
double TTSPConfigurationParameterEntry::GetInitial() const noexcept {
return initial;
}
const std::vector<double> &TTSPConfigurationParameterEntry::GetValues() const noexcept {
return values;
}
OptimizationParameterType TTSPConfigurationParameterEntry::GetParameterType() const noexcept {
return type;
}
void TTSPConfigurationSolverPrefixEntry::swap(TTSPConfigurationSolverPrefixEntry &left, TTSPConfigurationSolverPrefixEntry &right) {
std::swap(left.enabled, right.enabled);
std::swap(left.prefix, right.prefix);
std::swap(left.optimizer, right.optimizer);
std::swap(left.verbosity, right.verbosity);
std::swap(left.buffer_capacity, right.buffer_capacity);
std::swap(left.parameters, right.parameters);
}
TTSPConfigurationSolverPrefixEntry::TTSPConfigurationSolverPrefixEntry(const TTSPConfigurationSolverPrefixEntry &other) :
enabled(other.enabled), prefix(other.prefix), optimizer(other.optimizer), parameters(other.parameters) {}
TTSPConfigurationSolverPrefixEntry::TTSPConfigurationSolverPrefixEntry(TTSPConfigurationSolverPrefixEntry &&other) noexcept {
TTSPConfigurationSolverPrefixEntry::swap(*this, other);
}
TTSPConfigurationSolverPrefixEntry &TTSPConfigurationSolverPrefixEntry::operator=(const TTSPConfigurationSolverPrefixEntry &other) {
TTSPConfigurationSolverPrefixEntry tmp(other);
TTSPConfigurationSolverPrefixEntry::swap(*this, tmp);
return *this;
}
TTSPConfigurationSolverPrefixEntry::TTSPConfigurationSolverPrefixEntry(const XMLReader::XMLTree &entry, const std::vector<TTSPConfigurationParameterEntry> &global) {
this->prefix = entry.tag.name;
int num_attr = entry.NumAttrib();
int optimizeri = entry.FindAttrib("optimizer");
if (optimizeri != num_attr) {
this->optimizer = entry.GetAttrib(optimizeri).value;
} else {
throw "Bad parameter in XML solver optimization configuration file: Missing 'optimizer' property in prefix configuration!";
}