From 2eef3e89c17e7fce552ae2dbc58c3b6307bd9f94 Mon Sep 17 00:00:00 2001 From: naoaki Date: Sun, 2 Nov 2008 04:50:00 +0000 Subject: [PATCH] Release for liblbfgs 1.6. git-svn-id: file:///home/svnrepos/software/liblbfgs/trunk@25 ecf4c44f-38d1-4fa4-9757-a0b4dd0349fc --- include/lbfgs.h | 20 +++++-- lib/lbfgs.c | 10 ++-- sample/Makefile.am | 1 + sample/sample.c | 7 ++- sample/sample.cpp | 126 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 154 insertions(+), 10 deletions(-) create mode 100644 sample/sample.cpp diff --git a/include/lbfgs.h b/include/lbfgs.h index b594c95..e499c6f 100644 --- a/include/lbfgs.h +++ b/include/lbfgs.h @@ -152,10 +152,10 @@ enum { LBFGS_LINESEARCH_DEFAULT = 0, /** MoreThuente method proposd by More and Thuente. */ LBFGS_LINESEARCH_MORETHUENTE = 0, - /** Backtracking method. */ - LBFGS_LINESEARCH_BACKTRACKING, /** Backtracking method with strong Wolfe condition. */ - LBFGS_LINESEARCH_BACKTRACKING_STRONGWOLFE, + LBFGS_LINESEARCH_BACKTRACKING, + /** Backtracking method with regular Wolfe condition. */ + LBFGS_LINESEARCH_BACKTRACKING_LOOSE, }; /** @@ -529,12 +529,24 @@ This library is used by: @section download Download -- Source code +- Source code libLBFGS is distributed under the term of the MIT license. @section changelog History +- Version 1.6 (2008-11-02): + - Improved line-search algorithm with strong Wolfe condition, which was + contributed by Takashi Imamichi. This routine is now default for + ::LBFGS_LINESEARCH_BACKTRACKING. The previous line search algorithm + with regular Wolfe condition is still available as + ::LBFGS_LINESEARCH_BACKTRACKING_LOOSE. + - Configurable stop index for L1-norm computation. A member variable + ::lbfgs_parameter_t::orthantwise_end was added to specify the index + number at which the library stops computing the L1 norm of the + variables. This is useful to prevent some variables from being + regularized by the OW-LQN method. + - A sample program written in C++ (sample/sample.cpp). - Version 1.5 (2008-07-10): - Configurable starting index for L1-norm computation. A member variable ::lbfgs_parameter_t::orthantwise_start was added to specify the index diff --git a/lib/lbfgs.c b/lib/lbfgs.c index 29b7956..efd4c4c 100644 --- a/lib/lbfgs.c +++ b/lib/lbfgs.c @@ -131,7 +131,7 @@ typedef int (*line_search_proc)( const lbfgs_parameter_t *param ); -static int line_search_backtracking( +static int line_search_backtracking_loose( int n, lbfgsfloatval_t *x, lbfgsfloatval_t *f, @@ -344,11 +344,11 @@ int lbfgs( linesearch = line_search_morethuente; break; case LBFGS_LINESEARCH_BACKTRACKING: - linesearch = line_search_backtracking; - break; - case LBFGS_LINESEARCH_BACKTRACKING_STRONGWOLFE: linesearch = line_search_backtracking_strong_wolfe; break; + case LBFGS_LINESEARCH_BACKTRACKING_LOOSE: + linesearch = line_search_backtracking_loose; + break; default: return LBFGSERR_INVALID_LINESEARCH; } @@ -609,7 +609,7 @@ lbfgs_exit: -static int line_search_backtracking( +static int line_search_backtracking_loose( int n, lbfgsfloatval_t *x, lbfgsfloatval_t *f, diff --git a/sample/Makefile.am b/sample/Makefile.am index c64b46c..c50983a 100644 --- a/sample/Makefile.am +++ b/sample/Makefile.am @@ -1,6 +1,7 @@ # $Id$ EXTRA_DIST = \ + sample.cpp \ sample.vcproj noinst_PROGRAMS = sample diff --git a/sample/sample.c b/sample/sample.c index 5ea5ecc..b5f4f0d 100644 --- a/sample/sample.c +++ b/sample/sample.c @@ -49,6 +49,7 @@ int main(int argc, char *argv) int i, ret = 0; lbfgsfloatval_t fx; lbfgsfloatval_t *x = lbfgs_malloc(N); + lbfgs_parameter_t param; if (x == NULL) { printf("ERROR: Failed to allocate a memory block for variables.\n"); @@ -61,11 +62,15 @@ int main(int argc, char *argv) x[i+1] = 1.0; } + /* Initialize the parameters for the L-BFGS optimization. */ + lbfgs_parameter_init(¶m); + /* param.linesearch = LBFGS_LINESEARCH_BACKTRACKING; */ + /* Start the L-BFGS optimization; this will invoke the callback functions evaluate() and progress() when necessary. */ - ret = lbfgs(N, x, &fx, evaluate, progress, NULL, NULL); + ret = lbfgs(N, x, &fx, evaluate, progress, NULL, ¶m); /* Report the result. */ printf("L-BFGS optimization terminated with status code = %d\n", ret); diff --git a/sample/sample.cpp b/sample/sample.cpp new file mode 100644 index 0000000..ad7be97 --- /dev/null +++ b/sample/sample.cpp @@ -0,0 +1,126 @@ +#include +#include + +class objective_function +{ +protected: + lbfgsfloatval_t *m_x; + +public: + objective_function() : m_x(NULL) + { + } + + virtual ~objective_function() + { + if (m_x != NULL) { + lbfgs_free(m_x); + m_x = NULL; + } + } + + int run(int N) + { + lbfgsfloatval_t fx; + lbfgsfloatval_t *m_x = lbfgs_malloc(N); + + if (m_x == NULL) { + printf("ERROR: Failed to allocate a memory block for variables.\n"); + return 1; + } + + /* Initialize the variables. */ + for (int i = 0;i < N;i += 2) { + m_x[i] = -1.2; + m_x[i+1] = 1.0; + } + + /* + Start the L-BFGS optimization; this will invoke the callback functions + evaluate() and progress() when necessary. + */ + int ret = lbfgs(N, m_x, &fx, _evaluate, _progress, this, NULL); + + /* Report the result. */ + printf("L-BFGS optimization terminated with status code = %d\n", ret); + printf(" fx = %f, x[0] = %f, x[1] = %f\n", fx, m_x[0], m_x[1]); + + return ret; + } + +protected: + static lbfgsfloatval_t _evaluate( + void *instance, + const lbfgsfloatval_t *x, + lbfgsfloatval_t *g, + const int n, + const lbfgsfloatval_t step + ) + { + return reinterpret_cast(instance)->evaluate(x, g, n, step); + } + + lbfgsfloatval_t evaluate( + const lbfgsfloatval_t *x, + lbfgsfloatval_t *g, + const int n, + const lbfgsfloatval_t step + ) + { + lbfgsfloatval_t fx = 0.0; + + for (int i = 0;i < n;i += 2) { + lbfgsfloatval_t t1 = 1.0 - x[i]; + lbfgsfloatval_t t2 = 10.0 * (x[i+1] - x[i] * x[i]); + g[i+1] = 20.0 * t2; + g[i] = -2.0 * (x[i] * g[i+1] + t1); + fx += t1 * t1 + t2 * t2; + } + return fx; + } + + static int _progress( + void *instance, + const lbfgsfloatval_t *x, + const lbfgsfloatval_t *g, + const lbfgsfloatval_t fx, + const lbfgsfloatval_t xnorm, + const lbfgsfloatval_t gnorm, + const lbfgsfloatval_t step, + int n, + int k, + int ls + ) + { + return reinterpret_cast(instance)->progress(x, g, fx, xnorm, gnorm, step, n, k, ls); + } + + int progress( + const lbfgsfloatval_t *x, + const lbfgsfloatval_t *g, + const lbfgsfloatval_t fx, + const lbfgsfloatval_t xnorm, + const lbfgsfloatval_t gnorm, + const lbfgsfloatval_t step, + int n, + int k, + int ls + ) + { + printf("Iteration %d:\n", k); + printf(" fx = %f, x[0] = %f, x[1] = %f\n", fx, x[0], x[1]); + printf(" xnorm = %f, gnorm = %f, step = %f\n", xnorm, gnorm, step); + printf("\n"); + return 0; + } +}; + + + +#define N 100 + +int main(int argc, char *argv) +{ + objective_function obj; + return obj.run(N); +}