From a8b2183afa7cbdded591a9424af21f99fc030d65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 8 Jun 2018 16:48:59 +0200 Subject: [PATCH] [apps/reg] Prevent fitting when data not suitable --- apps/regression/calculation_controller.cpp | 5 +---- apps/regression/graph_controller.cpp | 15 ++------------- apps/regression/model/logarithmic_model.cpp | 15 +++++++++++++++ apps/regression/model/logarithmic_model.h | 2 ++ apps/regression/model/model.cpp | 12 +++++++++++- apps/regression/model/model.h | 3 +++ apps/regression/model/power_model.cpp | 15 +++++++++++++++ apps/regression/model/power_model.h | 2 ++ 8 files changed, 51 insertions(+), 18 deletions(-) diff --git a/apps/regression/calculation_controller.cpp b/apps/regression/calculation_controller.cpp index c4ae53f6b..4bde7bf6e 100644 --- a/apps/regression/calculation_controller.cpp +++ b/apps/regression/calculation_controller.cpp @@ -84,10 +84,7 @@ void CalculationController::tableViewDidChangeSelection(SelectableTableView * t, } bool CalculationController::isEmpty() const { - if (m_store->numberOfPairs() == 0) { - return true; - } - return false; + return m_store->isEmpty(); } I18n::Message CalculationController::emptyMessage() { diff --git a/apps/regression/graph_controller.cpp b/apps/regression/graph_controller.cpp index 5d8a1bad1..5d6514140 100644 --- a/apps/regression/graph_controller.cpp +++ b/apps/regression/graph_controller.cpp @@ -27,22 +27,11 @@ ViewController * GraphController::initialisationParameterController() { } bool GraphController::isEmpty() const { - if (m_store->isEmpty()) { - return true; - } - for (int series = 0; series < DoublePairStore::k_numberOfSeries; series++) { - if (!m_store->seriesIsEmpty(series) && !std::isinf(m_store->slope(series)) && !std::isnan(m_store->slope(series))) { - return false; - } - } - return true; + return m_store->isEmpty(); } I18n::Message GraphController::emptyMessage() { - if (m_store->numberOfPairs() == 0) { - return I18n::Message::NoDataToPlot; - } - return I18n::Message::NoEnoughDataForRegression; + return I18n::Message::NoDataToPlot; } void GraphController::viewWillAppear() { diff --git a/apps/regression/model/logarithmic_model.cpp b/apps/regression/model/logarithmic_model.cpp index 7329f2bfb..0fa6ec876 100644 --- a/apps/regression/model/logarithmic_model.cpp +++ b/apps/regression/model/logarithmic_model.cpp @@ -1,4 +1,5 @@ #include "logarithmic_model.h" +#include "../store.h" #include #include #include @@ -35,6 +36,7 @@ double LogarithmicModel::levelSet(double * modelCoefficients, double y) const { double LogarithmicModel::partialDerivate(double * modelCoefficients, int derivateCoefficientIndex, double x) const { if (derivateCoefficientIndex == 0) { // Derivate: ln(x) + assert(x >0); return log(x); } if (derivateCoefficientIndex == 1) { @@ -45,4 +47,17 @@ double LogarithmicModel::partialDerivate(double * modelCoefficients, int derivat return 0.0; } +bool LogarithmicModel::dataSuitableForFit(Store * store, int series) const { + if (!Model::dataSuitableForFit(store, series)) { + return false; + } + int numberOfPairs = store->numberOfPairsOfSeries(series); + for (int j = 0; j < numberOfPairs; j++) { + if (store->get(series, 0, j) <= 0) { + return false; + } + } + return true; +} + } diff --git a/apps/regression/model/logarithmic_model.h b/apps/regression/model/logarithmic_model.h index 6a51436d7..903f0211b 100644 --- a/apps/regression/model/logarithmic_model.h +++ b/apps/regression/model/logarithmic_model.h @@ -16,6 +16,8 @@ public: double levelSet(double * modelCoefficients, double y) const override; double partialDerivate(double * modelCoefficients, int derivateCoefficientIndex, double x) const override; int numberOfCoefficients() const override { return 2; } +protected: + virtual bool dataSuitableForFit(Store * store, int series) const override; }; } diff --git a/apps/regression/model/model.cpp b/apps/regression/model/model.cpp index 6c3107760..28211be7b 100644 --- a/apps/regression/model/model.cpp +++ b/apps/regression/model/model.cpp @@ -11,7 +11,17 @@ using namespace Shared; namespace Regression { void Model::fit(Store * store, int series, double * modelCoefficients, Poincare::Context * context) { - fitLevenbergMarquardt(store, series, modelCoefficients, context); + if (dataSuitableForFit(store, series)) { + fitLevenbergMarquardt(store, series, modelCoefficients, context); + } else { + for (int i = 0; i < numberOfCoefficients(); i++) { + modelCoefficients[i] = NAN; //TODO undef /inf ? + } + } +} + +bool Model::dataSuitableForFit(Store * store, int series) const { + return !store->seriesIsEmpty(series) && !std::isinf(store->slope(series)) && !std::isnan(store->slope(series)); } void Model::fitLevenbergMarquardt(Store * store, int series, double * modelCoefficients, Context * context) { diff --git a/apps/regression/model/model.h b/apps/regression/model/model.h index 1b48453f0..b31b57418 100644 --- a/apps/regression/model/model.h +++ b/apps/regression/model/model.h @@ -33,6 +33,9 @@ public: virtual double levelSet(double * modelCoefficients, double y) const = 0; virtual void fit(Store * store, int series, double * modelCoefficients, Poincare::Context * context); virtual int numberOfCoefficients() const = 0; +protected: + // Fit + virtual bool dataSuitableForFit(Store * store, int series) const; private: // Model attributes virtual double partialDerivate(double * modelCoefficients, int derivateCoefficientIndex, double x) const = 0; diff --git a/apps/regression/model/power_model.cpp b/apps/regression/model/power_model.cpp index cbe67c0ac..c789abcec 100644 --- a/apps/regression/model/power_model.cpp +++ b/apps/regression/model/power_model.cpp @@ -1,4 +1,5 @@ #include "power_model.h" +#include "../store.h" #include #include #include "../../poincare/include/poincare_layouts.h" @@ -66,4 +67,18 @@ double PowerModel::partialDerivate(double * modelCoefficients, int derivateCoeff return 0.0; } +bool PowerModel::dataSuitableForFit(Store * store, int series) const { + if (!Model::dataSuitableForFit(store, series)) { + return false; + } + int numberOfPairs = store->numberOfPairsOfSeries(series); + for (int j = 0; j < numberOfPairs; j++) { + if (store->get(series, 0, j) < 0) { + return false; + } + } + return true; +} + + } diff --git a/apps/regression/model/power_model.h b/apps/regression/model/power_model.h index 5216bd652..5408d4a34 100644 --- a/apps/regression/model/power_model.h +++ b/apps/regression/model/power_model.h @@ -16,6 +16,8 @@ public: double levelSet(double * modelCoefficients, double y) const override; double partialDerivate(double * modelCoefficients, int derivateCoefficientIndex, double x) const override; int numberOfCoefficients() const override { return 2; } +protected: + virtual bool dataSuitableForFit(Store * store, int series) const override; }; }