v0.2.48..v0.2.49 changeset ConflateTestSettingsOptimizer.cpp
Garret Voltz edited this page Oct 2, 2019
·
1 revision
diff --git a/hoot-core-test/src/test/cpp/hoot/core/conflate/optimization/ConflateTestSettingsOptimizer.cpp b/hoot-core-test/src/test/cpp/hoot/core/conflate/optimization/ConflateTestSettingsOptimizer.cpp
new file mode 100644
index 0000000..fbacee8
--- /dev/null
+++ b/hoot-core-test/src/test/cpp/hoot/core/conflate/optimization/ConflateTestSettingsOptimizer.cpp
@@ -0,0 +1,197 @@
+/*
+ * This file is part of Hootenanny.
+ *
+ * Hootenanny is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * --------------------------------------------------------------------
+ *
+ * The following copyright notices are generated automatically. If you
+ * have a new notice to add, please use the format:
+ * " * @copyright Copyright ..."
+ * This will properly maintain the copyright information. DigitalGlobe
+ * copyrights will be updated automatically.
+ *
+ * @copyright Copyright (C) 2017, 2018, 2019 DigitalGlobe (http://www.digitalglobe.com/)
+ */
+#include "ConflateTestSettingsOptimizer.h"
+
+// Hoot
+#include <hoot/core/util/ConfigOptions.h>
+#include <hoot/core/util/FileUtils.h>
+#include <hoot/core/util/Log.h>
+#include <hoot/core/util/HootException.h>
+#include <hoot/core/conflate/optimization/AbstractRegressionTestFitnessFunction.h>
+
+// Qt
+#include <QTextStream>
+
+// Tgs
+#include <tgs/Optimization/SimulatedAnnealing.h>
+
+// Boost
+#include <boost/property_tree/json_parser.hpp>
+#include <boost/foreach.hpp>
+
+// Standard
+#include <float.h>
+
+namespace hoot
+{
+
+ConflateTestSettingsOptimizer::ConflateTestSettingsOptimizer(bool verbose) :
+_verbose(verbose)
+{
+}
+
+Tgs::StateDescriptionPtr ConflateTestSettingsOptimizer::_initStateDescription(const QString& testSettingsFile)
+{
+ LOG_VARD(testSettingsFile);
+
+ boost::property_tree::ptree propTree;
+ try
+ {
+ boost::property_tree::read_json(testSettingsFile.toStdString(), propTree);
+ }
+ catch (boost::property_tree::json_parser::json_parser_error& e)
+ {
+ throw HootException(
+ QString("Error parsing JSON: %1 (line %2)")
+ .arg(QString::fromStdString(e.message()))
+ .arg(QString::number(e.line())));
+ }
+ catch (const std::exception& e)
+ {
+ const QString reason = e.what();
+ throw HootException("Error parsing JSON " + reason);
+ }
+
+ Tgs::StateDescriptionPtr stateDescription(new Tgs::StateDescription());
+ for (boost::property_tree::ptree::value_type& setting : propTree.get_child("settings"))
+ {
+ const QString settingName = QString::fromStdString(setting.second.get<std::string>("name", ""));
+ LOG_VART(settingName);
+ if (!conf().hasKey(settingName))
+ {
+ throw HootException("Invalid setting: " + settingName);
+ }
+ Tgs::ConstVariableDescriptionPtr var(
+ new Tgs::VariableDescription(
+ settingName,
+ Tgs::VariableDescription::Real,
+ setting.second.get<double>("min", DBL_MIN),
+ setting.second.get<double>("max", DBL_MAX)));
+ LOG_VART(var->toString());
+ stateDescription->addVariable(var);
+ }
+
+ return stateDescription;
+}
+
+void ConflateTestSettingsOptimizer::runOptimization(std::shared_ptr<AbstractTestFitnessFunction> fitnessFunction, const int numIterations,
+ const QString& testSettingsFile, const QString& outputFile)
+{
+ Tgs::SimulatedAnnealing sa(_initStateDescription(testSettingsFile), fitnessFunction);
+ sa.setPickFromBestScores(true);
+ sa.setVerbose(_verbose);
+ /*bestScore =*/ sa.iterate(numIterations);
+ _writeOutput(fitnessFunction, sa.getBestStates(), numIterations, outputFile);
+}
+
+void ConflateTestSettingsOptimizer::_writeOutput(const std::shared_ptr<AbstractTestFitnessFunction>& fitnessFunction,
+ const QSet<Tgs::ConstStatePtr>& bestStates, const int numIterations, const QString& outputFile)
+{
+ QString output =
+ "Results for Conflicts Network Matcher Configuration Option Optimization with Simulated Annealing\n\n";
+
+ QString temp = "Number of test iterations: " + QString::number(numIterations);
+ LOG_INFO(temp);
+ output += temp + "\n\n";
+
+ temp = "Number of tests in test suite: " + QString::number(fitnessFunction->getTestCount());
+ LOG_INFO(temp);
+ output += temp + "\n\n";
+
+ temp =
+ "Lowest number of test failures in test iteration: " +
+ QString::number(fitnessFunction->getLowestNumFailingTestsPerRun());
+ LOG_INFO(temp);
+ output += temp + "\n\n";
+
+ temp = "Number of best states found: " + QString::number(bestStates.size());
+ LOG_INFO(temp);
+ output += temp + "\n\n";
+
+ std::shared_ptr<AbstractRegressionTestFitnessFunction> regressionTestFitnessFunction =
+ std::dynamic_pointer_cast<AbstractRegressionTestFitnessFunction>(fitnessFunction);
+ if (regressionTestFitnessFunction)
+ {
+ temp = regressionTestFitnessFunction->bestScoresPerTestToString();
+ LOG_INFO(temp);
+ output += temp + "\n\n";
+ }
+
+ if (fitnessFunction->getLowestNumFailingTestsPerRun() == 0)
+ {
+ temp = "***YOU FOUND A SOLUTION! :-)***";
+ }
+ else
+ {
+ temp = "No solution was found. :-(";
+ }
+ LOG_INFO(temp);
+ output += temp + "\n\n";
+
+ LOG_INFO("Writing best states and failing test groups to: " << outputFile << "...");
+ const QStringList failingTestsForBestRuns = fitnessFunction->getFailingTestsForBestRuns();
+ output +=
+ "Failing Test Groups For Best States (" + QString::number(failingTestsForBestRuns.size()) +
+ "):\n\n";
+ if (failingTestsForBestRuns.size() == 0)
+ {
+ output += "no failing test groups\n\n";
+ }
+ else
+ {
+ for (int i = 0; i < failingTestsForBestRuns.size(); i++)
+ {
+ output += "#" + QString::number(i + 1) + ":\n\n";
+ QString failingTestsStr = failingTestsForBestRuns.at(i);
+ if (failingTestsStr.contains(";"))
+ {
+ QStringList failingTests = failingTestsStr.split(";");
+ for (int j = 0; j < failingTests.size(); j++)
+ {
+ output += failingTests.at(j) + "\n";
+ }
+ }
+ else
+ {
+ output += failingTestsStr + "\n";
+ }
+ output += "\n";
+ }
+ }
+ output += "Best States (" + QString::number(bestStates.size()) + "):\n\n";
+ int statesCtr = 1;
+ foreach (Tgs::ConstStatePtr state, bestStates)
+ {
+ output += "#" + QString::number(statesCtr) + ":\n\n";
+ output += state->toString() + "\n\n";
+ statesCtr++;
+ }
+ LOG_VARD(QDir::currentPath());
+ FileUtils::writeFully(outputFile, output);
+}
+
+}