Commit 6516342d authored by Dmitry Bagaev's avatar Dmitry Bagaev
Browse files

WIP: Update optimizer logic

parent 779bebd3
......@@ -5,8 +5,7 @@
#include <cmath>
#include <cstdio>
#include "Source/Solver/ttsp/optimization_parameters.h"
#include "Source/Solver/ttsp/optimizer_interface.h"
#include "Source/Solver/ttsp/ttsp.h"
#include "Source/Solver/ttsp/optimizers/bruteforce/ttsp_bruteforce.h"
using namespace INMOST;
......@@ -176,10 +175,7 @@ int main(int argc, char **argv) {
if (rank == 0) std::cout << "Load vector time: " << Timer() - timer << std::endl;
TTSP::OptimizationParameter tau("tau", { 1e-4, 3e-4, 5e-4, 7e-4,
1e-3, 3e-3, 5e-3, 7e-3,
1e-2, 3e-2, 5e-2, 7e-2,
1e-1, 3e-1, 5e-1, 7e-1 }, 1e-3);
TTSP::OptimizationParameter tau("tau", {1e-3, 3e-3, 5e-3, 7e-3, 1e-2, 3e-2, 5e-2, 7e-2}, 1e-3);
TTSP::OptimizationParameters parameters;
......@@ -188,32 +184,55 @@ int main(int argc, char **argv) {
TTSP::OptimizationParametersSpace space(solverName, "test", parameters);
TTSP::BruteforceOptimizer optimizer(space);
// BARRIER;
// timer = Timer();
// solver.SetMatrix(mat); // Compute the preconditioner for the original matrix
// BARRIER;
//
// if (rank == 0) std::cout << "Preconditioner time: " << Timer() - timer << std::endl;
//
// BARRIER;
// timer = Timer();
// bool isSuccess = solver.Solve(b, x); // Solve the linear system with the previously computted preconditioner
// BARRIER;
optimizer.Solve(solver, mat, b, x);
std::cout << "Best optimization parameters found for current iteration:" << std::endl;
const TTSP::OptimizationParameterPoints &best = optimizer.GetParametersCurrentValues();
std::for_each(best.begin(), best.end(), [](const TTSP::OptimizationParameterPoint &p) {
std::cout << "\t" << p.first << " = " << p.second << std::endl;
});
if (rank == 0) {
std::cout << "Solved with " << solver.SolverName()
<< " on " << solver.Iterations()
<< " iterations and " << solver.Residual()
<< " residual. Reason: " << solver.ReturnReason()
<< std::endl;
// BARRIER;
// timer = Timer();
// solver.SetMatrix(mat); // Compute the preconditioner for the original matrix
// BARRIER;
//
// if (rank == 0) std::cout << "Preconditioner time: " << Timer() - timer << std::endl;
//
// BARRIER;
// timer = Timer();
// bool isSuccess = solver.Solve(b, x); // Solve the linear system with the previously computted preconditioner
// BARRIER;
int test = 0;
while (test < 15) {
optimizer.Solve(solver, mat, b, x);
std::cout << std::endl << "Best optimization parameters found for current iteration:" << std::endl;
const TTSP::OptimizationParameterPoints &best = optimizer.GetSpace().GetPoints();
std::for_each(best.begin(), best.end(), [](const TTSP::OptimizationParameterPoint &p) {
std::cout << "\t" << p.first << " = " << p.second << std::endl;
});
std::cout << std::endl << "Optimization results buffer output:" << std::endl;
const TTSP::OptimizationParameterResultsBuffer &results = optimizer.GetResults();
int index = 1;
std::for_each(results.begin(), results.end(), [&index](const TTSP::OptimizationParameterResult &result) {
std::cout << "\t" << index++ << "\t" << " [";
const TTSP::OptimizationParameterPoints &points = result.GetPoints();
std::for_each(points.begin(), points.end(), [](const TTSP::OptimizationParameterPoint &point) {
std::cout << " " << point.first << "=" << point.second << " ";
});
std::cout << "] " << result.GetPreconditionerTime() << "\t" << result.GetSolveTime() << "\t" << result.GetTime() << std::endl;
});
if (rank == 0) {
std::cout << std::endl
<< "Solved with " << solver.SolverName()
<< " on " << solver.Iterations()
<< " iterations and " << solver.Residual()
<< " residual. Reason: " << solver.ReturnReason()
<< std::endl;
}
test += 1;
}
}
......
......@@ -29,4 +29,10 @@ namespace INMOST {
return lower;
}
void MPIBarrier() {
#if defined(USE_MPI)
MPI_Barrier(MPI_COMM_WORLD);
#endif
}
}
......@@ -27,8 +27,7 @@ namespace INMOST
std::string string_to_lower(const std::string &str);
void MPIBarrier();
class BinaryHeap
{
......
set(SOURCE ${SOURCE}
${CMAKE_CURRENT_SOURCE_DIR}/optimization_parameters.cpp)
${CMAKE_CURRENT_SOURCE_DIR}/ttsp.cpp)
set(HEADER ${HEADER}
${CMAKE_CURRENT_SOURCE_DIR}/optimizer_interface.h
${CMAKE_CURRENT_SOURCE_DIR}/optimization_parameters.h)
${CMAKE_CURRENT_SOURCE_DIR}/ttsp.h)
add_subdirectory(optimizers)
......
//
// Created by bvdmitri on 31.01.19.
//
#ifndef INMOST_OPTIMIZATION_PARAMETERS_H
#define INMOST_OPTIMIZATION_PARAMETERS_H
#include <string>
#include <vector>
namespace TTSP {
typedef std::pair<double, double> OptimizationParameterRange;
typedef std::pair<std::string, double> OptimizationParameterPoint;
typedef std::vector<OptimizationParameterPoint> OptimizationParameterPoints;
class OptimizationParameter {
private:
std::string name;
std::vector<double> values;
double default_value;
static void swap(OptimizationParameter &left, OptimizationParameter &right);
public:
OptimizationParameter(const std::string &name, const OptimizationParameterRange &range,
double step, double default_value);
OptimizationParameter(const std::string &name, const std::vector<double> &values, double default_value);
OptimizationParameter(const OptimizationParameter &other);
OptimizationParameter(OptimizationParameter &&other) noexcept;
OptimizationParameter &operator=(const OptimizationParameter &other);
const std::string &GetName() const;
const std::vector<double> &GetValues() const;
const double &GetDefaultValue() const;
};
typedef std::pair<OptimizationParameter, double> OptimizationParametersEntry;
typedef std::vector<OptimizationParametersEntry> OptimizationParameters;
class OptimizationParametersSpace {
private:
std::string solver_name;
std::string solver_prefix;
OptimizationParameters parameters;
static void swap(OptimizationParametersSpace &left, OptimizationParametersSpace &right);
public:
OptimizationParametersSpace(const std::string &solver_name, const std::string &solver_prefix,
const OptimizationParameters &parameters);
OptimizationParametersSpace(const OptimizationParametersSpace &other);
OptimizationParametersSpace(OptimizationParametersSpace &&other) noexcept;
OptimizationParametersSpace &operator=(const OptimizationParametersSpace &other);
bool isSolverNameMatch(const std::string &solver_name) const;
bool isSolverPrefixMatch(const std::string &solver_prefix) const;
const std::string &GetSolverName() const;
const std::string &GetSolverPrefix() const;
const OptimizationParameters &GetParameters() const;
const OptimizationParameterPoints GetPoints() const;
void Update(const OptimizationParameterPoints &update);
};
}
#endif //INMOST_OPTIMIZATION_PARAMETERS_H
//
// Created by bvdmitri on 31.01.19.
//
#ifndef INMOST_OPTIMIZER_INTERFACE_H
#define INMOST_OPTIMIZER_INTERFACE_H
#include <inmost_solver.h>
#include <cstdint>
#include "optimization_parameters.h"
#include "../../Misc/utils.h"
namespace TTSP {
class OptimizerInterface {
protected:
OptimizationParametersSpace space;
void TimeBarrier() const {
#if defined(USE_MPI)
MPI_Barrier(MPI_COMM_WORLD);
#endif
};
public:
OptimizerInterface(const OptimizationParametersSpace &space) : space(space) {};
void Solve(INMOST::Solver &solver, INMOST::Sparse::Matrix &matrix,
INMOST::Sparse::Vector &RHS, INMOST::Sparse::Vector &SOL) {
const OptimizationParameterPoints &current = this->GetParametersCurrentValues();
std::for_each(current.begin(), current.end(), [&solver](const OptimizationParameterPoint &p) {
solver.SetParameter(p.first, INMOST::to_string(p.second));
});
const OptimizationParameterPoints &update = this->RequestNewParameters(current, solver, matrix, RHS, SOL);
space.Update(update);
};
virtual OptimizationParameterPoints RequestNewParameters(
const OptimizationParameterPoints &current,
INMOST::Solver &solver, INMOST::Sparse::Matrix &matrix,
INMOST::Sparse::Vector &RHS, INMOST::Sparse::Vector &SOL) const = 0;
const OptimizationParameterPoints GetParametersCurrentValues() const {
return space.GetPoints();
}
virtual ~OptimizerInterface() {};
};
}
#endif // INMOST_OPTIMIZER_INTERFACE_H
\ No newline at end of file
......@@ -6,65 +6,58 @@
namespace TTSP {
BruteforceOptimizer::BruteforceOptimizer(const OptimizationParametersSpace &parameters) :
OptimizerInterface(parameters) {}
BruteforceOptimizer::BruteforceOptimizer(const OptimizationParametersSpace &space) : OptimizerInterface(space, 10) {}
BruteforceOptimizer::~BruteforceOptimizer() {}
OptimizationParameterPoints BruteforceOptimizer::RequestNewParameters(const OptimizationParameterPoints &current,
INMOST::Solver &solver,
INMOST::Sparse::Matrix &matrix,
INMOST::Sparse::Vector &RHS,
INMOST::Sparse::Vector &SOL) const {
OptimizationParameterPoints BruteforceOptimizer::MakeOptimizationIteration(INMOST::Solver &solver, INMOST::Sparse::Matrix &matrix,
INMOST::Sparse::Vector &RHS) const {
const OptimizationParameters &parameters = space.GetParameters();
OptimizationParameterPoints best(parameters.size());
OptimizationParameterPoints output(parameters.size());
std::transform(parameters.begin(), parameters.end(), best.begin(), [&](const OptimizationParametersEntry &p) {
const std::vector<double> &values = p.first.GetValues();
double timer = 0.0;
double best_time = -1.0;
std::transform(parameters.begin(), parameters.end(), output.begin(), [&](const OptimizationParametersEntry &entry) {
const std::vector<double> &values = entry.first.GetValues();
double tmp_time = 0.0;
double best_time = -1.0;
double best_value = 0.0;
std::for_each(values.begin(), values.end(), [&](double value) {
std::cout << "[TTSP] [Bruteforce] Solving with " << p.first.GetName() << " = " << value << "\t\t";
std::cout << "[TTSP] [Bruteforce] Solving with " << entry.first.GetName() << " = " << value << "\t\t";
solver.SetParameter(p.first.GetName(), INMOST::to_string(value));
solver.SetParameter(entry.first.GetName(), INMOST::to_string(value));
INMOST::Sparse::Vector RHSCopy(RHS);
INMOST::Sparse::Vector SOLCopy(SOL);
INMOST::Sparse::Vector SOL("SOL", RHS.GetFirstIndex(), RHS.GetLastIndex());
std::fill(SOL.Begin(), SOL.End(), 0.0);
TimeBarrier();
timer = Timer();
INMOST::MPIBarrier();
tmp_time = Timer();
solver.SetMatrix(matrix);
bool isSolved = solver.Solve(RHSCopy, SOLCopy);
TimeBarrier();
bool is_solved = solver.Solve(RHS, SOL);
INMOST::MPIBarrier();
double time = Timer() - timer;
double time = Timer() - tmp_time;
if (isSolved && (best_time < 0 || time < best_time)) {
if (is_solved && (best_time < 0 || time < best_time)) {
best_time = time;
best_value = value;
}
std::cout << "| Time = " << time << "\t" << isSolved << std::endl;
solver.SetParameter(p.first.GetName(), INMOST::to_string(best_value));
std::cout << "| Time = " << time << "\t" << is_solved << std::endl;
});
return std::make_pair(p.first.GetName(), best_value);
});
solver.SetParameter(entry.first.GetName(), INMOST::to_string(best_value));
std::for_each(current.begin(), current.end(), [&solver](const OptimizationParameterPoint &point) {
solver.SetParameter(point.first, INMOST::to_string(point.second));
return std::make_pair(entry.first.GetName(), best_value);
});
solver.SetMatrix(matrix);
solver.Solve(RHS, SOL);
return output;
}
BruteforceOptimizer::~BruteforceOptimizer() {
return best;
}
}
\ No newline at end of file
......@@ -5,18 +5,16 @@
#ifndef INMOST_TTSP_BRUTEFORCE_H
#define INMOST_TTSP_BRUTEFORCE_H
#include <Source/Solver/ttsp/optimizer_interface.h>
#include <Source/Solver/ttsp/ttsp.h>
namespace TTSP {
class BruteforceOptimizer : public OptimizerInterface {
public:
BruteforceOptimizer(const OptimizationParametersSpace &parameters);
BruteforceOptimizer(const OptimizationParametersSpace &space);
OptimizationParameterPoints RequestNewParameters(const OptimizationParameterPoints &current,
INMOST::Solver &solver, INMOST::Sparse::Matrix &matrix,
INMOST::Sparse::Vector &RHS,
INMOST::Sparse::Vector &SOL) const override;
OptimizationParameterPoints MakeOptimizationIteration(INMOST::Solver &solver, INMOST::Sparse::Matrix &matrix,
INMOST::Sparse::Vector &RHS) const override;
virtual ~BruteforceOptimizer();
};
......
//
// Created by bvdmitri on 31.01.19.
// Created by bvdmitri on 04.02.19.
//
#include "optimization_parameters.h"
#include <algorithm>
#include "ttsp.h"
namespace TTSP {
......@@ -115,6 +113,128 @@ namespace TTSP {
parameters[i].second = update[i].second;
}
}
}
void OptimizationParameterResult::swap(OptimizationParameterResult &left, OptimizationParameterResult &right) {
std::swap(left.points, right.points);
std::swap(left.preconditioner_time, right.preconditioner_time);
std::swap(left.solve_time, right.solve_time);
std::swap(left.is_solved, right.is_solved);
}
OptimizationParameterResult::OptimizationParameterResult(const OptimizationParameterPoints &points,
double preconditioner_time, double solve_time, bool is_solved) :
points(points), preconditioner_time(preconditioner_time), solve_time(solve_time), is_solved(is_solved) {}
OptimizationParameterResult::OptimizationParameterResult(const OptimizationParameterResult &other) :
points(other.points), preconditioner_time(other.preconditioner_time), solve_time(other.solve_time), is_solved(other.is_solved) {}
OptimizationParameterResult::OptimizationParameterResult(OptimizationParameterResult &&other) noexcept {
OptimizationParameterResult::swap(*this, other);
}
OptimizationParameterResult &OptimizationParameterResult::operator=(const OptimizationParameterResult &other) {
OptimizationParameterResult tmp(other);
OptimizationParameterResult::swap(*this, tmp);
return *this;
}
const OptimizationParameterPoints &OptimizationParameterResult::GetPoints() const {
return points;
}
const double &OptimizationParameterResult::GetPreconditionerTime() const {
return preconditioner_time;
}
const double &OptimizationParameterResult::GetSolveTime() const {
return solve_time;
}
double OptimizationParameterResult::GetTime() const {
return preconditioner_time + solve_time;
}
bool OptimizationParameterResult::IsSolved() const {
return is_solved;
}
void OptimizationParameterResultsBuffer::swap(OptimizationParameterResultsBuffer &left,
OptimizationParameterResultsBuffer &right) {
std::swap(left.buffer, right.buffer);
std::swap(left.capacity, right.capacity);
}
OptimizationParameterResultsBuffer::OptimizationParameterResultsBuffer(std::size_t capacity) : capacity(capacity) {}
OptimizationParameterResultsBuffer::OptimizationParameterResultsBuffer(const OptimizationParameterResultsBuffer &other) :
buffer(other.buffer), capacity(other.capacity) {}
OptimizationParameterResultsBuffer::OptimizationParameterResultsBuffer(OptimizationParameterResultsBuffer &&other) noexcept {
OptimizationParameterResultsBuffer::swap(*this, other);
}
OptimizationParameterResultsBuffer &OptimizationParameterResultsBuffer::operator=(const OptimizationParameterResultsBuffer &other) {
OptimizationParameterResultsBuffer tmp(other);
OptimizationParameterResultsBuffer::swap(*this, tmp);
return *this;
}
std::deque<OptimizationParameterResult>::const_reverse_iterator OptimizationParameterResultsBuffer::begin() const {
return buffer.crbegin();
}
std::deque<OptimizationParameterResult>::const_reverse_iterator OptimizationParameterResultsBuffer::end() const {
return buffer.crend();
}
void OptimizationParameterResultsBuffer::push(const OptimizationParameterResult &result) {
if (buffer.size() == capacity) {
buffer.pop_front();
}
buffer.push_back(result);
}
std::size_t OptimizationParameterResultsBuffer::size() const {
return buffer.size();
}
bool OptimizerInterface::Solve(INMOST::Solver &solver, INMOST::Sparse::Matrix &matrix, INMOST::Sparse::Vector &RHS, INMOST::Sparse::Vector &SOL,
GetPreconditionerTimeFromSolverLambda preconditioner_time, GetSolveTimeFromSolverLambda solve_time) {
const OptimizationParameterPoints &current = space.GetPoints();
std::for_each(current.begin(), current.end(), [&solver](const OptimizationParameterPoint &p) {
solver.SetParameter(p.first, INMOST::to_string(p.second));
});
solver.SetMatrix(matrix);
bool solved = solver.Solve(RHS, SOL);
SaveResult(current, solver, solved, preconditioner_time, solve_time);
const OptimizationParameterPoints &update = this->MakeOptimizationIteration(solver, matrix, RHS);
space.Update(update);
return solved;
}
void OptimizerInterface::SaveResult(const OptimizationParameterPoints &points, const INMOST::Solver &solver, bool is_solved,
GetPreconditionerTimeFromSolverLambda preconditioner_time, GetSolveTimeFromSolverLambda solve_time) {
results.push(OptimizationParameterResult(points, preconditioner_time(solver), solve_time(solver), is_solved));
}
const OptimizationParametersSpace &OptimizerInterface::GetSpace() const {
return space;
}
const OptimizationParameterResultsBuffer &OptimizerInterface::GetResults() const {
return results;
};
double OptimizerInterface::DefaultGetPreconditionerTime(const INMOST::Solver &solver) {
return atof(solver.GetParameter("time_prec").c_str());
}
double OptimizerInterface::DefaultGetSolveTime(const INMOST::Solver &solver) {
return atof(solver.GetParameter("time_iter").c_str());
}
}
//
// Created by bvdmitri on 04.02.19.
//
#ifndef INMOST_TTSP_H
#define INMOST_TTSP_H
#include <vector>
#include <algorithm>
#include <string>
#include <deque>
#include <inmost_solver.h>
#include <Source/Misc/utils.h>
namespace TTSP {
/// This class is used to define a range of possible values for some parameter
/// Usage: OptimizationParameterRange range = std::make_pair(0.0, 1.0)
typedef std::pair<double, double> OptimizationParameterRange;
/// 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
static void swap(OptimizationParameter &left, OptimizationParameter &right);
public:
/// Default constructor to define an OptimizationParameter with range of possible values and associated step
/// @param name - Name of a parameter
/// @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);
/// 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);
/// Copy constructor
/// @param other - OptimizationParameter to make copy of
OptimizationParameter(const OptimizationParameter &other);
/// Move constructor
/// @param other - OptimizationParameter to swap with
OptimizationParameter(OptimizationParameter &&other) noexcept;
/// Assignment operator
/// @param other - OptimizationParameter to assign
OptimizationParameter &operator=(const OptimizationParameter &other);
/// Getter for name of a parameter
const std::string &GetName() const;
/// Getter for values of a parameter
const std::vector<double> &GetValues() const;
/// Getter for default_value of a parameter