-
Mikhail Svechnikov authoredMikhail Svechnikov authored
MinimizerSettingsWidget.cpp 11.74 KiB
// ************************************************************************************************
//
// BornAgain: simulate and fit reflection and scattering
//
//! @file GUI/View/Fit/MinimizerSettingsWidget.cpp
//! @brief Implements class MinimizerSettingsWidget
//!
//! @homepage http://www.bornagainproject.org
//! @license GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2018
//! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
// ************************************************************************************************
#include "GUI/View/Fit/MinimizerSettingsWidget.h"
#include "GUI/Model/Job/FitSuiteItem.h"
#include "GUI/Model/Job/JobItem.h"
#include "GUI/Model/Job/MinimizerItem.h"
#include "GUI/View/Common/DoubleSpinBox.h"
#include "GUI/View/Common/SafeSpinBox.h"
#include "GUI/View/Tool/LayoutUtils.h"
#include "GUI/View/Tool/WidgetUtils.h"
#include <QComboBox>
#include <QFormLayout>
#include <QPushButton>
#include <QVBoxLayout>
MinimizerSettingsWidget::MinimizerSettingsWidget(QWidget* parent)
: QWidget(parent)
, m_currentItem(nullptr)
{
setWindowTitle(QLatin1String("Minimizer Settings"));
setAttribute(Qt::WA_StyledBackground, true);
setProperty("stylable", true); // for stylesheet addressing
m_mainLayout = new QFormLayout(this);
m_mainLayout->setContentsMargins(8, 8, 8, 8);
m_mainLayout->setSpacing(5);
}
void MinimizerSettingsWidget::setJobItem(JobItem* jobItem)
{
ASSERT(jobItem);
setMinItem(jobItem->fitSuiteItem()->minimizerContainerItem());
}
void MinimizerSettingsWidget::setMinItem(MinimizerContainerItem* minimizerItem)
{
ASSERT(minimizerItem);
GUI::Util::Layout::clearLayout(m_mainLayout);
m_updaters.clear();
m_currentItem = minimizerItem;
if (!m_currentItem)
return;
m_mainLayout->addRow("Minimizer:", GUI::Util::createComboBox(
[=] { return m_currentItem->minimizerCombo(); },
[=](const QString& t) {
m_currentItem->setCurrentMinimizer(t);
createMimimizerEdits();
}, &m_updaters));
auto* w = new QWidget(this);
m_minimizerLayout = new QFormLayout(w);
m_minimizerLayout->setContentsMargins(10, 8, 0, 8);
m_mainLayout->addRow(w);
m_mainLayout->addRow("Objective metric:", GUI::Util::createComboBox(
[=] { return m_currentItem->objectiveMetricCombo(); },
[=](const QString& t) { m_currentItem->setCurrentObjectiveMetric(t); },
&m_updaters, "Objective metric to use for estimating distance between simulated and experimental data"));
m_mainLayout->addRow("Norm function:", GUI::Util::createComboBox(
[=] { return m_currentItem->normFunctionCombo(); },
[=](const QString& t) { m_currentItem->setCurrentNormFunction(t); },
&m_updaters, "Normalization to use for estimating distance between simulated and experimental data"));
createMimimizerEdits();
updateUIValues();
}
void MinimizerSettingsWidget::createMimimizerEdits()
{
GUI::Util::Layout::clearLayout(m_minimizerLayout);
// Minuit2
if(m_currentItem->currentMinimizerM_TYPE() == MinuitMinimizerItem::M_TYPE)
createMinuitEdits();
else
// GSL MultiMin
if(m_currentItem->currentMinimizerM_TYPE() == GSLMultiMinimizerItem::M_TYPE)
createGSLMultiMinEdits();
else
// TMVA Genetic
if(m_currentItem->currentMinimizerM_TYPE() == GeneticMinimizerItem::M_TYPE)
createTMVAGeneticEdits();
else
// GSL Simulated Annealing
if(m_currentItem->currentMinimizerM_TYPE() == SimAnMinimizerItem::M_TYPE)
createGSLSimulatedAnnealingEdits();
else
// GSL Levenberg-Marquardt
if(m_currentItem->currentMinimizerM_TYPE() == GSLLMAMinimizerItem::M_TYPE)
createGSLLevMarEdits();
else
ASSERT(0);
}
void MinimizerSettingsWidget::createMinuitEdits()
{
MinuitMinimizerItem* minItem = m_currentItem->minimizerItemMinuit();
m_minimizerLayout->addRow("Algorithm:", GUI::Util::createComboBox(
[=] { return minItem->algorithmCombo(); },
[=](const QString& t) { minItem->setCurrentAlgorithm(t); },
&m_updaters));
m_minimizerLayout->addRow("Strategy:", GUI::Util::createIntSpinbox(
[=] { return minItem->strategy(); },
[=](int v) { minItem->setStrategy(v); },
&m_updaters, "Minimization strategy (0-low, 1-medium, 2-high quality)",
RealLimits::limited(0, 2)));
m_minimizerLayout->addRow("ErrorDef factor:", GUI::Util::createDoubleSpinbox(
[=] { return minItem->errorDefinition(); },
[=](double v) { minItem->setErrorDefinition(v); },
&m_updaters, "Error definition factor for parameter error calculation",
RealLimits::positive()));
m_minimizerLayout->addRow("Tolerance:", GUI::Util::createDoubleSpinbox(
[=] { return minItem->tolerance(); },
[=](double v) { minItem->setTolerance(v); },
&m_updaters, "Tolerance on the function value at the minimum",
RealLimits::nonnegative()));
m_minimizerLayout->addRow("Precision:", GUI::Util::createDoubleSpinbox(
[=] { return minItem->precision(); },
[=](double v) { minItem->setPrecision(v); },
&m_updaters, "Relative floating point arithmetic precision",
RealLimits::nonnegative()));
m_minimizerLayout->addRow("Max func calls:", GUI::Util::createIntSpinbox(
[=] { return minItem->maxFuncCalls(); },
[=](int v) { minItem->setMaxFuncCalls(v); },
&m_updaters, "Maximum number of function calls",
RealLimits::nonnegative()));
}
void MinimizerSettingsWidget::createGSLMultiMinEdits()
{
GSLMultiMinimizerItem* minItem = m_currentItem->minimizerItemGSLMulti();
m_minimizerLayout->addRow("Algorithm:", GUI::Util::createComboBox(
[=] { return minItem->algorithmCombo(); },
[=](const QString& t) { minItem->setCurrentAlgorithm(t); },
&m_updaters));
m_minimizerLayout->addRow("Max iterations:", GUI::Util::createIntSpinbox(
[=] { return minItem->maxIterations(); },
[=](int v) { minItem->setMaxIterations(v); },
&m_updaters, "Maximum number of iterations",
RealLimits::nonnegative()));
}
void MinimizerSettingsWidget::createTMVAGeneticEdits()
{
GeneticMinimizerItem* minItem = m_currentItem->minimizerItemGenetic();
m_minimizerLayout->addRow("Tolerance:", GUI::Util::createDoubleSpinbox(
[=] { return minItem->tolerance(); },
[=](double v) { minItem->setTolerance(v); },
&m_updaters, "Tolerance on the function value at the minimum",
RealLimits::nonnegative()));
m_minimizerLayout->addRow("Max iterations:", GUI::Util::createIntSpinbox(
[=] { return minItem->maxIterations(); },
[=](int v) { minItem->setMaxIterations(v); },
&m_updaters, "Maximum number of iterations",
RealLimits::nonnegative()));
m_minimizerLayout->addRow("Population:", GUI::Util::createIntSpinbox(
[=] { return minItem->populationSize(); },
[=](int v) { minItem->setPopulationSize(v); },
&m_updaters, "Population size",
RealLimits::nonnegative()));
m_minimizerLayout->addRow("Random seed:", GUI::Util::createIntSpinbox(
[=] { return minItem->randomSeed(); },
[=](int v) { minItem->setRandomSeed(v); },
&m_updaters));
}
void MinimizerSettingsWidget::createGSLSimulatedAnnealingEdits()
{
SimAnMinimizerItem* minItem = m_currentItem->minimizerItemSimAn();
m_minimizerLayout->addRow("Max iterations:", GUI::Util::createIntSpinbox(
[=] { return minItem->maxIterations(); },
[=](int v) { minItem->setMaxIterations(v); },
&m_updaters, "Number of points to try for each step",
RealLimits::nonnegative()));
m_minimizerLayout->addRow("Iterations at T:", GUI::Util::createIntSpinbox(
[=] { return minItem->iterationsAtEachTemp(); },
[=](int v) { minItem->setIterationsAtEachTemp(v); },
&m_updaters, "Number of iterations at each temperature",
RealLimits::nonnegative()));
m_minimizerLayout->addRow("Step size:", GUI::Util::createDoubleSpinbox(
[=] { return minItem->stepSize(); },
[=](double v) { minItem->setStepSize(v); },
&m_updaters, "Max step size used in random walk",
RealLimits::nonnegative()));
m_minimizerLayout->addRow("k:", GUI::Util::createDoubleSpinbox(
[=] { return minItem->boltzmanK(); },
[=](double v) { minItem->setBoltzmanK(v); },
&m_updaters, "Boltzmann k",
RealLimits::nonnegative()));
m_minimizerLayout->addRow("T init:", GUI::Util::createDoubleSpinbox(
[=] { return minItem->boltzmanInitT(); },
[=](double v) { minItem->setBoltzmanInitT(v); },
&m_updaters, "Boltzmann initial temperature",
RealLimits::nonnegative()));
m_minimizerLayout->addRow("mu:", GUI::Util::createDoubleSpinbox(
[=] { return minItem->boltzmanMu(); },
[=](double v) { minItem->setBoltzmanMu(v); },
&m_updaters, "Boltzmann mu",
RealLimits::nonnegative()));
m_minimizerLayout->addRow("T min:", GUI::Util::createDoubleSpinbox(
[=] { return minItem->boltzmanMinT(); },
[=](double v) { minItem->setBoltzmanMinT(v); },
&m_updaters, "Boltzmann minimal temperature",
RealLimits::nonnegative()));
}
void MinimizerSettingsWidget::createGSLLevMarEdits()
{
GSLLMAMinimizerItem* minItem = m_currentItem->minimizerItemGSLLMA();
m_minimizerLayout->addRow("Tolerance:", GUI::Util::createDoubleSpinbox(
[=] { return minItem->tolerance(); },
[=](double v) { minItem->setTolerance(v); },
&m_updaters, "Tolerance on the function value at the minimum",
RealLimits::nonnegative()));
m_minimizerLayout->addRow("Max iterations:", GUI::Util::createIntSpinbox(
[=] { return minItem->maxIterations(); },
[=](int v) { minItem->setMaxIterations(v); },
&m_updaters, "Maximum number of iterations",
RealLimits::nonnegative()));
}
void MinimizerSettingsWidget::updateUIValues()
{
for (const auto& updater : m_updaters)
updater();
}