main optimizes a pair of patterns of which the filepath is given as cl arguments. The user can additionally define the number of function calls and the directory in which the program should export the results.

This commit is contained in:
Iason 2021-02-18 15:33:31 +02:00
parent ae645b27d2
commit 9a225439cf
2 changed files with 99 additions and 247 deletions

View File

@ -16,245 +16,61 @@
#include <string>
#include <vcg/complex/algorithms/update/position.h>
void exportOptimizationResults(
const ReducedModelOptimizer::Results &optimizationResults,
const std::filesystem::path &optimizationDirectory,
const ReducedModelOptimizer::Settings &settings_optimization,
csvFile &statistics,
const std::pair<FlatPattern *, FlatPattern *> patternPair) {
std::filesystem::path saveToPath(std::filesystem::path(optimizationDirectory)
.append(patternPair.first->getLabel() +
"@" +
patternPair.second->getLabel()));
std::filesystem::create_directories(std::filesystem::path(saveToPath));
optimizationResults.save(saveToPath.string());
statistics << patternPair.first->getLabel() + "@" +
patternPair.second->getLabel();
statistics << optimizationResults.objectiveValue;
for (const double &optimalX : optimizationResults.x) {
statistics << optimalX;
}
for (int unusedXVarCounter = 0;
unusedXVarCounter <
settings_optimization.xRanges.size() - optimizationResults.x.size();
unusedXVarCounter++) {
statistics << "-";
}
statistics << optimizationResults.time;
if (optimizationResults.numberOfSimulationCrashes == 0) {
statistics << "No crashes";
} else {
statistics << optimizationResults.numberOfSimulationCrashes;
}
statistics << endrow;
}
void optimizeTestSet(
const std::vector<std::pair<FlatPattern *, FlatPattern *>> patternPairs,
const ReducedModelOptimizer::Settings &settings_optimization,
const std::string &saveTo) {
const std::string optimizationSettingsString =
settings_optimization.toString();
std::filesystem::path thisOptimizationDirectory(
std::filesystem::path(saveTo).append(optimizationSettingsString));
//.append("Results"));
std::filesystem::create_directories(thisOptimizationDirectory);
std::cout << optimizationSettingsString << std::endl;
csvFile csv_settings(std::filesystem::path(thisOptimizationDirectory)
.append("settings.csv")
.string(),
true);
settings_optimization.writeTo(csv_settings);
csvFile statistics(std::filesystem::path(thisOptimizationDirectory)
.append("statistics.csv")
.string(),
false);
// Write header to csv
statistics << "FullPattern@ReducedPattern"
<< "Obj value";
for (const ReducedModelOptimizer::xRange &range :
settings_optimization.xRanges) {
statistics << range.label;
}
statistics << "Time(s)";
statistics << "#Crashes";
statistics << endrow;
double totalError = 0;
int totalNumberOfSimulationCrashes = 0;
std::vector<ReducedModelOptimizer::Results> optimizationResults_testSet(
patternPairs.size());
auto start = std::chrono::high_resolution_clock::now();
int pairsOptimized = 0;
#pragma omp parallel for
for (int patternPairIndex = 0; patternPairIndex < patternPairs.size();
patternPairIndex++) {
const std::pair<FlatPattern *, FlatPattern *> &patternPair =
patternPairs[patternPairIndex];
std::cout << "Optimizing " << patternPair.first->getLabel() << "@"
<< patternPair.second->getLabel() << std::endl;
const std::vector<size_t> numberOfNodesPerSlot{1, 0, 0, 2, 1, 2, 1};
ReducedModelOptimizer optimizer(numberOfNodesPerSlot);
optimizer.initializePatterns(*patternPair.first, *patternPair.second, {});
ReducedModelOptimizer::Results optimizationResults =
optimizer.optimize(settings_optimization);
totalError += optimizationResults.objectiveValue;
optimizationResults_testSet[patternPairIndex] = optimizationResults;
totalNumberOfSimulationCrashes +=
optimizationResults.numberOfSimulationCrashes;
std::cout << "Optimized " << ++pairsOptimized << "/" << patternPairs.size()
<< std::endl;
#pragma omp critical
{
exportOptimizationResults(optimizationResults, thisOptimizationDirectory,
settings_optimization, statistics, patternPair);
optimizationResults.draw();
}
}
// for (int patternPairIndex = 0; patternPairIndex < patternPairs.size();
// patternPairIndex++) {
// const std::pair<FlatPattern *, FlatPattern *> &patternPair =
// patternPairs[patternPairIndex];
// const ReducedModelOptimizer::Results optimizationResults =
// optimizationResults_testSet[patternPairIndex];
// // Save results
// std::filesystem::path saveToPath(
// std::filesystem::path(thisOptimizationDirectory)
// .append(patternPair.first->getLabel() + "@" +
// patternPair.second->getLabel()));
// std::filesystem::create_directories(std::filesystem::path(saveToPath));
// optimizationResults.save(saveToPath.string());
// // Save statistics
// statistics << patternPair.first->getLabel() + "@" +
// patternPair.second->getLabel();
// statistics << optimizationResults.objectiveValue;
// for (const double &optimalX : optimizationResults.x) {
// statistics << optimalX;
// }
// for (int unusedXVarCounter = 0;
// unusedXVarCounter <
// settings_optimization.xRanges.size() -
// optimizationResults.x.size(); unusedXVarCounter++) {
// statistics << "-";
// }
// statistics << optimizationResults.time;
// if (optimizationResults.numberOfSimulationCrashes == 0) {
// statistics << "No crashes";
// } else {
// statistics << optimizationResults.numberOfSimulationCrashes;
// }
// statistics << endrow;
// }
}
int main(int argc, char *argv[]) {
// Create reduced models
// FormFinder::runUnitTests();
const std::vector<size_t> numberOfNodesPerSlot{1, 0, 0, 2, 1, 2, 1};
std::vector<vcg::Point2i> singleBarReducedModelEdges{vcg::Point2i(0, 3)};
FlatPattern singleBarReducedModel(numberOfNodesPerSlot,
singleBarReducedModelEdges);
singleBarReducedModel.setLabel("SingleBar_reduced");
singleBarReducedModel.savePly(singleBarReducedModel.getLabel());
singleBarReducedModel.scale(0.03);
if (argc < 4) {
std::cerr << "Specify the pattern pair to be optimized." << std::endl;
std::terminate();
}
// Populate the pattern pair to be optimized
////Full pattern
const std::string filepath_fullPattern = argv[1];
FlatPattern fullPattern(filepath_fullPattern);
fullPattern.setLabel(
std::filesystem::path(filepath_fullPattern).stem().string());
fullPattern.scale(0.03);
////Reduced pattern
const std::string filepath_reducedPattern = argv[2];
FlatPattern reducedPattern(filepath_reducedPattern);
reducedPattern.setLabel(
std::filesystem::path(filepath_reducedPattern).stem().string());
reducedPattern.scale(0.03);
std::vector<vcg::Point2i> CWreducedModelEdges{vcg::Point2i(1, 5),
vcg::Point2i(3, 5)};
FlatPattern CWReducedModel(numberOfNodesPerSlot, CWreducedModelEdges);
CWReducedModel.setLabel("CW_reduced");
CWReducedModel.scale(0.03);
std::vector<vcg::Point2i> CCWreducedModelEdges{vcg::Point2i(1, 5),
vcg::Point2i(3, 1)};
FlatPattern CCWReducedModel(numberOfNodesPerSlot, CCWreducedModelEdges);
CCWReducedModel.setLabel("CCW_reduced");
CCWReducedModel.savePly(CWReducedModel.getLabel());
CCWReducedModel.scale(0.03);
std::vector<FlatPattern *> reducedModels{&singleBarReducedModel,
&CWReducedModel, &CCWReducedModel};
// Define the ranges that the optimizer will use
// Set the optization settings
ReducedModelOptimizer::xRange beamWidth{"B", 0.5, 1.5};
ReducedModelOptimizer::xRange beamDimensionsRatio{"bOverh", 0.7, 1.3};
ReducedModelOptimizer::xRange beamE{"E", 0.1, 1.9};
ReducedModelOptimizer::xRange innerHexagonSize{"HS", 0.1, 0.9};
// Test set of full patterns
std::string fullPatternsTestSetDirectory = "../TestSet";
if (!std::filesystem::exists(
std::filesystem::path(fullPatternsTestSetDirectory))) {
std::cerr << "Full pattern directory does not exist: "
<< fullPatternsTestSetDirectory << std::endl;
return 1;
}
// "/home/iason/Documents/PhD/Research/Approximating shapes with flat "
// "patterns/Pattern_enumerator/Results/1v_0v_2e_1e_1c_6fan/3/Valid";
std::vector<std::pair<FlatPattern *, FlatPattern *>> patternPairs;
for (const auto &entry :
filesystem::directory_iterator(fullPatternsTestSetDirectory)) {
const auto filepath =
// std::filesystem::path(fullPatternsTestSetDirectory).append("305.ply");
entry.path();
const std::string filepathString = filepath.string();
const std::string tiledSuffix = "_tiled.ply";
if (filepathString.compare(filepathString.size() - tiledSuffix.size(),
tiledSuffix.size(), tiledSuffix) == 0) {
continue;
}
FlatPattern fullPattern(filepathString);
fullPattern.setLabel(filepath.stem().string());
fullPattern.scale(0.03);
// for (int reducedPatternIndex = 0;
// reducedPatternIndex < reducedModels.size();
// reducedPatternIndex++) {
FlatPattern *pFullPattern = new FlatPattern();
pFullPattern->copy(fullPattern);
FlatPattern *pReducedPattern = new FlatPattern();
// pReducedPattern->copy(*reducedModels[reducedPatternIndex]);
pReducedPattern->copy(*reducedModels[0]);
patternPairs.push_back(std::make_pair(pFullPattern, pReducedPattern));
// }
}
// for (double rangeOffset = 0.15; rangeOffset <= 0.95; rangeOffset += 0.05)
// {
ReducedModelOptimizer::Settings settings_optimization;
settings_optimization.xRanges = {beamWidth, beamDimensionsRatio, beamE,
innerHexagonSize};
const bool input_numberOfFunctionCallsDefined = argc >= 4;
settings_optimization.numberOfFunctionCalls =
input_numberOfFunctionCallsDefined ? std::atoi(argv[3]) : 100;
// Optimize pair
const std::string pairName =
fullPattern.getLabel() + "@" + reducedPattern.getLabel();
std::cout << "Optimizing " << pairName << std::endl;
const std::vector<size_t> numberOfNodesPerSlot{1, 0, 0, 2, 1, 2, 1};
ReducedModelOptimizer optimizer(numberOfNodesPerSlot);
optimizer.initializePatterns(fullPattern, reducedPattern, {});
ReducedModelOptimizer::Results optimizationResults =
optimizer.optimize(settings_optimization);
// Export results
const bool input_resultDirectoryDefined = argc >= 5;
std::string optimiziationResultsDirectory =
input_resultDirectoryDefined ? argv[4] : "OptimizationResults";
std::filesystem::path dirPath_thisOptimization(
std::filesystem::path(optimiziationResultsDirectory).append(pairName));
std::filesystem::create_directories(dirPath_thisOptimization);
csvFile csv_results(std::filesystem::path(dirPath_thisOptimization)
.append("results.csv")
.string(),
false);
settings_optimization.writeTo(csv_results);
optimizationResults.writeTo(settings_optimization, csv_results);
optimizationResults.save(dirPath_thisOptimization.string());
// for (settings_optimization.numberOfFunctionCalls = 100;
// settings_optimization.numberOfFunctionCalls < 5000;
// settings_optimization.numberOfFunctionCalls += 100) {
std::string optimiziationResultsDirectory = "OptimizationResults";
if (argc < 2) {
settings_optimization.numberOfFunctionCalls = 100;
} else if (argc == 2) {
settings_optimization.numberOfFunctionCalls = std::atoi(argv[1]);
} else if (argc == 3) {
settings_optimization.numberOfFunctionCalls = std::atoi(argv[1]);
optimiziationResultsDirectory = argv[2];
}
// settings_optimization.normalizeObjectiveValue = false;
// optimizeTestSet(patternPairs, settings_optimization,
// optimiziationResultsDirectory);
settings_optimization.normalizeObjectiveValue = true;
optimizeTestSet(patternPairs, settings_optimization,
optimiziationResultsDirectory);
// optimizationResults.draw();
for (auto &patternPair : patternPairs) {
delete patternPair.first;
delete patternPair.second;
}
return 0;
}

