Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a396674115 | |||
| 9fd52d7121 | |||
| f27bc17948 | |||
| 24235f44ca | |||
| 9d31decd84 | |||
| e3f737fbc0 | |||
| 038fb4a60d | |||
| 47b3e01cfb | |||
| aafcfc4279 | |||
| fe17b3fe0c | |||
| 2aea5ff2b9 | |||
| 3c1de9f322 | |||
| 4733fe57ac | |||
|
|
69a4b33b8f | ||
| 253b66d3c7 | |||
| 71d0a5e3aa | |||
| 2ff925cdc4 | |||
| 6083b80485 | |||
| 5b958b10ab |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -21,5 +21,7 @@
|
|||||||
*.app
|
*.app
|
||||||
|
|
||||||
|
|
||||||
|
.vscode/
|
||||||
build/
|
build/
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
*.sh
|
||||||
@@ -1,12 +1,19 @@
|
|||||||
cmake_minimum_required(VERSION 3.15.2)
|
cmake_minimum_required(VERSION 3.15.2)
|
||||||
# 设置cxx编译器
|
|
||||||
# 如果你使用别的编译器,请在这里修改
|
|
||||||
set(CMAKE_C_COMPILER /usr/local/bin/gcc-9)
|
|
||||||
set(CMAKE_CXX_COMPILER /usr/local/bin/g++-9)
|
|
||||||
# 设置工程名称和语言
|
# 设置工程名称和语言
|
||||||
project(LIBLBFGS VERSION 1.1.0)
|
project(LibLBFGS VERSION 1.1.0)
|
||||||
# 设置安装地址 改用homebrew安装后这一句就不需要了
|
# 添加配置配件编写的函数
|
||||||
# set(CMAKE_INSTALL_PREFIX /usr/local)
|
include(CMakePackageConfigHelpers)
|
||||||
|
|
||||||
|
if(${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Windows")
|
||||||
|
set(CMAKE_INSTALL_PREFIX D:/Library)
|
||||||
|
else()
|
||||||
|
set(CMAKE_INSTALL_PREFIX /opt/stow/liblbfgs)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "Platform: " ${CMAKE_HOST_SYSTEM_NAME})
|
||||||
|
message(STATUS "Install prefix: " ${CMAKE_INSTALL_PREFIX})
|
||||||
|
message(STATUS "Build type: " ${CMAKE_BUILD_TYPE})
|
||||||
|
|
||||||
# 添加编译选项
|
# 添加编译选项
|
||||||
option(HAVE_CONFIG_H "use config.h" ON)
|
option(HAVE_CONFIG_H "use config.h" ON)
|
||||||
option(_MSC_VER "use __msc_ver" OFF)
|
option(_MSC_VER "use __msc_ver" OFF)
|
||||||
@@ -16,5 +23,6 @@ configure_file(
|
|||||||
"${PROJECT_SOURCE_DIR}/config.h.in"
|
"${PROJECT_SOURCE_DIR}/config.h.in"
|
||||||
"${PROJECT_SOURCE_DIR}/src/lib/config.h"
|
"${PROJECT_SOURCE_DIR}/src/lib/config.h"
|
||||||
)
|
)
|
||||||
|
|
||||||
# 添加源文件地址
|
# 添加源文件地址
|
||||||
add_subdirectory(src/)
|
add_subdirectory(src/)
|
||||||
16
LibLBFGSConfig.cmake.in
Normal file
16
LibLBFGSConfig.cmake.in
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
@PACKAGE_INIT@
|
||||||
|
|
||||||
|
set(@PROJECT_NAME@_VERSION "@PROJECT_VERSION@")
|
||||||
|
set_and_check(@PROJECT_NAME@_INSTALL_PREFIX "${PACKAGE_PREFIX_DIR}")
|
||||||
|
set_and_check(@PROJECT_NAME@_INC_DIR "${PACKAGE_PREFIX_DIR}/include")
|
||||||
|
set_and_check(@PROJECT_NAME@_INCLUDE_DIR "${PACKAGE_PREFIX_DIR}/include")
|
||||||
|
set_and_check(@PROJECT_NAME@_LIB_DIR "${PACKAGE_PREFIX_DIR}/lib")
|
||||||
|
set_and_check(@PROJECT_NAME@_LIBRARY_DIR "${PACKAGE_PREFIX_DIR}/lib")
|
||||||
|
|
||||||
|
set(@PROJECT_NAME@_LIB lbfgs)
|
||||||
|
set(@PROJECT_NAME@_LIBRARY lbfgs)
|
||||||
|
|
||||||
|
# include target information
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
|
||||||
|
|
||||||
|
check_required_components(@PROJECT_NAME@)
|
||||||
@@ -13,13 +13,52 @@ set_target_properties(lbfgs_static PROPERTIES OUTPUT_NAME "lbfgs")
|
|||||||
set_target_properties(lbfgs PROPERTIES CLEAN_DIRECT_OUTPUT 1)
|
set_target_properties(lbfgs PROPERTIES CLEAN_DIRECT_OUTPUT 1)
|
||||||
set_target_properties(lbfgs_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
|
set_target_properties(lbfgs_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
|
||||||
# 设置动态库的版本号
|
# 设置动态库的版本号
|
||||||
set_target_properties(lbfgs PROPERTIES VERSION 1.1 SOVERSION 1.1)
|
set_target_properties(lbfgs PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR})
|
||||||
|
# 设置动态库的运行搜索地址
|
||||||
|
set_target_properties(lbfgs PROPERTIES INSTALL_RPATH /usr/local/lib)
|
||||||
|
set_target_properties(lbfgs_static PROPERTIES INSTALL_RPATH /usr/local/lib)
|
||||||
|
|
||||||
# 设置库文件的输出地址
|
# 设置库文件的输出地址
|
||||||
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
|
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
|
||||||
|
# 在LINUX中需添加math库
|
||||||
|
if(UNIX AND NOT APPLE)
|
||||||
|
message(STATUS "Linking math library.")
|
||||||
|
find_library(MATH_LIBRARY m)
|
||||||
|
find_library(MATH_A_LIBRARY libm.a)
|
||||||
|
target_link_libraries(lbfgs PUBLIC ${MATH_LIBRARY})
|
||||||
|
target_link_libraries(lbfgs_static ${MATH_A_LIBRARY})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# 添加编译命令
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3")
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
|
||||||
|
|
||||||
|
set(CONFIG_FILE_PATH lib/cmake/${PROJECT_NAME})
|
||||||
|
|
||||||
|
configure_package_config_file(${PROJECT_SOURCE_DIR}/${PROJECT_NAME}Config.cmake.in
|
||||||
|
${CMAKE_BINARY_DIR}/${PROJECT_NAME}Config.cmake
|
||||||
|
INSTALL_DESTINATION ${CONFIG_FILE_PATH})
|
||||||
|
|
||||||
|
write_basic_package_version_file(${CMAKE_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
|
||||||
|
VERSION ${PROJECT_VERSION}
|
||||||
|
COMPATIBILITY SameMajorVersion)
|
||||||
|
|
||||||
# 库的安装命令
|
# 库的安装命令
|
||||||
install(TARGETS lbfgs lbfgs_static
|
if(WIN32)
|
||||||
LIBRARY DESTINATION lib
|
install(TARGETS lbfgs DESTINATION lib)
|
||||||
ARCHIVE DESTINATION lib)
|
install(TARGETS lbfgs_static DESTINATION lib)
|
||||||
|
else()
|
||||||
|
install(TARGETS lbfgs lbfgs_static
|
||||||
|
EXPORT ${PROJECT_NAME}Targets
|
||||||
|
LIBRARY DESTINATION lib
|
||||||
|
ARCHIVE DESTINATION lib)
|
||||||
|
install(EXPORT ${PROJECT_NAME}Targets
|
||||||
|
DESTINATION ${CONFIG_FILE_PATH})
|
||||||
|
install(FILES
|
||||||
|
${CMAKE_BINARY_DIR}/${PROJECT_NAME}Config.cmake
|
||||||
|
${CMAKE_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
|
||||||
|
DESTINATION ${CONFIG_FILE_PATH})
|
||||||
|
endif()
|
||||||
# 头文件安装命令
|
# 头文件安装命令
|
||||||
install(FILES lib/lbfgs.h DESTINATION include)
|
install(FILES lib/lbfgs.h DESTINATION include)
|
||||||
|
|
||||||
@@ -27,23 +66,17 @@ install(FILES lib/lbfgs.h DESTINATION include)
|
|||||||
# 设置可执行文件的输出地址
|
# 设置可执行文件的输出地址
|
||||||
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
|
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
|
||||||
|
|
||||||
# 添加可执行文件 命令行
|
# 例子的编译方法
|
||||||
add_executable(lbfgs_sample sample/sample.c)
|
macro(add_sample name file)
|
||||||
# 为安装文件添加动态库的搜索地址
|
# 添加可执行文件 命令行
|
||||||
set_target_properties(lbfgs_sample PROPERTIES INSTALL_RPATH "/usr/local/lib")
|
add_executable(${name} sample/${file})
|
||||||
# 链接动态库
|
# 为安装文件添加动态库的搜索地址 在Windows下并没有什么用 直接忽略
|
||||||
target_link_libraries(lbfgs_sample PUBLIC lbfgs)
|
set_target_properties(${name} PROPERTIES INSTALL_RPATH ${PACKAGE_PREFIX_DIR}/lib)
|
||||||
|
# 链接动态库
|
||||||
|
target_link_libraries(${name} PUBLIC lbfgs)
|
||||||
|
endmacro()
|
||||||
|
|
||||||
# 添加可执行文件 命令行
|
add_sample(lbfgs_sample sample.c)
|
||||||
add_executable(lbfgs_sample2 sample/sample2.cpp)
|
add_sample(lbfgs_sample2 sample2.cpp)
|
||||||
# 为安装文件添加动态库的搜索地址
|
add_sample(lbfgs_sample3 sample3.cpp)
|
||||||
set_target_properties(lbfgs_sample2 PROPERTIES INSTALL_RPATH "/usr/local/lib")
|
add_sample(lbfgs_sample4 sample4.cpp)
|
||||||
# 链接动态库
|
|
||||||
target_link_libraries(lbfgs_sample2 PUBLIC lbfgs)
|
|
||||||
|
|
||||||
# 添加可执行文件 命令行
|
|
||||||
add_executable(lbfgs_sample3 sample/sample3.cpp)
|
|
||||||
# 为安装文件添加动态库的搜索地址
|
|
||||||
set_target_properties(lbfgs_sample3 PROPERTIES INSTALL_RPATH "/usr/local/lib")
|
|
||||||
# 链接动态库
|
|
||||||
target_link_libraries(lbfgs_sample3 PUBLIC lbfgs)
|
|
||||||
180
src/lib/lbfgs.c
180
src/lib/lbfgs.c
@@ -99,6 +99,7 @@ struct tag_callback_data {
|
|||||||
void *instance; // 用户给出的运行实例
|
void *instance; // 用户给出的运行实例
|
||||||
lbfgs_evaluate_t proc_evaluate; // 目标函数与模型梯度计算函数指针
|
lbfgs_evaluate_t proc_evaluate; // 目标函数与模型梯度计算函数指针
|
||||||
lbfgs_progress_t proc_progress; // 迭代过程监控函数指针
|
lbfgs_progress_t proc_progress; // 迭代过程监控函数指针
|
||||||
|
lbfgs_precondition_t proc_precondition; // 预优函数指针
|
||||||
};
|
};
|
||||||
typedef struct tag_callback_data callback_data_t;
|
typedef struct tag_callback_data callback_data_t;
|
||||||
|
|
||||||
@@ -147,6 +148,20 @@ static int line_search_backtracking(
|
|||||||
const lbfgs_parameter_t *param
|
const lbfgs_parameter_t *param
|
||||||
);
|
);
|
||||||
|
|
||||||
|
static int line_search_backtracking_quad(
|
||||||
|
int n,
|
||||||
|
lbfgsfloatval_t *x,
|
||||||
|
lbfgsfloatval_t *f,
|
||||||
|
lbfgsfloatval_t *g,
|
||||||
|
lbfgsfloatval_t *s,
|
||||||
|
lbfgsfloatval_t *stp,
|
||||||
|
const lbfgsfloatval_t* xp,
|
||||||
|
const lbfgsfloatval_t* gp,
|
||||||
|
lbfgsfloatval_t *wa,
|
||||||
|
callback_data_t *cd,
|
||||||
|
const lbfgs_parameter_t *param
|
||||||
|
);
|
||||||
|
|
||||||
static int line_search_backtracking_owlqn(
|
static int line_search_backtracking_owlqn(
|
||||||
int n,
|
int n,
|
||||||
lbfgsfloatval_t *x,
|
lbfgsfloatval_t *x,
|
||||||
@@ -250,7 +265,8 @@ int lbfgs(
|
|||||||
lbfgs_evaluate_t proc_evaluate,
|
lbfgs_evaluate_t proc_evaluate,
|
||||||
lbfgs_progress_t proc_progress,
|
lbfgs_progress_t proc_progress,
|
||||||
void *instance,
|
void *instance,
|
||||||
lbfgs_parameter_t *_param
|
lbfgs_parameter_t *_param,
|
||||||
|
lbfgs_precondition_t proc_precondition
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@@ -264,10 +280,13 @@ int lbfgs(
|
|||||||
const int m = param.m;
|
const int m = param.m;
|
||||||
|
|
||||||
lbfgsfloatval_t *xp = NULL;
|
lbfgsfloatval_t *xp = NULL;
|
||||||
lbfgsfloatval_t *g = NULL, *gp = NULL, *pg = NULL;
|
lbfgsfloatval_t *g = NULL, *gp = NULL, *pg = NULL; // gp (p for previous) pg (p for pesudo)
|
||||||
lbfgsfloatval_t *d = NULL, *w = NULL, *pf = NULL;
|
lbfgsfloatval_t *d = NULL, *w = NULL, *pf = NULL;
|
||||||
|
lbfgsfloatval_t *dp = NULL; // p for preconditioned (Add by Yi Zhang on 02-16-2022)
|
||||||
|
lbfgsfloatval_t *y2 = NULL; // Add by Yi Zhang on 02-16-2022
|
||||||
iteration_data_t *lm = NULL, *it = NULL;
|
iteration_data_t *lm = NULL, *it = NULL;
|
||||||
lbfgsfloatval_t ys, yy;
|
lbfgsfloatval_t ys, yy;
|
||||||
|
lbfgsfloatval_t Yk; // Add by Yi Zhang on 02-16-2022
|
||||||
lbfgsfloatval_t xnorm, gnorm, beta;
|
lbfgsfloatval_t xnorm, gnorm, beta;
|
||||||
lbfgsfloatval_t fx = 0.;
|
lbfgsfloatval_t fx = 0.;
|
||||||
lbfgsfloatval_t rate = 0.;
|
lbfgsfloatval_t rate = 0.;
|
||||||
@@ -280,6 +299,7 @@ int lbfgs(
|
|||||||
cd.instance = instance;
|
cd.instance = instance;
|
||||||
cd.proc_evaluate = proc_evaluate;
|
cd.proc_evaluate = proc_evaluate;
|
||||||
cd.proc_progress = proc_progress;
|
cd.proc_progress = proc_progress;
|
||||||
|
cd.proc_precondition = proc_precondition;
|
||||||
|
|
||||||
#if defined(USE_SSE) && (defined(__SSE__) || defined(__SSE2__))
|
#if defined(USE_SSE) && (defined(__SSE__) || defined(__SSE2__))
|
||||||
/* Round out the number of variables. */
|
/* Round out the number of variables. */
|
||||||
@@ -364,6 +384,11 @@ int lbfgs(
|
|||||||
case LBFGS_LINESEARCH_BACKTRACKING_STRONG_WOLFE:
|
case LBFGS_LINESEARCH_BACKTRACKING_STRONG_WOLFE:
|
||||||
linesearch = line_search_backtracking;
|
linesearch = line_search_backtracking;
|
||||||
break;
|
break;
|
||||||
|
case LBFGS_LINESEARCH_BACKTRACKING_ARMIJO_QUAD:
|
||||||
|
//case LBFGS_LINESEARCH_BACKTRACKING_WOLFE_QUAD:
|
||||||
|
//case LBFGS_LINESEARCH_BACKTRACKING_STRONG_WOLFE_QUAD:
|
||||||
|
linesearch = line_search_backtracking_quad;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return LBFGSERR_INVALID_LINESEARCH;
|
return LBFGSERR_INVALID_LINESEARCH;
|
||||||
}
|
}
|
||||||
@@ -379,6 +404,23 @@ int lbfgs(
|
|||||||
ret = LBFGSERR_OUTOFMEMORY;
|
ret = LBFGSERR_OUTOFMEMORY;
|
||||||
goto lbfgs_exit;
|
goto lbfgs_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add by Yi Zhang on 02-16-2022
|
||||||
|
y2 = (lbfgsfloatval_t*)vecalloc(n * sizeof(lbfgsfloatval_t));
|
||||||
|
if (y2 == NULL) {
|
||||||
|
ret = LBFGSERR_OUTOFMEMORY;
|
||||||
|
goto lbfgs_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cd.proc_precondition) {
|
||||||
|
dp = (lbfgsfloatval_t*)vecalloc(n * sizeof(lbfgsfloatval_t));
|
||||||
|
if (dp == NULL) {
|
||||||
|
ret = LBFGSERR_OUTOFMEMORY;
|
||||||
|
goto lbfgs_exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// End
|
||||||
|
|
||||||
// 初始化计算L1模的数组
|
// 初始化计算L1模的数组
|
||||||
if (param.orthantwise_c != 0.) {
|
if (param.orthantwise_c != 0.) {
|
||||||
/* Allocate working space for OW-LQN. */
|
/* Allocate working space for OW-LQN. */
|
||||||
@@ -438,6 +480,7 @@ int lbfgs(
|
|||||||
we assume the initial hessian matrix H_0 as the identity matrix.
|
we assume the initial hessian matrix H_0 as the identity matrix.
|
||||||
*/
|
*/
|
||||||
// 初始下降方向为梯度的反方向
|
// 初始下降方向为梯度的反方向
|
||||||
|
// LBFGS中下降方向为 -1*H_k*g_k
|
||||||
if (param.orthantwise_c == 0.) {
|
if (param.orthantwise_c == 0.) {
|
||||||
vecncpy(d, g, n); //拷贝数组 并反号(乘-1)
|
vecncpy(d, g, n); //拷贝数组 并反号(乘-1)
|
||||||
} else {
|
} else {
|
||||||
@@ -455,6 +498,7 @@ int lbfgs(
|
|||||||
vec2norm(&gnorm, pg, n);
|
vec2norm(&gnorm, pg, n);
|
||||||
}
|
}
|
||||||
// 为啥要保证xnorm大于等于1?不明白
|
// 为啥要保证xnorm大于等于1?不明白
|
||||||
|
// 答 参考头文件中的注释 如果模型参数的模长小于1则使用梯度的模长作为收敛性的测试指标
|
||||||
if (xnorm < 1.0) xnorm = 1.0;
|
if (xnorm < 1.0) xnorm = 1.0;
|
||||||
// 如果输入x即为最优化的解 则退出
|
// 如果输入x即为最优化的解 则退出
|
||||||
if (gnorm / xnorm <= param.epsilon) {
|
if (gnorm / xnorm <= param.epsilon) {
|
||||||
@@ -465,14 +509,14 @@ int lbfgs(
|
|||||||
/* Compute the initial step:
|
/* Compute the initial step:
|
||||||
step = 1.0 / sqrt(vecdot(d, d, n))
|
step = 1.0 / sqrt(vecdot(d, d, n))
|
||||||
*/
|
*/
|
||||||
// 计算估算的初始步长
|
// 计算估算的初始步长 这一步在实际应用中重要 在相似代码编写中需参考
|
||||||
vec2norminv(&step, d, n); // 计算数组L2模的倒数,与注释的内容等效
|
vec2norminv(&step, d, n); // 计算数组L2模的倒数,与注释的内容等效
|
||||||
|
|
||||||
k = 1;
|
k = 1;
|
||||||
end = 0;
|
end = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
/* Store the current position and gradient vectors. */
|
/* Store the current position and gradient vectors. */
|
||||||
veccpy(xp, x, n);
|
veccpy(xp, x, n); // p for previous
|
||||||
veccpy(gp, g, n);
|
veccpy(gp, g, n);
|
||||||
|
|
||||||
/* Search for an optimal step. */
|
/* Search for an optimal step. */
|
||||||
@@ -485,7 +529,8 @@ int lbfgs(
|
|||||||
param.orthantwise_c, param.orthantwise_start, param.orthantwise_end
|
param.orthantwise_c, param.orthantwise_start, param.orthantwise_end
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// 线性搜索错误 此时则退回到上一次迭代的位置并退出
|
|
||||||
|
// 返回值小于0则表示线性搜索错误 此时则退回到上一次迭代的位置并退出
|
||||||
if (ls < 0) {
|
if (ls < 0) {
|
||||||
/* Revert to the previous point. */
|
/* Revert to the previous point. */
|
||||||
veccpy(x, xp, n);
|
veccpy(x, xp, n);
|
||||||
@@ -560,6 +605,7 @@ int lbfgs(
|
|||||||
s_{k+1} = x_{k+1} - x_{k} = \step * d_{k}.
|
s_{k+1} = x_{k+1} - x_{k} = \step * d_{k}.
|
||||||
y_{k+1} = g_{k+1} - g_{k}.
|
y_{k+1} = g_{k+1} - g_{k}.
|
||||||
*/
|
*/
|
||||||
|
// 计算最新保存的s和y
|
||||||
it = &lm[end];
|
it = &lm[end];
|
||||||
vecdiff(it->s, x, xp, n); // 计算两个数组的差 it->s = x - xp
|
vecdiff(it->s, x, xp, n); // 计算两个数组的差 it->s = x - xp
|
||||||
vecdiff(it->y, g, gp, n);
|
vecdiff(it->y, g, gp, n);
|
||||||
@@ -582,8 +628,12 @@ int lbfgs(
|
|||||||
Mathematics of Computation, Vol. 35, No. 151,
|
Mathematics of Computation, Vol. 35, No. 151,
|
||||||
pp. 773--782, 1980.
|
pp. 773--782, 1980.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// m小于迭代次数
|
||||||
bound = (m <= k) ? m : k;
|
bound = (m <= k) ? m : k;
|
||||||
++k;
|
++k;
|
||||||
|
|
||||||
|
// end+1等于m则将其重置为0 循环保存
|
||||||
end = (end + 1) % m;
|
end = (end + 1) % m;
|
||||||
|
|
||||||
/* Compute the steepest direction. */
|
/* Compute the steepest direction. */
|
||||||
@@ -605,7 +655,32 @@ int lbfgs(
|
|||||||
vecadd(d, it->y, -it->alpha, n);
|
vecadd(d, it->y, -it->alpha, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
vecscale(d, ys / yy, n); // 适当缩放d的大小
|
// Annotated by Yi Zhang on 02-16-2022
|
||||||
|
//vecscale(d, ys / yy, n); // 适当缩放d的大小
|
||||||
|
|
||||||
|
// Add by Yi Zhang on 02-16-2022
|
||||||
|
// Wah June Leong & Chuei Yee Chen (2013) A class of diagonal preconditioners for limited memory BFGS method,
|
||||||
|
// Optimization Methods and Software, 28:2, 379-392, DOI: 10.1080/10556788.2011.653356
|
||||||
|
// 我们在这里提供一个预优函数的接口 需还原则删除下面的代码段 同时取消上面一行注释
|
||||||
|
if (cd.proc_precondition) {
|
||||||
|
if (param.orthantwise_c == 0.) {
|
||||||
|
cd.proc_precondition(cd.instance, x, g, d, dp, n);
|
||||||
|
} else {
|
||||||
|
cd.proc_precondition(cd.instance, x, pg, d, dp, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
veccpy(d, dp, n);
|
||||||
|
} else if (ys < yy) {
|
||||||
|
// 这里假设了初始的Hessian矩阵为单位阵乘以ys/yy
|
||||||
|
vecscale(d, ys / yy, n); // 适当缩放d的大小
|
||||||
|
} else {
|
||||||
|
// 假设初始的Hessian矩阵为 I + [(ys - yy)/tr(Yk)]diag(y2)
|
||||||
|
veccpy(y2, lm[end].y, n);
|
||||||
|
vecmul(y2, lm[end].y, n);
|
||||||
|
vecdot(&Yk, y2, y2, n);
|
||||||
|
vecadd(d, y2, (ys-yy)/Yk, n);
|
||||||
|
}
|
||||||
|
// End
|
||||||
|
|
||||||
for (i = 0;i < bound;++i) {
|
for (i = 0;i < bound;++i) {
|
||||||
it = &lm[j];
|
it = &lm[j];
|
||||||
@@ -657,6 +732,14 @@ lbfgs_exit:
|
|||||||
vecfree(g);
|
vecfree(g);
|
||||||
vecfree(xp);
|
vecfree(xp);
|
||||||
|
|
||||||
|
// Add by Yi Zhang on 02-16-2022
|
||||||
|
vecfree(y2);
|
||||||
|
|
||||||
|
if (cd.proc_precondition) {
|
||||||
|
vecfree(dp);
|
||||||
|
}
|
||||||
|
// End
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -881,6 +964,91 @@ static int line_search_backtracking(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int line_search_backtracking_quad(
|
||||||
|
int n,
|
||||||
|
lbfgsfloatval_t *x,
|
||||||
|
lbfgsfloatval_t *f,
|
||||||
|
lbfgsfloatval_t *g,
|
||||||
|
lbfgsfloatval_t *s,
|
||||||
|
lbfgsfloatval_t *stp,
|
||||||
|
const lbfgsfloatval_t* xp,
|
||||||
|
const lbfgsfloatval_t* gp,
|
||||||
|
lbfgsfloatval_t *wp,
|
||||||
|
callback_data_t *cd,
|
||||||
|
const lbfgs_parameter_t *param
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
lbfgsfloatval_t dg, stp2;
|
||||||
|
lbfgsfloatval_t finit, dginit = 0., dgtest;
|
||||||
|
const lbfgsfloatval_t dec = 0.5;
|
||||||
|
|
||||||
|
/* Check the input parameters for errors. */
|
||||||
|
if (*stp <= 0.) {
|
||||||
|
return LBFGSERR_INVALIDPARAMETERS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compute the initial gradient in the search direction. */
|
||||||
|
vecdot(&dginit, g, s, n); //计算点积 g为梯度方向 s为下降方向
|
||||||
|
|
||||||
|
/* Make sure that s points to a descent direction. */
|
||||||
|
if (0 < dginit) {
|
||||||
|
return LBFGSERR_INCREASEGRADIENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The initial value of the objective function. */
|
||||||
|
finit = *f;
|
||||||
|
dgtest = param->ftol * dginit; // ftol 大概为 function tolerance
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
veccpy(x, xp, n);
|
||||||
|
vecadd(x, s, *stp, n); // vecadd x += (*stp)*s
|
||||||
|
|
||||||
|
/* Evaluate the function and gradient values. */
|
||||||
|
// 这里我们发现的cd的用法,即传递函数指针
|
||||||
|
*f = cd->proc_evaluate(cd->instance, x, g, cd->n, *stp);
|
||||||
|
|
||||||
|
++count;
|
||||||
|
|
||||||
|
// 充分下降条件
|
||||||
|
if (*f > finit + *stp * dgtest) {
|
||||||
|
stp2 = 0.5*dginit*(*stp)*(*stp)/(finit - (*f) + dginit*(*stp));
|
||||||
|
if (stp2 < 0) {
|
||||||
|
(*stp) *= dec;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
(*stp) = stp2;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// 充分下降条件满足并搜索方法为backtracking,搜索条件为Armijo,则可以退出了。否则更新步长,继续搜索。
|
||||||
|
/* The sufficient decrease condition (Armijo condition). */
|
||||||
|
if (param->linesearch == LBFGS_LINESEARCH_BACKTRACKING_ARMIJO_QUAD) {
|
||||||
|
/* Exit with the Armijo condition. */
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 以下情况返回的步长不能保证满足搜索条件
|
||||||
|
if (*stp < param->min_step) {
|
||||||
|
/* The step is the minimum value. */
|
||||||
|
// 退出 此时步长小于最小步长
|
||||||
|
return LBFGSERR_MINIMUMSTEP;
|
||||||
|
}
|
||||||
|
if (*stp > param->max_step) {
|
||||||
|
/* The step is the maximum value. */
|
||||||
|
// 退出 此时步长大于最大步长
|
||||||
|
return LBFGSERR_MAXIMUMSTEP;
|
||||||
|
}
|
||||||
|
if (param->max_linesearch <= count) {
|
||||||
|
/* Maximum number of iteration. */
|
||||||
|
// 退出 线性搜索次数超过了最大限制
|
||||||
|
return LBFGSERR_MAXIMUMLINESEARCH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 还是反向搜索 只是添加了L1模方向
|
// 还是反向搜索 只是添加了L1模方向
|
||||||
static int line_search_backtracking_owlqn(
|
static int line_search_backtracking_owlqn(
|
||||||
int n,
|
int n,
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ extern "C" {
|
|||||||
#endif/*__cplusplus*/
|
#endif/*__cplusplus*/
|
||||||
|
|
||||||
// 算法库使用的浮点类型定义
|
// 算法库使用的浮点类型定义
|
||||||
|
// 结合后面的定义可见我们现在使用的其实就是 double 类型
|
||||||
/*
|
/*
|
||||||
* The default precision of floating point values is 64bit (double).
|
* The default precision of floating point values is 64bit (double).
|
||||||
*/
|
*/
|
||||||
@@ -196,6 +197,14 @@ enum {
|
|||||||
* a is the step length.
|
* a is the step length.
|
||||||
*/
|
*/
|
||||||
LBFGS_LINESEARCH_BACKTRACKING_STRONG_WOLFE = 3,
|
LBFGS_LINESEARCH_BACKTRACKING_STRONG_WOLFE = 3,
|
||||||
|
|
||||||
|
LBFGS_LINESEARCH_BACKTRACKING_ARMIJO_QUAD = 4,
|
||||||
|
|
||||||
|
//LBFGS_LINESEARCH_BACKTRACKING_QUAD = 5,
|
||||||
|
|
||||||
|
//LBFGS_LINESEARCH_BACKTRACKING_WOLFE_QUAD = 5,
|
||||||
|
|
||||||
|
//LBFGS_LINESEARCH_BACKTRACKING_STRONG_WOLFE_QUAD = 6,
|
||||||
};
|
};
|
||||||
|
|
||||||
// L-BFGS参数类型。参数很多,简要说明如下:
|
// L-BFGS参数类型。参数很多,简要说明如下:
|
||||||
@@ -204,8 +213,8 @@ enum {
|
|||||||
// past 以delta(不同迭代次数的目标函数值)为基础的迭代终止条件数,past代表了以多少迭代次数之前的目标函数值作为delta计算的间隔,默认值为0,
|
// past 以delta(不同迭代次数的目标函数值)为基础的迭代终止条件数,past代表了以多少迭代次数之前的目标函数值作为delta计算的间隔,默认值为0,
|
||||||
// 即不以delta为迭代终止条件。
|
// 即不以delta为迭代终止条件。
|
||||||
// delta (f' - f) / f 不同迭代次数时目标函数之差与当前目标函数值之比,但past不为0时会计算。
|
// delta (f' - f) / f 不同迭代次数时目标函数之差与当前目标函数值之比,但past不为0时会计算。
|
||||||
// max_iterations 最大迭代次数
|
// max_iterations 最大迭代次数,为0时表示一直迭代到终止条件被满足或出现其他错误。
|
||||||
// linesearch 线性搜索方式,由此文件上部枚举类型定义。
|
// linesearch 线性搜索方式,由此文件前述枚举类型定义。
|
||||||
// max_linesearch 每次迭代中线性搜索的最大次数,默认值为40
|
// max_linesearch 每次迭代中线性搜索的最大次数,默认值为40
|
||||||
// min_step 线性搜索中的最小步长,默认值为1e-20
|
// min_step 线性搜索中的最小步长,默认值为1e-20
|
||||||
// max_step 线性搜索中的最大步长,默认值为1e+20
|
// max_step 线性搜索中的最大步长,默认值为1e+20
|
||||||
@@ -462,6 +471,30 @@ typedef int (*lbfgs_progress_t)(
|
|||||||
int ls
|
int ls
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback interface to implement the preconditioning process.
|
||||||
|
*
|
||||||
|
* The lbfgs() function call this function for each iteration. Implementing
|
||||||
|
* this function, a client program can preform the preconditioning process.
|
||||||
|
*
|
||||||
|
* @param instance The user data sent for lbfgs() function by the client.
|
||||||
|
* @param x The current values of variables.
|
||||||
|
* @param g The current gradient values of variables.
|
||||||
|
* @param d The current values of search directions.
|
||||||
|
* @param d_pre The values of search directions being preconditioned.
|
||||||
|
* The callback function must compute these values.
|
||||||
|
* @param n The number of variables.
|
||||||
|
*/
|
||||||
|
typedef void (*lbfgs_precondition_t)(
|
||||||
|
void *instance,
|
||||||
|
const lbfgsfloatval_t *x,
|
||||||
|
const lbfgsfloatval_t *g,
|
||||||
|
const lbfgsfloatval_t *d,
|
||||||
|
lbfgsfloatval_t *d_pre,
|
||||||
|
const int n
|
||||||
|
);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
A user must implement a function compatible with ::lbfgs_evaluate_t (evaluation
|
A user must implement a function compatible with ::lbfgs_evaluate_t (evaluation
|
||||||
callback) and pass the pointer to the callback function to lbfgs() arguments.
|
callback) and pass the pointer to the callback function to lbfgs() arguments.
|
||||||
@@ -549,7 +582,8 @@ int lbfgs(
|
|||||||
lbfgs_evaluate_t proc_evaluate,
|
lbfgs_evaluate_t proc_evaluate,
|
||||||
lbfgs_progress_t proc_progress,
|
lbfgs_progress_t proc_progress,
|
||||||
void *instance,
|
void *instance,
|
||||||
lbfgs_parameter_t *param
|
lbfgs_parameter_t *param,
|
||||||
|
lbfgs_precondition_t proc_precondition
|
||||||
);
|
);
|
||||||
|
|
||||||
// 将一个参数类型内的全部变量值重置为默认值
|
// 将一个参数类型内的全部变量值重置为默认值
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ int main(int argc, char *argv[])
|
|||||||
Start the L-BFGS optimization; this will invoke the callback functions
|
Start the L-BFGS optimization; this will invoke the callback functions
|
||||||
evaluate() and progress() when necessary.
|
evaluate() and progress() when necessary.
|
||||||
*/
|
*/
|
||||||
ret = lbfgs(N, x, &fx, evaluate, progress, NULL, ¶m);
|
ret = lbfgs(N, x, &fx, evaluate, progress, NULL, ¶m, NULL);
|
||||||
|
|
||||||
/* Report the result. */
|
/* Report the result. */
|
||||||
printf("L-BFGS optimization terminated with status code = %d\n", ret);
|
printf("L-BFGS optimization terminated with status code = %d\n", ret);
|
||||||
|
|||||||
@@ -39,10 +39,16 @@ public:
|
|||||||
Start the L-BFGS optimization; this will invoke the callback functions
|
Start the L-BFGS optimization; this will invoke the callback functions
|
||||||
evaluate() and progress() when necessary.
|
evaluate() and progress() when necessary.
|
||||||
*/
|
*/
|
||||||
int ret = lbfgs(N, m_x, &fx, _evaluate, _progress, this, NULL);
|
lbfgs_parameter_t self_para;
|
||||||
|
lbfgs_parameter_init(&self_para);
|
||||||
|
self_para.epsilon = 1e-7;
|
||||||
|
//self_para.linesearch = LBFGS_LINESEARCH_BACKTRACKING_ARMIJO_QUAD;
|
||||||
|
//self_para.ftol = 1e-3;
|
||||||
|
|
||||||
|
int ret = lbfgs(N, m_x, &fx, _evaluate, _progress, this, &self_para, NULL);
|
||||||
|
|
||||||
/* Report the result. */
|
/* Report the result. */
|
||||||
printf("L-BFGS optimization terminated with status code = %d\n", ret);
|
printf("L-BFGS optimization terminated with status: %s\n", lbfgs_strerror(ret));
|
||||||
printf(" fx = %f, x[0] = %f, x[1] = %f\n", fx, m_x[0], m_x[1]);
|
printf(" fx = %f, x[0] = %f, x[1] = %f\n", fx, m_x[0], m_x[1]);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@@ -111,7 +117,7 @@ protected:
|
|||||||
{
|
{
|
||||||
printf("Iteration %d:\n", k);
|
printf("Iteration %d:\n", k);
|
||||||
printf(" fx = %f, x[0] = %f, x[1] = %f\n", fx, x[0], x[1]);
|
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(" xnorm = %f, gnorm = %f, step = %f, convergence = %e\n", xnorm, gnorm, step, gnorm/xnorm);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ int TEST_FUNC::Progress(const lbfgsfloatval_t *x, const lbfgsfloatval_t *g, cons
|
|||||||
const lbfgsfloatval_t xnorm, const lbfgsfloatval_t gnorm, const lbfgsfloatval_t step, const lbfgs_parameter_t param,
|
const lbfgsfloatval_t xnorm, const lbfgsfloatval_t gnorm, const lbfgsfloatval_t step, const lbfgs_parameter_t param,
|
||||||
int n, int k, int ls)
|
int n, int k, int ls)
|
||||||
{
|
{
|
||||||
clog << "iteration times: " << k << " fx = " << fx << " gnorm/xnorm = " << gnorm/xnorm << endl;
|
clog << "iteration times: " << k << " fx = " << fx << " gnorm/xnorm = " << gnorm/(xnorm>1.0?xnorm:1.0) << endl;
|
||||||
clog << x[0] << " " << x[1] << " " << x[2] << endl;
|
clog << x[0] << " " << x[1] << " " << x[2] << endl;
|
||||||
|
|
||||||
if (fx < 1e-10) return 1; //这里我们设置一个方程组的整体目标函数值作为终止条件 因为此方程组在0值处梯度不为0 无法使用梯度条件
|
if (fx < 1e-10) return 1; //这里我们设置一个方程组的整体目标函数值作为终止条件 因为此方程组在0值处梯度不为0 无法使用梯度条件
|
||||||
@@ -83,11 +83,12 @@ int TEST_FUNC::Routine()
|
|||||||
|
|
||||||
lbfgs_parameter_t self_para;
|
lbfgs_parameter_t self_para;
|
||||||
lbfgs_parameter_init(&self_para);
|
lbfgs_parameter_init(&self_para);
|
||||||
|
self_para.past = 2;
|
||||||
//self_para.min_step = 1e-30;
|
//self_para.min_step = 1e-30;
|
||||||
//self_para.max_linesearch = 40;
|
//self_para.max_linesearch = 40;
|
||||||
//self_para.linesearch = LBFGS_LINESEARCH_BACKTRACKING_WOLFE;
|
//self_para.linesearch = LBFGS_LINESEARCH_BACKTRACKING_WOLFE;
|
||||||
|
|
||||||
int ret = lbfgs(3, m_x, &fx, _Func, _Progress, this, &self_para);
|
int ret = lbfgs(3, m_x, &fx, _Func, _Progress, this, &self_para, NULL);
|
||||||
|
|
||||||
clog << "L-BFGS optimization terminated with status: " << endl << lbfgs_strerror(ret) << endl;
|
clog << "L-BFGS optimization terminated with status: " << endl << lbfgs_strerror(ret) << endl;
|
||||||
clog << m_x[0] << " " << m_x[1] << " " << m_x[2] << endl;
|
clog << m_x[0] << " " << m_x[1] << " " << m_x[2] << endl;
|
||||||
|
|||||||
204
src/sample/sample4.cpp
Normal file
204
src/sample/sample4.cpp
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
#include "iostream"
|
||||||
|
#include "cmath"
|
||||||
|
#include "ctime"
|
||||||
|
#include "random"
|
||||||
|
|
||||||
|
#include "../lib/lbfgs.h"
|
||||||
|
|
||||||
|
using std::clog;
|
||||||
|
using std::endl;
|
||||||
|
|
||||||
|
#define M 120
|
||||||
|
#define N 100
|
||||||
|
|
||||||
|
inline lbfgsfloatval_t scalernd(lbfgsfloatval_t l, lbfgsfloatval_t h)
|
||||||
|
{
|
||||||
|
return (h-l)*rand()*1.0/RAND_MAX + l;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void vecrnd(lbfgsfloatval_t *a, lbfgsfloatval_t l, lbfgsfloatval_t h, int n)
|
||||||
|
{
|
||||||
|
srand(time(nullptr));
|
||||||
|
for (size_t i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
a[i] = (h-l)*rand()*1.0/RAND_MAX + l;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline lbfgsfloatval_t max_diff(const lbfgsfloatval_t *a, const lbfgsfloatval_t *b, int n)
|
||||||
|
{
|
||||||
|
lbfgsfloatval_t tmp, max = -1.0;
|
||||||
|
for (int i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
tmp = sqrt((a[i] - b[i])*(a[i] - b[i]));
|
||||||
|
max = tmp>max?tmp:max;
|
||||||
|
}
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
class TEST_FUNC
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TEST_FUNC();
|
||||||
|
virtual ~TEST_FUNC();
|
||||||
|
|
||||||
|
static lbfgsfloatval_t _Func(void *instance, const lbfgsfloatval_t *x, lbfgsfloatval_t *g,
|
||||||
|
const int n, const lbfgsfloatval_t step)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<TEST_FUNC*>(instance)->Func(x, g, n, step);
|
||||||
|
}
|
||||||
|
|
||||||
|
lbfgsfloatval_t Func(const lbfgsfloatval_t *x, lbfgsfloatval_t *g,
|
||||||
|
const int n, const lbfgsfloatval_t step);
|
||||||
|
|
||||||
|
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, const lbfgs_parameter_t param,
|
||||||
|
int n, int k, int ls)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<TEST_FUNC*>(instance)->Progress(x, g, fx, xnorm, gnorm, step, param, 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, const lbfgs_parameter_t param,
|
||||||
|
int n, int k, int ls);
|
||||||
|
|
||||||
|
static void _Precondition(void *instance, const lbfgsfloatval_t *x, const lbfgsfloatval_t *g, const lbfgsfloatval_t *d,
|
||||||
|
lbfgsfloatval_t *d_pre, const int n)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<TEST_FUNC*>(instance)->Precondition(x, g, d, d_pre, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Precondition(const lbfgsfloatval_t *x, const lbfgsfloatval_t *g, const lbfgsfloatval_t *d,
|
||||||
|
lbfgsfloatval_t *d_pre, const int n);
|
||||||
|
|
||||||
|
int Routine();
|
||||||
|
private:
|
||||||
|
lbfgsfloatval_t **kernel;
|
||||||
|
lbfgsfloatval_t *x, *m, *mid, *d;
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_FUNC::TEST_FUNC()
|
||||||
|
{
|
||||||
|
kernel = new lbfgsfloatval_t* [M];
|
||||||
|
for (size_t i = 0; i < M; i++)
|
||||||
|
{
|
||||||
|
kernel[i] = new lbfgsfloatval_t [N];
|
||||||
|
}
|
||||||
|
|
||||||
|
x = new lbfgsfloatval_t [N];
|
||||||
|
m = new lbfgsfloatval_t [N];
|
||||||
|
mid = new lbfgsfloatval_t [M];
|
||||||
|
d = new lbfgsfloatval_t [M];
|
||||||
|
|
||||||
|
srand(time(nullptr));
|
||||||
|
for (size_t i = 0; i < M; i++)
|
||||||
|
{
|
||||||
|
for (size_t j = 0; j < N; j++)
|
||||||
|
{
|
||||||
|
kernel[i][j] = scalernd(-2.0, 2.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vecrnd(m, 1.0, 2.0, N);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < M; i++)
|
||||||
|
{
|
||||||
|
d[i] = 0.0;
|
||||||
|
for (size_t j = 0; j < N; j++)
|
||||||
|
{
|
||||||
|
d[i] += kernel[i][j] * m[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_FUNC::~TEST_FUNC()
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
delete[] kernel[i];
|
||||||
|
}
|
||||||
|
delete[] kernel;
|
||||||
|
|
||||||
|
delete[] x;
|
||||||
|
delete[] m;
|
||||||
|
delete[] mid;
|
||||||
|
delete[] d;
|
||||||
|
}
|
||||||
|
|
||||||
|
lbfgsfloatval_t TEST_FUNC::Func(const lbfgsfloatval_t *x, lbfgsfloatval_t *g,
|
||||||
|
const int n, const lbfgsfloatval_t step)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < M; i++)
|
||||||
|
{
|
||||||
|
mid[i] = 0.0;
|
||||||
|
for (size_t j = 0; j < N; j++)
|
||||||
|
{
|
||||||
|
mid[i] += kernel[i][j] * x[j];
|
||||||
|
}
|
||||||
|
mid[i] -= d[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
lbfgsfloatval_t fx = 0;
|
||||||
|
for (size_t i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
fx += mid[i]*mid[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t j = 0; j < N; j++)
|
||||||
|
{
|
||||||
|
g[j] = 0.0;
|
||||||
|
for (size_t i = 0; i < M; i++)
|
||||||
|
{
|
||||||
|
g[j] += kernel[i][j]*mid[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fx;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TEST_FUNC::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, const lbfgs_parameter_t param,
|
||||||
|
int n, int k, int ls)
|
||||||
|
{
|
||||||
|
clog << "\riteration times: " << k << " fx = " << fx << " gnorm/xnorm = " << gnorm/(xnorm>1.0?xnorm:1.0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TEST_FUNC::Precondition(const lbfgsfloatval_t *x, const lbfgsfloatval_t *g, const lbfgsfloatval_t *d,
|
||||||
|
lbfgsfloatval_t *d_pre, const int n)
|
||||||
|
{
|
||||||
|
for (size_t j = 0; j < N; j++)
|
||||||
|
{
|
||||||
|
d_pre[j] = 0.0;
|
||||||
|
for (size_t i = 0; i < M; i++)
|
||||||
|
{
|
||||||
|
d_pre[j] += kernel[i][j]*kernel[i][j];
|
||||||
|
}
|
||||||
|
d_pre[j] = d[j]/d_pre[j];
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TEST_FUNC::Routine()
|
||||||
|
{
|
||||||
|
lbfgsfloatval_t fx;
|
||||||
|
|
||||||
|
lbfgs_parameter_t self_para;
|
||||||
|
lbfgs_parameter_init(&self_para);
|
||||||
|
self_para.epsilon = 1e-7;
|
||||||
|
self_para.linesearch = LBFGS_LINESEARCH_BACKTRACKING_ARMIJO_QUAD;
|
||||||
|
self_para.ftol = 1e-3;
|
||||||
|
|
||||||
|
int ret = lbfgs(N, x, &fx, _Func, _Progress, this, &self_para, _Precondition);
|
||||||
|
|
||||||
|
clog << endl << "L-BFGS optimization terminated with status: " << lbfgs_strerror(ret) << endl;
|
||||||
|
clog << "Maximal difference = " << max_diff(x, m, N) << endl;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
TEST_FUNC test;
|
||||||
|
test.Routine();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user