From e28ca0847a7064ce277dbdb601e5761d6df4d856 Mon Sep 17 00:00:00 2001 From: Abdullah Tahiri Date: Thu, 26 Nov 2015 15:19:03 +0100 Subject: [PATCH] Sketch: Solver: Extended Advanced Solver configuration ======================================================== This is an advanced setting just for allowing increased choices to power users that have problems with a given sketch and want to test different flavours of DogLeg algorithm. This commit does not change the default behaviour of FreeCAD. It is only intended to give more options to power users. The advanced solver configuration is extended to support three different Gauss-newton steps for DogLeg: FullPivLU => h_gn = Jx.fullPivLu().solve(-fx); LeastNormFullPivLU => h_gn = Jx.adjoint()*(Jx*Jx.adjoint()).fullPivLu().solve(-fx); LeastNormLdlt => h_gn = Jx.adjoint()*(Jx*Jx.adjoint()).ldlt().solve(-fx); This setting is applied only to DogLeg. It is applied to DogLeg as normal or redundant solver, if DogLeg is the selected solver. Selecting a solver different from DogLeg for both normal and redundant disables the setting. We have been told: https://forum.kde.org/viewtopic.php?f=74&t=129439#p346104 that our default Gauss-Newton step in DogLeg may not be adequate in general (we generally deal with underconstraint systems unless we have a fully constraint sketch, and even then it is many times overconstraint at least for redundant solving). We have been told that maybe these LeastNorm options are more suitable for us (performance set aside). This enables you as power user to test if it works fine with FreeCAD. --- src/Mod/Sketcher/App/Sketch.h | 1 + src/Mod/Sketcher/App/planegcs/GCS.cpp | 17 +++++++- src/Mod/Sketcher/App/planegcs/GCS.h | 7 ++++ .../Gui/TaskSketcherSolverAdvanced.cpp | 35 ++++++++++++++-- .../Sketcher/Gui/TaskSketcherSolverAdvanced.h | 3 +- .../Gui/TaskSketcherSolverAdvanced.ui | 42 +++++++++++++++++++ 6 files changed, 100 insertions(+), 5 deletions(-) diff --git a/src/Mod/Sketcher/App/Sketch.h b/src/Mod/Sketcher/App/Sketch.h index 5283149bac..ad40385ae1 100644 --- a/src/Mod/Sketcher/App/Sketch.h +++ b/src/Mod/Sketcher/App/Sketch.h @@ -377,6 +377,7 @@ protected: public: GCS::Algorithm defaultSolver; GCS::Algorithm defaultSolverRedundant; + inline void setDogLegGaussStep(GCS::DogLegGaussStep mode){GCSsys.dogLegGaussStep=mode;} inline void setDebugMode(GCS::DebugMode mode) {debugMode=mode;GCSsys.debugMode=mode;} inline GCS::DebugMode getDebugMode(void) {return debugMode;} inline void setMaxIter(int maxiter){GCSsys.maxIter=maxiter;} diff --git a/src/Mod/Sketcher/App/planegcs/GCS.cpp b/src/Mod/Sketcher/App/planegcs/GCS.cpp index 9620a4dca5..cb12453ed1 100644 --- a/src/Mod/Sketcher/App/planegcs/GCS.cpp +++ b/src/Mod/Sketcher/App/planegcs/GCS.cpp @@ -198,6 +198,7 @@ System::System() , convergence(1e-10) , convergenceRedundant(1e-10) , qrAlgorithm(EigenSparseQR) + , dogLegGaussStep(FullPivLU) , qrpivotThreshold(1E-13) , debugMode(Minimal) , LM_eps(1E-10) @@ -1453,6 +1454,7 @@ int System::solve_DL(SubSystem* subsys, bool isRedundantsolving) << ", tolx: " << tolx << ", tolf: " << tolf << ", convergence: " << (isRedundantsolving?convergenceRedundant:convergence) + << ", dogLegGaussStep: " << (dogLegGaussStep==FullPivLU?"FullPivLU":(dogLegGaussStep==LeastNormFullPivLU?"LeastNormFullPivLU":"LeastNormLdlt")) << ", xsize: " << xsize << ", csize: " << csize << ", maxIter: " << maxIterNumber << "\n"; @@ -1505,7 +1507,20 @@ int System::solve_DL(SubSystem* subsys, bool isRedundantsolving) h_sd = alpha*g; // get the gauss-newton step - h_gn = Jx.fullPivLu().solve(-fx); + // http://forum.freecadweb.org/viewtopic.php?f=10&t=12769&start=50#p106220 + // https://forum.kde.org/viewtopic.php?f=74&t=129439#p346104 + switch (dogLegGaussStep){ + case FullPivLU: + h_gn = Jx.fullPivLu().solve(-fx); + break; + case LeastNormFullPivLU: + h_gn = Jx.adjoint()*(Jx*Jx.adjoint()).fullPivLu().solve(-fx); + break; + case LeastNormLdlt: + h_gn = Jx.adjoint()*(Jx*Jx.adjoint()).ldlt().solve(-fx); + break; + } + double rel_error = (Jx*h_gn + fx).norm() / fx.norm(); if (rel_error > 1e15) break; diff --git a/src/Mod/Sketcher/App/planegcs/GCS.h b/src/Mod/Sketcher/App/planegcs/GCS.h index 0810b1f2eb..99688df5a5 100644 --- a/src/Mod/Sketcher/App/planegcs/GCS.h +++ b/src/Mod/Sketcher/App/planegcs/GCS.h @@ -51,6 +51,12 @@ namespace GCS DogLeg = 2 }; + enum DogLegGaussStep { + FullPivLU = 0, + LeastNormFullPivLU = 1, + LeastNormLdlt = 2 + }; + enum QRAlgorithm { EigenDenseQR = 0, EigenSparseQR = 1 @@ -108,6 +114,7 @@ namespace GCS double convergence; double convergenceRedundant; QRAlgorithm qrAlgorithm; + DogLegGaussStep dogLegGaussStep; double qrpivotThreshold; DebugMode debugMode; double LM_eps; diff --git a/src/Mod/Sketcher/Gui/TaskSketcherSolverAdvanced.cpp b/src/Mod/Sketcher/Gui/TaskSketcherSolverAdvanced.cpp index 38a91d5ec5..86a01e77a0 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherSolverAdvanced.cpp +++ b/src/Mod/Sketcher/Gui/TaskSketcherSolverAdvanced.cpp @@ -58,6 +58,7 @@ #define QR_PIVOT_THRESHOLD 1E-13 // under this value a Jacobian value is regarded as zero #define DEFAULT_SOLVER_DEBUG 1 // None=0, Minimal=1, IterationLevel=2 #define MAX_ITER_MULTIPLIER false +#define DEFAULT_DOGLEG_GAUSS_STEP 0 // FullPivLU = 0, LeastNormFullPivLU = 1, LeastNormLdlt = 2 using namespace SketcherGui; using namespace Gui::TaskView; @@ -75,6 +76,7 @@ TaskSketcherSolverAdvanced::TaskSketcherSolverAdvanced(ViewProviderSketch *sketc this->groupLayout()->addWidget(proxy); ui->comboBoxDefaultSolver->onRestore(); + ui->comboBoxDogLegGaussStep->onRestore(); ui->spinBoxMaxIter->onRestore(); ui->checkBoxSketchSizeMultiplier->onRestore(); ui->lineEditConvergence->onRestore(); @@ -98,7 +100,15 @@ void TaskSketcherSolverAdvanced::updateDefaultMethodParameters(void) { ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Sketcher/SolverAdvanced"); - switch(ui->comboBoxDefaultSolver->currentIndex()) + int currentindex = ui->comboBoxDefaultSolver->currentIndex(); + int redundantcurrentindex = ui->comboBoxRedundantDefaultSolver->currentIndex(); + + if(redundantcurrentindex == 2 || currentindex == 2) + ui->comboBoxDogLegGaussStep->setEnabled(true); + else + ui->comboBoxDogLegGaussStep->setEnabled(false); + + switch(currentindex) { case 0: // BFGS ui->labelSolverParam1->setText(QString::fromLatin1("")); @@ -156,7 +166,15 @@ void TaskSketcherSolverAdvanced::updateRedundantMethodParameters(void) { ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Sketcher/SolverAdvanced"); - switch(ui->comboBoxRedundantDefaultSolver->currentIndex()) + int currentindex = ui->comboBoxDefaultSolver->currentIndex(); + int redundantcurrentindex = ui->comboBoxRedundantDefaultSolver->currentIndex(); + + if(redundantcurrentindex == 2 || currentindex == 2) + ui->comboBoxDogLegGaussStep->setEnabled(true); + else + ui->comboBoxDogLegGaussStep->setEnabled(false); + + switch(redundantcurrentindex) { case 0: // BFGS ui->labelRedundantSolverParam1->setText(QString::fromLatin1("")); @@ -385,6 +403,13 @@ void TaskSketcherSolverAdvanced::on_comboBoxDefaultSolver_currentIndexChanged(in updateDefaultMethodParameters(); } +void TaskSketcherSolverAdvanced::on_comboBoxDogLegGaussStep_currentIndexChanged(int index) +{ + ui->comboBoxDogLegGaussStep->onSave(); + sketchView->getSketchObject()->getSolvedSketch().setDogLegGaussStep((GCS::DogLegGaussStep) index); + updateDefaultMethodParameters(); +} + void TaskSketcherSolverAdvanced::on_spinBoxMaxIter_valueChanged(int i) { ui->spinBoxMaxIter->onSave(); @@ -505,6 +530,8 @@ void TaskSketcherSolverAdvanced::on_pushButtonDefaults_clicked(bool checked/* = hGrp->SetASCII("Redundant_DL_tolf",QString::number(DL_TOLF).toUtf8()); // Set other settings hGrp->SetInt("DefaultSolver",DEFAULT_SOLVER); + hGrp->SetInt("DogLegGaussStep",DEFAULT_DOGLEG_GAUSS_STEP); + hGrp->SetInt("RedundantDefaultSolver",DEFAULT_RSOLVER); hGrp->SetInt("MaxIter",MAX_ITER); hGrp->SetInt("RedundantSolverMaxIterations",MAX_ITER); @@ -517,6 +544,7 @@ void TaskSketcherSolverAdvanced::on_pushButtonDefaults_clicked(bool checked/* = hGrp->SetInt("DebugMode",DEFAULT_SOLVER_DEBUG); ui->comboBoxDefaultSolver->onRestore(); + ui->comboBoxDogLegGaussStep->onRestore(); ui->spinBoxMaxIter->onRestore(); ui->checkBoxSketchSizeMultiplier->onRestore(); ui->lineEditConvergence->onRestore(); @@ -543,7 +571,8 @@ void TaskSketcherSolverAdvanced::updateSketchObject(void) sketchView->getSketchObject()->getSolvedSketch().setConvergence(ui->lineEditConvergence->text().toDouble()); sketchView->getSketchObject()->getSolvedSketch().setSketchSizeMultiplier(ui->checkBoxSketchSizeMultiplier->isChecked()); sketchView->getSketchObject()->getSolvedSketch().setMaxIter(ui->spinBoxMaxIter->value()); - sketchView->getSketchObject()->getSolvedSketch().defaultSolver=(GCS::Algorithm) ui->comboBoxDefaultSolver->currentIndex(); + sketchView->getSketchObject()->getSolvedSketch().defaultSolver=(GCS::Algorithm) ui->comboBoxDefaultSolver->currentIndex(); + sketchView->getSketchObject()->getSolvedSketch().setDogLegGaussStep((GCS::DogLegGaussStep) ui->comboBoxDogLegGaussStep->currentIndex()); updateDefaultMethodParameters(); updateRedundantMethodParameters(); diff --git a/src/Mod/Sketcher/Gui/TaskSketcherSolverAdvanced.h b/src/Mod/Sketcher/Gui/TaskSketcherSolverAdvanced.h index d387d4edde..92b1423bc6 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherSolverAdvanced.h +++ b/src/Mod/Sketcher/Gui/TaskSketcherSolverAdvanced.h @@ -47,7 +47,8 @@ public: ~TaskSketcherSolverAdvanced(); private Q_SLOTS: - void on_comboBoxDefaultSolver_currentIndexChanged(int index); + void on_comboBoxDefaultSolver_currentIndexChanged(int index); + void on_comboBoxDogLegGaussStep_currentIndexChanged(int index); void on_spinBoxMaxIter_valueChanged(int i); void on_checkBoxSketchSizeMultiplier_stateChanged(int state); void on_lineEditConvergence_editingFinished(); diff --git a/src/Mod/Sketcher/Gui/TaskSketcherSolverAdvanced.ui b/src/Mod/Sketcher/Gui/TaskSketcherSolverAdvanced.ui index 565d9ecbd2..708ab9eb60 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherSolverAdvanced.ui +++ b/src/Mod/Sketcher/Gui/TaskSketcherSolverAdvanced.ui @@ -56,6 +56,48 @@ + + + + + + Type of function to apply in DogLeg for the Gauss step + + + DogLeg Gauss step: + + + + + + + 0 + + + DogLegGaussStep + + + Mod/Sketcher/SolverAdvanced + + + + FullPivLU + + + + + LeastNorm-FullPivLU + + + + + LeastNorm-LDLT + + + + + +