View File

@ -47,7 +47,7 @@ public:
std::vector<xRange> xRanges;
int numberOfFunctionCalls{100};
double solutionAccuracy{1e-2};
bool normalizeObjectiveValue{ true };
bool normalizeObjectiveValue{true};
std::string toString() const {
std::string settingsString;
@ -59,23 +59,25 @@ public:
settingsString += xRangesString;
}
settingsString += "FuncCalls=" + std::to_string(numberOfFunctionCalls) +
" Accuracy=" + std::to_string(solutionAccuracy)+" Norm="+(normalizeObjectiveValue ? "yes" : "no");
" Accuracy=" + std::to_string(solutionAccuracy) +
" Norm=" + (normalizeObjectiveValue ? "yes" : "no");
return settingsString;
}
void writeTo(csvFile &csv) const {
void writeTo(csvFile &csv, const bool writeHeader = true) const {
// Create settings csv header
if (!xRanges.empty()) {
for (const xRange &range : xRanges) {
csv << range.label + " max";
csv << range.label + " min";
if (writeHeader) {
if (!xRanges.empty()) {
for (const xRange &range : xRanges) {
csv << range.label + " max";
csv << range.label + " min";
}
}
csv << "Function Calls";
csv << "Solution Accuracy";
csv << endrow;
}
csv << "Function Calls";
csv << "Solution Accuracy";
csv << "Normalize obj value";
csv << endrow;
if (!xRanges.empty()) {
for (const xRange &range : xRanges) {
@ -85,7 +87,6 @@ public:
}
csv << numberOfFunctionCalls;
csv << solutionAccuracy;
csv <<(normalizeObjectiveValue ? "yes" : "no");
csv << endrow;
}
};
@ -149,7 +150,8 @@ public:
&reducedToFullInterfaceViMap);
static double computeError(const std::vector<Vector6d> &reducedPatternResults,
const std::vector<Vector6d> &fullPatternResults,const double& interfaceDisplacementNormSum,
const std::vector<Vector6d> &fullPatternResults,
const double &interfaceDisplacementNormSum,
const std::unordered_map<ReducedPatternVertexIndex,
FullPatternVertexIndex>
&reducedToFullInterfaceViMap);
@ -250,10 +252,9 @@ struct ReducedModelOptimizer::Results {
const std::shared_ptr<SimulationJob> &pReducedPatternSimulationJob =
reducedPatternSimulationJobs[simulationJobIndex];
const auto reducedPatternDirectoryPath =
std::filesystem::path(simulationJobFolderPath)
.append("Reduced");
std::filesystem::path(simulationJobFolderPath).append("Reduced");
if (!std::filesystem::exists(reducedPatternDirectoryPath)) {
std::filesystem::create_directory(reducedPatternDirectoryPath);
std::filesystem::create_directory(reducedPatternDirectoryPath);
}
pReducedPatternSimulationJob->save(reducedPatternDirectoryPath.string());
}
@ -264,10 +265,12 @@ struct ReducedModelOptimizer::Results {
for (const auto &directoryEntry :
filesystem::directory_iterator(loadFromPath)) {
const auto simulationScenarioPath = directoryEntry.path();
if (!std::filesystem::is_directory(simulationScenarioPath)) {
continue;
}
// Load reduced pattern files
for (const auto &fileEntry : filesystem::directory_iterator(
std::filesystem::path(simulationScenarioPath)
.append("Full"))) {
std::filesystem::path(simulationScenarioPath).append("Full"))) {
const auto filepath = fileEntry.path();
if (filepath.extension() == ".json") {
SimulationJob job;
@ -291,6 +294,39 @@ struct ReducedModelOptimizer::Results {
}
}
}
void writeTo(const ReducedModelOptimizer::Settings &settings_optimization,
csvFile &csv, const bool writeHeader = true) const {
if (writeHeader) {
//// Write header to csv
csv << "Obj value";
for (const ReducedModelOptimizer::xRange &range :
settings_optimization.xRanges) {
csv << range.label;
}
csv << "Time(s)";
csv << "#Crashes";
csv << endrow;
}
csv << objectiveValue;
for (const double &optimalX : x) {
csv << optimalX;
}
for (int unusedXVarCounter = 0;
unusedXVarCounter < settings_optimization.xRanges.size() - x.size();
unusedXVarCounter++) {
csv << "-";
}
csv << time;
if (numberOfSimulationCrashes == 0) {
csv << "No crashes";
} else {
csv << numberOfSimulationCrashes;
}
csv << endrow;
}
};
#endif // REDUCEDMODELOPTIMIZER_HPP