{"id":19795578,"url":"https://github.com/dkogan/libdogleg","last_synced_at":"2025-07-04T04:40:09.881Z","repository":{"id":136714424,"uuid":"2337030","full_name":"dkogan/libdogleg","owner":"dkogan","description":"Large-scale nonlinear least-squares optimization library for both sparse and dense problems","archived":false,"fork":false,"pushed_at":"2024-11-21T01:37:02.000Z","size":294,"stargazers_count":25,"open_issues_count":0,"forks_count":13,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-06T08:08:02.480Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dkogan.png","metadata":{"files":{"readme":"README.pod","changelog":"Changes","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2011-09-06T20:08:45.000Z","updated_at":"2024-12-10T05:20:32.000Z","dependencies_parsed_at":"2023-12-08T04:28:14.166Z","dependency_job_id":"d61bf1b6-7143-48e0-aed8-669f0a741be3","html_url":"https://github.com/dkogan/libdogleg","commit_stats":null,"previous_names":[],"tags_count":24,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dkogan%2Flibdogleg","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dkogan%2Flibdogleg/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dkogan%2Flibdogleg/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dkogan%2Flibdogleg/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dkogan","download_url":"https://codeload.github.com/dkogan/libdogleg/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251817809,"owners_count":21648811,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-12T07:16:45.939Z","updated_at":"2025-05-01T03:30:28.169Z","avatar_url":"https://github.com/dkogan.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"=head1 NAME\n\nlibdogleg - A general purpose optimizer to solve data fitting problems\n\n=head1 NOTICE\n\nIf you're considering using this library for new projects, please look at the\nC\u003cceres\u003e solver instead:\n\nL\u003chttp://ceres-solver.org/\u003e\n\nC\u003clibdogleg\u003e is not deprecated, and I will fix bugs as they're reported. However\nC\u003cceres\u003e is more feature-rich and I\u003cmuch\u003e more widely used. I consider C\u003cceres\u003e\nto be a superset of C\u003clibdogleg\u003e, and if C\u003cceres\u003e was available when I wrote\nC\u003clibdogleg\u003e, I would not have written it.\n\n=head1 DESCRIPTION\n\nThis is a library for solving large-scale nonlinear optimization problems. By employing sparse\nlinear algebra, it is taylored for problems that have weak coupling between the optimization\nvariables. For appropriately sparse problems this results in I\u003cmassive\u003e performance gains.\n\nFor smaller problems with dense Jacobians a dense mode is available also. This\nutilizes the same optimization loop as the sparse code, but uses dense linear\nalgebra.\n\nThe main task of this library is to find the vector B\u003cp\u003e that minimizes\n\nnorm2( B\u003cx\u003e )\n\nwhere B\u003cx\u003e = I\u003cf\u003e(B\u003cp\u003e) is a vector that has higher dimensionality than B\u003cp\u003e. The user passes in a\ncallback function (of type C\u003cdogleg_callback_t\u003e) that takes in the vector B\u003cp\u003e and returns the\nvector B\u003cx\u003e and a matrix of derivatives B\u003cJ\u003e = dB\u003cf\u003e/dB\u003cp\u003e. B\u003cJ\u003e is a matrix with a row for each\nelement of I\u003cf\u003e and a column for each element of B\u003cp\u003e. If B\u003cJ\u003e is a sparse matrix, then this library\ncan take advantage of that, which results in substantial increases in computational efficiency if\nmost entries of B\u003cJ\u003e are 0. B\u003cJ\u003e is stored row-first in the callback routine. libdogleg uses a\ncolumn-first data representation so it references the transpose of B\u003cJ\u003e (called B\u003cJt\u003e). B\u003cJ\u003e stored\nrow-first is identical to B\u003cJt\u003e stored column-first; this is purely a naming choice.\n\nThis library implements Powell's dog-leg algorithm to solve the problem. Like the more-widely-known\nLevenberg-Marquardt algorithm, Powell's dog-leg algorithm solves a nonlinear optimization problem by\ninterpolating between a Gauss-Newton step and a gradient descent step. Improvements over LM are\n\n=over\n\n=item * a more natural representation of the linearity of the operating point (trust region size vs\na vague lambda term).\n\n=item * significant efficiency gains, since a matrix inversion isn't needed to retry a rejected step\n\n=back\n\nThe algorithm is described in many places, originally in\n\nM. Powell. A Hybrid Method for Nonlinear Equations. In P. Rabinowitz, editor, Numerical Methods for\nNonlinear Algebraic Equations, pages 87-144.  Gordon and Breach Science, London, 1970.\n\nVarious enhancements to Powell's original method are described in the literature; at this time only\nthe original algorithm is implemented here. \n\nThe sparse matrix algebra is handled by the CHOLMOD library, written by Tim Davis. Parts of CHOLMOD\nare licensed under the GPL and parts under the LGPL. Only the LGPL pieces are used here, allowing\nlibdogleg to be licensed under the LGPL as well. Due to this I lose some convenience (all simple\nsparse matrix arithmetic in CHOLMOD is GPL-ed) and some performance (the fancier computational\nmethods, such as supernodal analysis are GPL-ed). For my current applications the performance losses\nare minor.\n\n\n=head1 FUNCTIONS AND TYPES\n\n=head2 Main API\n\n=head3 dogleg_optimize2\n\nThis is the main call to the library for I\u003csparse\u003e Jacobians. It's declared as\n\n double dogleg_optimize2(double* p, unsigned int Nstate,\n                         unsigned int Nmeas, unsigned int NJnnz,\n                         dogleg_callback_t* f, void* cookie,\n                         const dogleg_parameters2_t* parameters,\n                         dogleg_solverContext_t** returnContext);\n\n=over\n\n=item * B\u003cp\u003e is the initial estimate of the state vector (and holds the final result)\n\n=item * C\u003cNstate\u003e specifies the number of optimization variables (elements of B\u003cp\u003e)\n\n=item * C\u003cNmeas\u003e specifies the number of measurements (elements of B\u003cx\u003e). C\u003cNmeas E\u003cgt\u003e= Nstate\u003e is a\nrequirement\n\n=item * C\u003cNJnnz\u003e specifies the number of non-zero elements of the jacobian matrix dB\u003cf\u003e/dB\u003cp\u003e. In a\ndense matrix C\u003cJnnz = Nstate*Nmeas\u003e. We are dealing with sparse jacobians, so C\u003cNJnnz\u003e should be far\nless. If not, libdogleg is not an appropriate routine to solve this problem.\n\n=item * C\u003cf\u003e specifies the callback function that the optimization routine calls to sample the problem\nbeing solved\n\n=item * C\u003ccookie\u003e is an arbitrary data pointer passed untouched to C\u003cf\u003e\n\n=item * C\u003cparameters\u003e a pointer to the set of parameters to use. Set to C\u003cNULL\u003e\nto use the global parameters, or call C\u003cdogleg_optimize\u003e instead. See the\nL\u003cParameters\u003e section below for more details\n\n=item * If not C\u003cNULL\u003e, C\u003creturnContext\u003e can be used to retrieve the full\ncontext structure from the solver. This can be useful since this structure\ncontains the latest operating point values. It also has an active\nC\u003ccholmod_common\u003e structure, which can be reused if more CHOLMOD routines need\nto be called externally. You usually want C\u003creturnContext-E\u003cgt\u003ebeforeStep\u003e. I\u003cIf\nthis data is requested, the user is required to free it with\nC\u003cdogleg_freeContext\u003e when done\u003e.\n\n=back\n\nC\u003cdogleg_optimize\u003e returns norm2( B\u003cx\u003e ) at the minimum, or a negative value if an error occurred.\n\n=head3 dogleg_optimize\n\nThis is a flavor of C\u003cdogleg_optimize2\u003e that implicitly uses the global\nparameters. It's declared as\n\n double dogleg_optimize(double* p, unsigned int Nstate,\n                        unsigned int Nmeas, unsigned int NJnnz,\n                        dogleg_callback_t* f, void* cookie,\n                        dogleg_solverContext_t** returnContext);\n\n=head3 dogleg_optimize_dense2\n\nThis is the main call to the library for I\u003cdense\u003e Jacobians. Its declared as\n\n double dogleg_optimize_dense2(double* p, unsigned int Nstate,\n                               unsigned int Nmeas,\n                               dogleg_callback_dense_t* f, void* cookie,\n                               const dogleg_parameters2_t* parameters,\n                               dogleg_solverContext_t** returnContext);\n\nThe arguments are almost identical to those in the C\u003cdogleg_optimize\u003e call.\n\n=over\n\n=item * B\u003cp\u003e is the initial estimate of the state vector (and holds the final result)\n\n=item * C\u003cNstate\u003e specifies the number of optimization variables (elements of B\u003cp\u003e)\n\n=item * C\u003cNmeas\u003e specifies the number of measurements (elements of B\u003cx\u003e). C\u003cNmeas E\u003cgt\u003e= Nstate\u003e is a\nrequirement\n\n=item * C\u003cf\u003e specifies the callback function that the optimization routine calls to sample the problem\nbeing solved. Note that this callback has a different type from that in C\u003cdogleg_optimize\u003e\n\n=item * C\u003ccookie\u003e is an arbitrary data pointer passed untouched to C\u003cf\u003e\n\n=item * C\u003cparameters\u003e a pointer to the set of parameters to use. Set to C\u003cNULL\u003e\nto use the global parameters, or call C\u003cdogleg_optimize\u003e instead. See the\nL\u003cParameters\u003e section below for more details\n\n=item * If not C\u003cNULL\u003e, C\u003creturnContext\u003e can be used to retrieve the full\ncontext structure from the solver. This can be useful since this structure\ncontains the latest operating point values. You usually want\nC\u003creturnContext-E\u003cgt\u003ebeforeStep\u003e. I\u003cIf this data is requested, the user is\nrequired to free it with C\u003cdogleg_freeContext\u003e when done\u003e.\n\n=back\n\nC\u003cdogleg_optimize\u003e returns norm2( B\u003cx\u003e ) at the minimum, or a negative value if an error occurred.\n\n=head3 dogleg_optimize_dense\n\nThis is a flavor of C\u003cdogleg_optimize_dense2\u003e that implicitly uses the global\nparameters. It's declared as\n\n double dogleg_optimize_dense(double* p, unsigned int Nstate,\n                              unsigned int Nmeas,\n                              dogleg_callback_dense_t* f, void* cookie,\n                              dogleg_solverContext_t** returnContext);\n\n=head3 dogleg_freeContext\n\nUsed to deallocate memory used for an optimization cycle. Defined as:\n\n void dogleg_freeContext(dogleg_solverContext_t** ctx);\n\nIf a pointer to a context is not requested (by passing C\u003creturnContext = NULL\u003e\nto C\u003cdogleg_optimize\u003e), libdogleg calls this routine automatically. If the user\nI\u003cdid\u003e retrieve this pointer, though, it must be freed with\nC\u003cdogleg_freeContext\u003e when the user is finished.\n\n=head3 dogleg_computeJtJfactorization\n\nComputes the cholesky decomposition of JtJ. This function is only exposed if you\nneed to touch libdogleg internals via returnContext. Sometimes after computing\nan optimization you want to do stuff with the factorization of JtJ, and this\ncall ensures that the factorization is available. Most people don't need this\nfunction. If the comment wasn't clear, you don't need this function.\n\nThis is declared as\n\n void dogleg_computeJtJfactorization(dogleg_operatingPoint_t* point,\n                                     dogleg_solverContext_t* ctx);\n\nThe arguments are\n\n=over\n\n=item * C\u003cpoint\u003e is the operating point of the system. Generally this will be\nC\u003creturnContext-E\u003cgt\u003ebeforeStep\u003e where C\u003creturnContext\u003e is from one of the\nC\u003cdogleg_optimize_...\u003e functions.\n\n=item * C\u003cctx\u003e is the dogleg context. Generally this will be C\u003creturnContext\u003e\nfrom one of the C\u003cdogleg_optimize_...\u003e functions\n\n=back\n\n=head3 dogleg_testGradient\n\nlibdogleg requires the user to compute the jacobian matrix B\u003cJ\u003e. This is a performance optimization,\nsince B\u003cJ\u003e could be computed by differences of B\u003cx\u003e. This optimization is often worth the extra\neffort, but it creates a possibility that B\u003cJ\u003e will have a mistake and B\u003cJ\u003e = dB\u003cf\u003e/dB\u003cp\u003e would not\nbe true. To find these types of issues, the user can call\n\n void dogleg_testGradient(unsigned int var, const double* p0,\n                          unsigned int Nstate, unsigned int Nmeas, unsigned int NJnnz,\n                          dogleg_callback_t* f, void* cookie);\n\nThis function computes the jacobian with center differences and compares the result with the\njacobian computed by the callback function. It is recommended to do this for every variable while\ndeveloping the program that uses libdogleg.\n\n=over\n\n=item * C\u003cvar\u003e is the index of the variable being tested\n\n=item * C\u003cp0\u003e is the state vector B\u003cp\u003e where we're evaluating the jacobian\n\n=item * C\u003cNstate\u003e, C\u003cNmeas\u003e, C\u003cNJnnz\u003e are the number of state variables, measurements and non-zero jacobian elements, as before\n\n=item * C\u003cf\u003e is the callback function, as before\n\n=item * C\u003ccookie\u003e is the user data, as before\n\n=back\n\nThis function returns nothing, but prints out the test results.\n\n=head3 dogleg_testGradient_dense\n\nVery similar to C\u003cdogleg_testGradient\u003e, but for dense jacobians.\n\n void dogleg_testGradient_dense(unsigned int var, const double* p0,\n                                unsigned int Nstate, unsigned int Nmeas,\n                                dogleg_callback_dense_t* f, void* cookie);\n\nThis function computes the jacobian with center differences and compares the result with the\njacobian computed by the callback function. It is recommended to do this for every variable while\ndeveloping the program that uses libdogleg.\n\n=over\n\n=item * C\u003cvar\u003e is the index of the variable being tested\n\n=item * C\u003cp0\u003e is the state vector B\u003cp\u003e where we're evaluating the jacobian\n\n=item * C\u003cNstate\u003e, C\u003cNJnnz\u003e are the number of state variables, measurements\n\n=item * C\u003cf\u003e is the callback function, as before\n\n=item * C\u003ccookie\u003e is the user data, as before\n\n=back\n\nThis function returns nothing, but prints out the test results.\n\n\n=head3 dogleg_callback_t\n\nThe main user callback that specifies the sparse optimization problem has type\n\n typedef void (dogleg_callback_t)(const double*   p,\n                                  double*         x,\n                                  cholmod_sparse* Jt,\n                                  void*           cookie);\n\n=over\n\n=item * B\u003cp\u003e is the current state vector\n\n=item * B\u003cx\u003e is the resulting I\u003cf\u003e(B\u003cp\u003e)\n\n=item * B\u003cJt\u003e is the transpose of dB\u003cf\u003e/dB\u003cp\u003e at B\u003cp\u003e. As mentioned previously, B\u003cJt\u003e is stored\ncolumn-first by CHOLMOD, which can be interpreted as storing B\u003cJ\u003e row-first by the user-defined\ncallback routine\n\n=item * The C\u003ccookie\u003e is the user-defined arbitrary data passed into C\u003cdogleg_optimize\u003e.\n\n=back\n\n=head3 dogleg_callback_dense_t\n\nThe main user callback that specifies the dense optimization problem has type\n\n typedef void (dogleg_callback_dense_t)(const double*   p,\n                                        double*         x,\n                                        double*         J,\n                                        void*           cookie);\n\n=over\n\n=item * B\u003cp\u003e is the current state vector\n\n=item * B\u003cx\u003e is the resulting I\u003cf\u003e(B\u003cp\u003e)\n\n=item * B\u003cJ\u003e is dB\u003cf\u003e/dB\u003cp\u003e at B\u003cp\u003e. B\u003cJ\u003e is stored row-first, with all the derivatives for the\nfirst measurement, then all the derivatives for the second measurement and so on.\n\n=item * The C\u003ccookie\u003e is the user-defined arbitrary data passed into C\u003cdogleg_optimize\u003e.\n\n=back\n\n=head3 dogleg_solverContext_t\n\nThis is the solver context that can be retrieved through the C\u003creturnContext\u003e\nparameter of the C\u003cdogleg_optimize\u003e call. This structure contains I\u003call\u003e the\ninternal state used by the solver. If requested, the user is responsible for\ncalling C\u003cdogleg_freeContext\u003e when done. This structure is defined as:\n\n typedef struct\n {\n   cholmod_common  common;\n\n   union\n   {\n     dogleg_callback_t*       f;\n     dogleg_callback_dense_t* f_dense;\n   };\n   void*              cookie;\n\n   // between steps, beforeStep contains the operating point of the last step.\n   // afterStep is ONLY used while making the step. Externally, use beforeStep\n   // unless you really know what you're doing\n   dogleg_operatingPoint_t* beforeStep;\n   dogleg_operatingPoint_t* afterStep;\n\n   // The result of the last JtJ factorization performed. Note that JtJ is not\n   // necessarily factorized at every step, so this is NOT guaranteed to contain\n   // the factorization of the most recent JtJ\n   union\n   {\n     cholmod_factor* factorization;\n\n     // This is a factorization of JtJ, stored as a packed symmetric matrix\n     // returned by dpptrf('L', ...)\n     double*         factorization_dense;\n   };\n\n   // Have I ever seen a singular JtJ? If so, I add this constant to the diagonal\n   // from that point on. This is a simple and fast way to deal with\n   // singularities. This constant starts at 0, and is increased every time a\n   // singular JtJ is encountered. This is suboptimal but works for me for now.\n   double                   lambda;\n\n   // Are we using sparse math (cholmod)?\n   int                      is_sparse;\n   int                      Nstate, Nmeasurements;\n } dogleg_solverContext_t;\n\nSome of the members are copies of the data passed into C\u003cdogleg_optimize\u003e; some\nothers are internal state. Of potential interest are\n\n=over\n\n=item * C\u003ccommon\u003e is a cholmod_common structure used by all CHOLMOD calls. This\ncan be used for any extra CHOLMOD work the user may want to do\n\n=item * C\u003cbeforeStep\u003e contains the operating point of the optimum solution. The\nuser can analyze this data without the need to re-call the callback routine.\n\n=back\n\n=head3 dogleg_operatingPoint_t\n\nAn operating point of the solver. This is a part of C\u003cdogleg_solverContext_t\u003e.\nVarious variables describing the operating point such as B\u003cp\u003e, B\u003cJ\u003e, B\u003cx\u003e,\nB\u003cnorm2(x)\u003e and B\u003cJt x\u003e are available. All of the just-mentioned variables are\ncomputed at every step and are thus always valid.\n\n // an operating point of the solver\n typedef struct\n {\n   double*         p;\n   double*         x;\n   double          norm2_x;\n   union\n   {\n     cholmod_sparse* Jt;\n     double*         J_dense; // row-first: grad0, grad1, grad2, ...\n   };\n   double*         Jt_x;\n\n   // the cached update vectors. It's useful to cache these so that when a step is rejected, we can\n   // reuse these when we retry\n   double*        updateCauchy;\n   union\n   {\n     cholmod_dense* updateGN_cholmoddense;\n     double*        updateGN_dense;\n   };\n   double         updateCauchy_lensq, updateGN_lensq; // update vector lengths\n\n   // whether the current update vectors are correct or not\n   int updateCauchy_valid, updateGN_valid;\n\n   int didStepToEdgeOfTrustRegion;\n } dogleg_operatingPoint_t;\n\n=head2 Parameters\n\nThe optimization is controlled by several parameters. These can be set globally\nfor I\u003call\u003e callers of C\u003clibdogleg\u003e in a process using the C\u003cdogleg_set....()\u003e\nfunctions. Those global values are used by C\u003cdogleg_optimize\u003e and\nC\u003cdogleg_optimize_dense\u003e. Or these can be specified independently for each\ninvocation by passing a C\u003cparameters\u003e argument to C\u003cdogleg_optimize2\u003e or\nC\u003cdogleg_optimize_dense2\u003e. The latter is recommended because multiple instances\nof libdogleg in a single application would no longer conflict.\n\nIt is not required to set any of these, but it's highly recommended to set the\ninitial trust-region size and the termination thresholds to match the problem\nbeing solved. Furthermore, it's highly recommended for the problem being solved\nto be scaled so that every state variable affects the objective norm2( B\u003cx\u003e )\nequally. This makes this method's concept of \"trust region\" much more\nwell-defined and makes the termination criteria work correctly.\n\n=head3 dogleg_setMaxIterations\n\nTo set the maximum number of solver iterations, call\n\n void dogleg_setMaxIterations(int n);\n\n=head3 dogleg_setDebug\n\nTo turn on diagnostic output, call\n\n void dogleg_setDebug(int debug);\n\nwith a non-zero value for C\u003cdebug\u003e. Two separate diagnostic streams are\navailable: a verbose human-oriented stream, and a\nL\u003cvnlog|http://github.com/dkogan/vnlog\u003e.\n\nBy default, diagnostic output is disabled. The C\u003cdebug\u003e argument is a bit-mapped\ninteger:\n\n if(debug == 0                 ): no diagnostic output\n if(debug \u0026  DOGLEG_DEBUG_VNLOG): output vnlog diagnostics to stdout\n if(debug \u0026 ~DOGLEG_DEBUG_VNLOG): output human-oriented diagnostics to stderr\n\nC\u003cDOGLEG_DEBUG_VNLOG\u003e has a very high value, so if human diagnostics are\ndesired, the recommended call is:\n\n dogleg_setDebug(1);\n\n=head3 dogleg_setInitialTrustregion\n\nThe optimization method keeps track of a trust region size. Here, the trust region is a ball in\nR^Nstate. When the method takes a step B\u003cp\u003e -\u003e B\u003cp + delta_p\u003e, it makes sure that\n\nS\u003csqrt( norm2( B\u003cdelta_p\u003e ) ) \u003c trust region size\u003e.\n\nThe initial value of the trust region size can be set with\n\n void dogleg_setInitialTrustregion(double t);\n\nThe dogleg algorithm is efficient when recomputing a rejected step for a smaller trust region, so\nset the initial trust region size to a value larger to a reasonable estimate; the method will\nquickly shrink the trust region to the correct size.\n\n=head3 dogleg_setThresholds\n\nThe routine exits when the maximum number of iterations is exceeded, or a termination threshold is\nhit, whichever happens first. The termination thresholds are all designed to trigger when very slow\nprogress is being made. If all went well, this slow progress is due to us finding the optimum. There\nare 3 termination thresholds:\n\n=over\n\n=item * The function being minimized is E = norm2( B\u003cx\u003e ) where B\u003cx\u003e = I\u003cf\u003e(B\u003cp\u003e).\n\ndE/dB\u003cp\u003e = 2*B\u003cJt\u003e*B\u003cx\u003e where B\u003cJt\u003e is transpose(dB\u003cx\u003e/dB\u003cp\u003e).\n\n if( for every i  fabs(Jt_x[i]) \u003c JT_X_THRESHOLD )\n { we are done; }\n\n=item * The method takes discrete steps: B\u003cp\u003e -\u003e B\u003cp + delta_p\u003e\n\n if( for every i  fabs(delta_p[i]) \u003c UPDATE_THRESHOLD)\n { we are done; }\n\n=item * The method dynamically controls the trust region.\n\n if(trustregion \u003c TRUSTREGION_THRESHOLD)\n { we are done; }\n\n=back\n\nTo set these threholds, call\n\n void dogleg_setThresholds(double Jt_x, double update, double trustregion);\n\nTo leave a particular threshold alone, specify a negative value.\n\n=head3 dogleg_setTrustregionUpdateParameters\n\nThis function sets the parameters that control when and how the trust region is updated. The default\nvalues should work well in most cases, and shouldn't need to be tweaked.\n\nDeclaration looks like\n\n void dogleg_setTrustregionUpdateParameters(double downFactor, double downThreshold,\n                                            double upFactor,   double upThreshold);\n\nTo see what the parameters do, look at C\u003cevaluateStep_adjustTrustRegion\u003e in the source. Again, these\nshould just work as is.\n\n\n=head1 BUGS\n\nThe current implementation doesn't handle a singular B\u003cJtJ\u003e gracefully (B\u003cJtJ\u003e =\nB\u003cJt\u003e * B\u003cJ\u003e). Analytically, B\u003cJtJ\u003e is at worst positive semi-definite (has 0 eigenvalues). If a\nsingular B\u003cJtJ\u003e is ever encountered, from that point on, B\u003cJtJ\u003e + lambda*B\u003cI\u003e is inverted instead\nfor some positive constant lambda. This makes the matrix strictly positive definite, but is\nsloppy. At least I should vary lambda. In my current applications, a singular B\u003cJtJ\u003e only occurs if\nat a particular operating point the vector B\u003cx\u003e has no dependence at all on some elements of\nB\u003cp\u003e. In the general case other causes could exist, though.\n\nThere's an inefficiency in that the callback always returns B\u003cx\u003e and B\u003cJ\u003e. When I evaluate and\nreject a step, I do not end up using B\u003cJ\u003e at all. Dependng on the callback function, it may be\nbetter to ask for B\u003cx\u003e and then, if the step is accepted, to ask for B\u003cJ\u003e.\n\n=head1 AUTHOR\n\nDima Kogan, C\u003c\u003c \u003cdima@secretsauce.net\u003e \u003e\u003e\n\n=head1 LICENSE AND COPYRIGHT\n\nCopyright 2011 Oblong Industries\n          2017 Dima Kogan \u003cdima@secretsauce.net\u003e\n\nThis program is free software: you can redistribute it and/or modify it under the terms of the GNU\nLesser General Public License as published by the Free Software Foundation, either version 3 of the\nLicense, or (at your option) any later version.\n\nThis program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without\neven the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\nLesser General Public License for more details.\n\nThe full text of the license is available at L\u003chttp://www.gnu.org/licenses\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdkogan%2Flibdogleg","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdkogan%2Flibdogleg","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdkogan%2Flibdogleg/lists"}