Using global optimizer of dlib c++ instead of bobyqa.

This commit is contained in:
Iason 2021-01-12 14:41:40 +02:00
parent af1fb25766
commit 50c110c08e
4 changed files with 152 additions and 103 deletions

View File

@ -44,6 +44,17 @@ add_compile_definitions(BOBYQA_DEBUG)
add_subdirectory(${BOBYQA_SOURCE_DIR}) add_subdirectory(${BOBYQA_SOURCE_DIR})
message(STATUS "BOBYQA bin dir:${BOBYQA_BINARY_DIR}") message(STATUS "BOBYQA bin dir:${BOBYQA_BINARY_DIR}")
#dlib
download_project(PROJ DLIB
GIT_REPOSITORY https://github.com/davisking/dlib.git
GIT_TAG master
PREFIX ${CMAKE_CURRENT_SOURCE_DIR}/build/external/
${UPDATE_DISCONNECTED_IF_AVAILABLE}
)
add_subdirectory(${DLIB_SOURCE_DIR})
#message(STATUS "BOBYQA bin dir:${BOBYQA_BINARY_DIR}")
##vcglib devel branch ##vcglib devel branch
download_project(PROJ vcglib_devel download_project(PROJ vcglib_devel
GIT_REPOSITORY https://github.com/cnr-isti-vclab/vcglib.git GIT_REPOSITORY https://github.com/cnr-isti-vclab/vcglib.git
@ -78,4 +89,4 @@ else(MSVC)
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_20) target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_20)
endif(MSVC) endif(MSVC)
target_link_libraries(${PROJECT_NAME} polyscope Eigen3::Eigen OpenMP::OpenMP_CXX matplot bobyqa_shared) target_link_libraries(${PROJECT_NAME} polyscope Eigen3::Eigen OpenMP::OpenMP_CXX matplot bobyqa_shared dlib::dlib)

View File

@ -45,7 +45,7 @@ int main(int argc, char *argv[]) {
// SimulationJob job; // SimulationJob job;
// job.load("../" // job.load("../"
// "ProblematicSimulationJobs/12:24_4_1_2021/" // "ProblematicSimulationJobs/17:16_4_1_2021/"
// "reduced_pattern_Single bar reduced model_simScenario.json"); // "reduced_pattern_Single bar reduced model_simScenario.json");
// FormFinder ff; // FormFinder ff;
// ff.executeSimulation(std::make_shared<SimulationJob>(job), false, false, // ff.executeSimulation(std::make_shared<SimulationJob>(job), false, false,
@ -86,27 +86,13 @@ int main(int argc, char *argv[]) {
std::string fullPatternsTestSetDirectory = std::string fullPatternsTestSetDirectory =
// "/home/iason/Models/TestSet_validPatterns"; // "/home/iason/Models/TestSet_validPatterns";
"/home/iason/Documents/PhD/Research/Pattern_enumerator/Results/" "/home/iason/Documents/PhD/Research/Approximating shapes with flat "
"1v_0v_2e_1e_1c_6fan/3/Valid"; "patterns/Pattern_enumerator/Results/1v_0v_2e_1e_1c_6fan/3/Valid";
for (const auto &entry : for (const auto &entry :
filesystem::directory_iterator(fullPatternsTestSetDirectory)) { filesystem::directory_iterator(fullPatternsTestSetDirectory)) {
const auto filepath = const auto filepath =
// std::filesystem::path("/home/iason/Models/valid_6777.ply"); // std::filesystem::path(fullPatternsTestSetDirectory).append("305.ply");
// std::filesystem::path( entry.path();
// "/home/iason/Documents/PhD/Research/Pattern_enumerator/Results/"
// "1v_0v_2e_1e_1c_6fan/3/Valid/222.ply");
std::filesystem::path(
"/home/iason/Documents/PhD/Research/Pattern_enumerator/Results/"
"1v_0v_2e_1e_1c_6fan/3/Valid/624.ply");
// std::filesystem::path(
// "/home/iason/Documents/PhD/Research/Pattern_enumerator/Results/"
// "1v_0v_2e_1e_1c_6fan/2/Valid/33.ply");
// std::filesystem::path(
// "/home/iason/Documents/PhD/Research/Pattern_enumerator/Results/"
// "1v_0v_2e_1e_1c_6fan/3/Valid/431.ply");
// std::filesystem::path(
// "/home/iason/Models/TestSet_validPatterns/59.ply");
// entry.path();
const auto filepathString = filepath.string(); const auto filepathString = filepath.string();
// Use only the base triangle version // Use only the base triangle version
const std::string tiledSuffix = "_tiled.ply"; const std::string tiledSuffix = "_tiled.ply";
@ -114,6 +100,7 @@ int main(int argc, char *argv[]) {
tiledSuffix.size(), tiledSuffix) == 0) { tiledSuffix.size(), tiledSuffix) == 0) {
continue; continue;
} }
std::cout << "Full pattern:" << filepathString << std::endl;
FlatPattern pattern(filepathString); FlatPattern pattern(filepathString);
pattern.setLabel(filepath.stem().string()); pattern.setLabel(filepath.stem().string());
pattern.scale(0.03); pattern.scale(0.03);
@ -130,11 +117,11 @@ int main(int argc, char *argv[]) {
// // first in the reducedModels vector // // first in the reducedModels vector
// optimizationExcludedEi.insert(0); // optimizationExcludedEi.insert(0);
// } // }
std::cout << "Full pattern:" << filepathString << std::endl; // FlatPattern cp;
FlatPattern cp; // cp.copy(*reducedModels[0]);
cp.copy(*reducedModels[0]); optimizer.initializePatterns(pattern, *reducedModels[0],
optimizer.initializePatterns(cp, *reducedModels[0], optimizationExcludedEi); optimizationExcludedEi);
optimizer.optimize({ReducedModelOptimizer::SimulationScenario::Bending}); optimizer.optimize();
// } // }
} }

