// ************************************************************************************************ // // 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(); }