View File

@ -4,6 +4,9 @@
#include "gradientDescent.h" #include "gradientDescent.h"
#include "simulationhistoryplotter.hpp" #include "simulationhistoryplotter.hpp"
#include "trianglepattterntopology.hpp" #include "trianglepattterntopology.hpp"
#include <chrono>
#include <dlib/global_optimization.h>
#include <dlib/optimization.h>
const bool gShouldDraw = true; const bool gShouldDraw = true;
@ -28,6 +31,8 @@ double g_innerHexagonInitialPos = 0;
bool g_optimizeInnerHexagonSize{false}; bool g_optimizeInnerHexagonSize{false};
std::vector<SimulationResults> firstOptimizationRoundResults; std::vector<SimulationResults> firstOptimizationRoundResults;
int g_firstRoundIterationIndex{0}; int g_firstRoundIterationIndex{0};
double minY{std::numeric_limits<double>::max()};
std::vector<double> minX;
// struct OptimizationCallback { // struct OptimizationCallback {
// double operator()(const size_t &iterations, const Eigen::VectorXd &x, // double operator()(const size_t &iterations, const Eigen::VectorXd &x,
@ -120,6 +125,11 @@ double ReducedModelOptimizer::computeError(
reducedPatternResults.displacements[reducedModelVi][0], reducedPatternResults.displacements[reducedModelVi][0],
reducedPatternResults.displacements[reducedModelVi][1], reducedPatternResults.displacements[reducedModelVi][1],
reducedPatternResults.displacements[reducedModelVi][2]); reducedPatternResults.displacements[reducedModelVi][2]);
if (!std::isfinite(vertexDisplacement[0]) ||
!std::isfinite(vertexDisplacement[1]) ||
!std::isfinite(vertexDisplacement[2])) {
return std::numeric_limits<double>::max();
}
Eigen::Vector3d errorVector = Eigen::Vector3d errorVector =
Eigen::Vector3d( Eigen::Vector3d(
optimalReducedPatternDisplacements.row(reducedModelVi)) - optimalReducedPatternDisplacements.row(reducedModelVi)) -
@ -184,6 +194,12 @@ void updateMesh(long n, const double *x) {
} }
} }
double ReducedModelOptimizer::objective(double x0, double x1, double x2,
double x3) {
std::vector<double> x{x0, x1, x2, x3};
return ReducedModelOptimizer::objective(4, x.data());
}
double ReducedModelOptimizer::objective(long n, const double *x) { double ReducedModelOptimizer::objective(long n, const double *x) {
std::cout.precision(17); std::cout.precision(17);
@ -205,23 +221,29 @@ double ReducedModelOptimizer::objective(long n, const double *x) {
double error = 0; double error = 0;
for (const int simulationScenarioIndex : g_simulationScenarioIndices) { for (const int simulationScenarioIndex : g_simulationScenarioIndices) {
SimulationResults reducedModelResults = simulator.executeSimulation( SimulationResults reducedModelResults = simulator.executeSimulation(
g_reducedPatternSimulationJob[simulationScenarioIndex], false, false); g_reducedPatternSimulationJob[simulationScenarioIndex]);
error += computeError( error += computeError(
reducedModelResults, reducedModelResults,
g_optimalReducedModelDisplacements[simulationScenarioIndex]); g_optimalReducedModelDisplacements[simulationScenarioIndex]);
} }
if (error < minY) {
minY = error;
minX = std::vector<double>({x[0], x[1], x[2], x[3]});
}
// compute error and return it // compute error and return it
gObjectiveValueHistory.push_back(error); gObjectiveValueHistory.push_back(error);
auto xPlot = matplot::linspace(0, gObjectiveValueHistory.size(), // auto xPlot = matplot::linspace(0, gObjectiveValueHistory.size(),
gObjectiveValueHistory.size()); // gObjectiveValueHistory.size());
std::vector<double> colors(gObjectiveValueHistory.size(), 2); // std::vector<double> colors(gObjectiveValueHistory.size(), 2);
if (g_firstRoundIterationIndex != 0) { // if (g_firstRoundIterationIndex != 0) {
for_each(colors.begin() + g_firstRoundIterationIndex, colors.end(), // for_each(colors.begin() + g_firstRoundIterationIndex, colors.end(),
[](double &c) { c = 0.7; }); // [](double &c) { c = 0.7; });
} // }
gPlotHandle = matplot::scatter(xPlot, gObjectiveValueHistory, 6, colors); // gPlotHandle = matplot::scatter(xPlot, gObjectiveValueHistory, 6, colors);
std::cout << std::endl; std::cout << std::endl;
SimulationResultsReporter::createPlot("Number of Steps", "Objective value",
gObjectiveValueHistory);
return error; return error;
} }
@ -503,14 +525,15 @@ Eigen::VectorXd ReducedModelOptimizer::runOptimization(
gObjectiveValueHistory.clear(); gObjectiveValueHistory.clear();
const size_t n = g_optimizeInnerHexagonSize ? 5 : 4; const size_t n = g_optimizeInnerHexagonSize ? 5 : 4;
const size_t npt = 2 * n; // const size_t npt = (n + 1) * (n + 2) / 2;
// ((n + 2) + ((n + 1) * (n + 2) / 2)) / 2; // // ((n + 2) + ((n + 1) * (n + 2) / 2)) / 2;
assert(npt <= (n + 1) * (n + 2) / 2 && npt >= n + 2); // assert(npt <= (n + 1) * (n + 2) / 2 && npt >= n + 2);
assert(npt <= 2 * n + 1 && "The choice of the number of interpolation " // assert(npt <= 2 * n + 1 && "The choice of the number of interpolation "
"conditions is not recommended."); // "conditions is not recommended.");
// Set initial guess of solution // Set initial guess of solution
std::vector<double> x(n, 50); const size_t initialGuess = 1;
std::vector<double> x(n, initialGuess);
if (g_optimizeInnerHexagonSize) { if (g_optimizeInnerHexagonSize) {
x[n - 1] = g_innerHexagonInitialPos; x[n - 1] = g_innerHexagonInitialPos;
} }
@ -523,50 +546,76 @@ Eigen::VectorXd ReducedModelOptimizer::runOptimization(
// {initialGuess(0), initialGuess(1), initialGuess(2), // {initialGuess(0), initialGuess(1), initialGuess(2),
// initialGuess(3)}; // initialGuess(3)};
const double xMin = 1e-2; const double xMin = 1e-2;
const double xMax = 500; const double xMax = 1e2;
// assert(x.end() == find_if(x.begin(), x.end(), [&](const double &d) { // assert(x.end() == find_if(x.begin(), x.end(), [&](const double &d) {
// return d >= xMax || d <= xMin; // return d >= xMax || d <= xMin;
// })); // }));
std::vector<double> xLow(x.size(), xMin); // std::vector<double> xLow(x.size(), xMin);
std::vector<double> xUpper(x.size(), xMax); // std::vector<double> xUpper(x.size(), xMax);
if (g_optimizeInnerHexagonSize) { // if (g_optimizeInnerHexagonSize) {
xLow[n - 1] = 0.1; // xLow[n - 1] = 0.1;
xUpper[n - 1] = 0.9; // xUpper[n - 1] = 0.9;
} // }
const double maxX = *std::max_element( // const double maxX = *std::max_element(
x.begin(), x.end(), // x.begin(), x.end(),
[](const double &a, const double &b) { return abs(a) < abs(b); }); // [](const double &a, const double &b) { return abs(a) < abs(b); });
// const double rhobeg = std::min(0.95, 0.2 * maxX); // const double rhobeg = std::min(0.95, 0.2 * maxX);
const double rhobeg = 1; // double rhobeg = 1;
// const double rhobeg = 10; // double rhoend = rhobeg * 1e-8;
const double rhoend = rhobeg * 1e-6; // const size_t wSize = (npt + 5) * (npt + n) + 3 * n * (n + 5) / 2;
const size_t wSize = (npt + 5) * (npt + n) + 3 * n * (n + 5) / 2; // std::vector<double> w(wSize);
std::vector<double> w(wSize); // const size_t maxFun = std::min(100.0 * (x.size() + 1), 1000.0);
// const size_t maxFun = 10 * (x.size() ^ 2); const size_t maxFun = 150;
const size_t maxFun = 200;
bobyqa(pObjectiveFunction, n, npt, x.data(), xLow.data(), xUpper.data(), double (*objF)(double, double, double, double) = &objective;
rhobeg, rhoend, maxFun, w.data()); auto start = std::chrono::system_clock::now();
std::cout << "Finished first optimization round" << std::endl; dlib::function_evaluation result = dlib::find_min_global(
firstOptimizationRoundResults.resize(6); objF, {xMin, xMin, xMin, xMin}, {xMax, xMax, xMax, xMax},
for (int simulationScenarioIndex = SimulationScenario::Axial; dlib::max_function_calls(maxFun));
simulationScenarioIndex != auto end = std::chrono::system_clock::now();
SimulationScenario::NumberOfSimulationScenarios; auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(end - start);
simulationScenarioIndex++) { std::cout << "Finished optimization with dlib" << endl;
SimulationResults reducedModelResults = simulator.executeSimulation( std::cout << "Solution x:" << endl;
g_reducedPatternSimulationJob[simulationScenarioIndex], false, false); std::cout << result.x << endl;
reducedModelResults.setLabelPrefix("FirstRound"); std::cout << "Solution y:" << endl;
firstOptimizationRoundResults[simulationScenarioIndex] = std::cout << result.y << endl;
std::move(reducedModelResults); std::cout << minY << endl;
} std::cout << "Time(sec):" << elapsed.count() << std::endl;
g_firstRoundIterationIndex = gObjectiveValueHistory.size(); std::cout << "Max function evaluations:" << maxFun << std::endl;
bobyqa(pObjectiveFunction, n, npt, x.data(), xLow.data(), xUpper.data(), std::cout << "[" + std::to_string(xMin) + "," + std::to_string(xMax) + "]"
rhobeg * 1e-3, rhoend, maxFun, w.data()); << std::endl;
std::cout << "Finished second optimization round" << std::endl; std::cout << "Initial guess:" << initialGuess << std::endl;
// const size_t maxFun = 200;
// bobyqa(pObjectiveFunction, n, npt, x.data(), xLow.data(), xUpper.data(),
// rhobeg, rhoend, maxFun, w.data());
// std::cout << "Finished first optimization round" << std::endl;
// firstOptimizationRoundResults.resize(6);
// for (int simulationScenarioIndex = SimulationScenario::Axial;
// simulationScenarioIndex !=
// SimulationScenario::NumberOfSimulationScenarios;
// simulationScenarioIndex++) {
// SimulationResults reducedModelResults = simulator.executeSimulation(
// g_reducedPatternSimulationJob[simulationScenarioIndex], false,
// false);
// reducedModelResults.setLabelPrefix("FirstRound");
// firstOptimizationRoundResults[simulationScenarioIndex] =
// std::move(reducedModelResults);
// }
// g_firstRoundIterationIndex = gObjectiveValueHistory.size();
// rhobeg *= 1e1;
// // rhoend *= 1e2;
// bobyqa(pObjectiveFunction, n, npt, x.data(), xLow.data(), xUpper.data(),
// rhobeg, rhoend, maxFun, w.data());
// std::cout << "Finished second optimization round" << std::endl;
Eigen::VectorXd eigenX(x.size(), 1); Eigen::VectorXd eigenX(x.size(), 1);
for (size_t xi = 0; xi < x.size(); xi++) { for (size_t xi = 0; xi < x.size(); xi++) {
eigenX(xi) = x[xi]; eigenX(xi) = minX[xi];
// eigenX(xi) = x[xi];
// eigenX(xi) = result.x(xi);
} }
// for (size_t xi = 0; xi < x.size(); xi++) {
// }
return eigenX; return eigenX;
} }
@ -815,8 +864,7 @@ void ReducedModelOptimizer::runBeamOptimization() {
fullModelResults.registerForDrawing(); fullModelResults.registerForDrawing();
SimulationResults reducedModelResults = simulator.executeSimulation( SimulationResults reducedModelResults = simulator.executeSimulation(
g_reducedPatternSimulationJob[numberOfSimulationScenarios - 1], false, g_reducedPatternSimulationJob[numberOfSimulationScenarios - 1]);
false);
double error = computeError( double error = computeError(
reducedModelResults, reducedModelResults,
g_optimalReducedModelDisplacements[numberOfSimulationScenarios - 1]); g_optimalReducedModelDisplacements[numberOfSimulationScenarios - 1]);
@ -840,13 +888,13 @@ void ReducedModelOptimizer::visualizeResults(
pFullPatternSimulationJob->registerForDrawing( pFullPatternSimulationJob->registerForDrawing(
m_pFullPatternSimulationMesh->getLabel()); m_pFullPatternSimulationMesh->getLabel());
SimulationResults fullModelResults = SimulationResults fullModelResults =
simulator.executeSimulation(pFullPatternSimulationJob, false); simulator.executeSimulation(pFullPatternSimulationJob);
fullModelResults.registerForDrawing(); fullModelResults.registerForDrawing();
fullModelResults.saveDeformedModel(); fullModelResults.saveDeformedModel();
const std::shared_ptr<SimulationJob> &pReducedPatternSimulationJob = const std::shared_ptr<SimulationJob> &pReducedPatternSimulationJob =
g_reducedPatternSimulationJob[simulationScenarioIndex]; g_reducedPatternSimulationJob[simulationScenarioIndex];
SimulationResults reducedModelResults = SimulationResults reducedModelResults =
simulator.executeSimulation(pReducedPatternSimulationJob, false, false); simulator.executeSimulation(pReducedPatternSimulationJob);
error += computeError( error += computeError(
reducedModelResults, reducedModelResults,
g_optimalReducedModelDisplacements[simulationScenarioIndex]); g_optimalReducedModelDisplacements[simulationScenarioIndex]);
@ -854,39 +902,46 @@ void ReducedModelOptimizer::visualizeResults(
<< simulationScenarioStrings[simulationScenarioIndex] << " is " << simulationScenarioStrings[simulationScenarioIndex] << " is "
<< error << std::endl; << error << std::endl;
reducedModelResults.registerForDrawing(); reducedModelResults.registerForDrawing();
firstOptimizationRoundResults[simulationScenarioIndex].registerForDrawing(); // firstOptimizationRoundResults[simulationScenarioIndex].registerForDrawing();
reducedModelResults.saveDeformedModel(); // reducedModelResults.saveDeformedModel();
// registerWorldAxes(); // registerWorldAxes();
const std::string screenshotFilename =
"/home/iason/Coding/Projects/Approximating shapes with flat "
"patterns/RodModelOptimizationForPatterns/build/OptimizationResults/" +
m_pFullPatternSimulationMesh->getLabel() + "_" +
simulationScenarioStrings[simulationScenarioIndex];
polyscope::show(); polyscope::show();
polyscope::screenshot(screenshotFilename, false);
fullModelResults.unregister(); fullModelResults.unregister();
reducedModelResults.unregister(); reducedModelResults.unregister();
firstOptimizationRoundResults[simulationScenarioIndex].unregister(); // firstOptimizationRoundResults[simulationScenarioIndex].unregister();
} }
} }
void ReducedModelOptimizer::optimize( void ReducedModelOptimizer::optimize(
const std::vector<SimulationScenario> &simulationScenariosIndices) { const std::vector<SimulationScenario> &simulationScenarios) {
g_simulationScenarioIndices = simulationScenarios;
if (g_simulationScenarioIndices.empty()) {
g_simulationScenarioIndices = {
SimulationScenario::Axial, SimulationScenario::Shear,
SimulationScenario::Bending, SimulationScenario::Dome,
SimulationScenario::Saddle};
}
std::vector<std::shared_ptr<SimulationJob>> simulationJobs = std::vector<std::shared_ptr<SimulationJob>> simulationJobs =
createScenarios(m_pFullPatternSimulationMesh); createScenarios(m_pFullPatternSimulationMesh);
g_optimalReducedModelDisplacements.resize(6); g_optimalReducedModelDisplacements.resize(6);
g_reducedPatternSimulationJob.resize(6); g_reducedPatternSimulationJob.resize(6);
g_firstRoundIterationIndex = 0; g_firstRoundIterationIndex = 0;
minY = std::numeric_limits<double>::max();
// polyscope::removeAllStructures(); // polyscope::removeAllStructures();
for (int simulationScenarioIndex = SimulationScenario::Axial; for (int simulationScenarioIndex : g_simulationScenarioIndices) {
simulationScenarioIndex !=
SimulationScenario::NumberOfSimulationScenarios;
simulationScenarioIndex++) {
const std::shared_ptr<SimulationJob> &pFullPatternSimulationJob = const std::shared_ptr<SimulationJob> &pFullPatternSimulationJob =
simulationJobs[simulationScenarioIndex]; simulationJobs[simulationScenarioIndex];
// fullPatternSimulationJob.mesh->savePly(
// "Fanned_" + m_pFullModelSimulationMesh->getLabel() + ".ply");
SimulationResults fullModelResults = SimulationResults fullModelResults =
simulator.executeSimulation(pFullPatternSimulationJob); simulator.executeSimulation(pFullPatternSimulationJob);
// fullModelResults.label =
// "fullModel_" + SimulationScenarioStrings[simulationScenarioIndex];
// fullModelResults.registerForDrawing(fullPatternSimulationJob);
g_optimalReducedModelDisplacements[simulationScenarioIndex].resize( g_optimalReducedModelDisplacements[simulationScenarioIndex].resize(
m_pReducedPatternSimulationMesh->VN(), 3); m_pReducedPatternSimulationMesh->VN(), 3);
computeDesiredReducedModelDisplacements( computeDesiredReducedModelDisplacements(
@ -901,14 +956,7 @@ void ReducedModelOptimizer::optimize(
std::make_shared<SimulationJob>(reducedPatternSimulationJob); std::make_shared<SimulationJob>(reducedPatternSimulationJob);
} }
g_simulationScenarioIndices = simulationScenariosIndices; Eigen::VectorXd optimalParameters = runOptimization(&objective);
if (simulationScenariosIndices.empty()) { updateMesh(4, optimalParameters.data());
g_simulationScenarioIndices = {
SimulationScenario::Axial, SimulationScenario::Shear,
SimulationScenario::Bending, SimulationScenario::Dome,
SimulationScenario::Saddle};
}
runOptimization(&objective);
visualizeResults(simulationJobs, g_simulationScenarioIndices); visualizeResults(simulationJobs, g_simulationScenarioIndices);
} }

View File

@ -32,7 +32,8 @@ public:
}; };
inline static const std::string simulationScenarioStrings[] = { inline static const std::string simulationScenarioStrings[] = {
"Axial", "Shear", "Bending", "Double", "Saddle"}; "Axial", "Shear", "Bending", "Double", "Saddle"};
void optimize(const std::vector<SimulationScenario> &simulationScenarios); void optimize(const std::vector<SimulationScenario> &simulationScenarios =
std::vector<SimulationScenario>());
double operator()(const Eigen::VectorXd &x, Eigen::VectorXd &) const; double operator()(const Eigen::VectorXd &x, Eigen::VectorXd &) const;
ReducedModelOptimizer(const std::vector<size_t> &numberOfNodesPerSlot); ReducedModelOptimizer(const std::vector<size_t> &numberOfNodesPerSlot);
@ -55,6 +56,8 @@ public:
static void runSimulation(const std::string &filename, static void runSimulation(const std::string &filename,
std::vector<double> &x); std::vector<double> &x);
static double objective(double x0, double x1, double x2, double x3);
private: private:
void void
visualizeResults(const std::vector<std::shared_ptr<SimulationJob>> visualizeResults(const std::vector<std::shared_ptr<SimulationJob>>