40 return residual <= cfg->
abs_tol ||
41 (initial_residual > 0.0 &&
42 residual <= cfg->
rel_tol * initial_residual);
51 lmmc_scaled_sumsq_init(&acc);
52 for (i = 0; i < v->
size; ++i) {
54 if (!isfinite(value_abs)) {
57 lmmc_scaled_sumsq_add(&acc, value_abs);
59 return lmmc_scaled_sumsq_norm(&acc);
78 return x != NULL && out != NULL && x->
data != NULL &&
95 if (!isfinite(norm)) {
113static int optimize_workspace_count(
114 size_t n,
size_t vectors,
size_t matrices,
size_t extra,
size_t* count)
116 size_t vector_count, matrix_count = 0;
117 if (!lmmc_safe_mul_size(n, vectors, &vector_count)) {
121 if (!lmmc_safe_mul_size(n, n, &matrix_count) ||
122 !lmmc_safe_mul_size(matrix_count, matrices, &matrix_count)) {
126 return lmmc_safe_add_size(vector_count, matrix_count, count) &&
127 lmmc_safe_add_size(*count, extra, count);
131 size_t n,
size_t vectors,
size_t matrices,
size_t extra,
134 size_t count, scalar_bytes, pivot_bytes = 0, bytes;
136 if (!optimize_workspace_count(n, vectors, matrices, extra, &count) ||
137 !lmmc_safe_mul_size(count,
sizeof(
lmmc_real_t), &scalar_bytes)) {
141 if (!lmmc_safe_mul_size(n,
sizeof(
size_t), &pivot_bytes) ||
142 !lmmc_safe_add_size(pivot_bytes, alignment - 1, &pivot_bytes)) {
145 pivot_bytes -= pivot_bytes % alignment;
147 if (!lmmc_safe_add_size(pivot_bytes, scalar_bytes, &bytes)) {
180 if (!isfinite(perturbed_x) || perturbed_x == x->
data[j]) {
181 perturbed_x = x->
data[j] - h;
183 if (!isfinite(perturbed_x) || perturbed_x == x->
data[j]) {
184 perturbed_x = nextafter(x->
data[j], 0.0);
186 h = perturbed_x - x->
data[j];
187 if (!isfinite(perturbed_x) || !isfinite(h) || h == 0.0) {
190 x_pert->
data[j] = perturbed_x;
200 for (i = 0; i < Fx->
size; ++i) {
202 if (!isfinite(F_pert->
data[i]) || !isfinite(Fx->
data[i])) {
205 derivative = (F_pert->
data[i] - Fx->
data[i]) / h;
206 if (!isfinite(derivative)) {
209 matrix->
data[i * matrix->
stride + j] = derivative;
221 return J(x, matrix, user_data);
223 for (j = 0; j < x->
size; ++j) {
229 status = F(x_pert, F_pert, user_data);
233 status = optimize_difference_column(Fx, F_pert, h, j, matrix);
250 for (attempt = 0; attempt < attempts; ++attempt) {
251 for (i = 0; i < x->
size; ++i) {
253 trial->
data[i] = x->
data[i] - step * direction->
data[i];
255 trial->
data[i] = x->
data[i] + step * direction->
data[i];
259 if (next <= *value + c1 * step * derivative) {
double lmmc_real_t
Public and internal LMMC real type.
#define LMMC_REAL_EPSILON
既有算法的经验近似阈值,非机器 epsilon。
void lmmc_diagnostic_emit(const lmmc_diagnostic_sink_t *sink, const lmmc_diagnostic_t *diagnostic)
通过调用方持有的接收器发送一个诊断事件;空接收器直接完成.
void * lmmc_memory_alloc(size_t size)
int lmmc_optimize_armijo(lmmc_opt_obj_t obj, void *user_data, const lmmc_vec_t *x, const lmmc_vec_t *direction, lmmc_vec_t *trial, lmmc_real_t *value, lmmc_real_t derivative, int attempts, int subtract)
lmmc_real_t lmmc_optimize_norm(const lmmc_vec_t *v)
计算向量的 L2 范数。
int lmmc_optimize_config_is_valid(const lmmc_optimize_config_t *cfg)
lmmc_mat_t lmmc_opt_workspace_matrix(lmmc_opt_workspace_t *work, size_t n)
lmmc_status_t lmmc_optimize_jacobian(lmmc_opt_func_t F, lmmc_opt_jac_t J, void *user_data, const lmmc_vec_t *x, const lmmc_vec_t *Fx, lmmc_mat_t *matrix, lmmc_vec_t *x_pert, lmmc_vec_t *F_pert)
临时向量由外层求解器一次性分配。
void lmmc_optimize_emit(const lmmc_optimize_config_t *cfg, const char *operation, size_t iteration, const lmmc_real_t *values, size_t value_count)
lmmc_vec_t lmmc_opt_workspace_vector(lmmc_opt_workspace_t *work, size_t n)
int lmmc_optimize_stop(lmmc_real_t norm, lmmc_real_t *initial, size_t iteration, const lmmc_optimize_config_t *cfg, lmmc_optimize_result_t *out)
int lmmc_optimize_has_converged(lmmc_real_t residual, lmmc_real_t initial_residual, const lmmc_optimize_config_t *cfg)
lmmc_status_t lmmc_opt_workspace_create(size_t n, size_t vectors, size_t matrices, size_t extra, int need_pivots, lmmc_opt_workspace_t *work)
void lmmc_optimize_result_init(lmmc_optimize_result_t *out)
int lmmc_optimize_arguments_valid(const lmmc_vec_t *x, const lmmc_optimize_config_t *cfg, const lmmc_optimize_result_t *out)
@ LMMC_OPT_FAILURE_MAX_ITER
@ LMMC_OPT_FAILURE_NUMERICAL_ISSUE
lmmc_status_t(*) lmmc_opt_func_t(const lmmc_vec_t *x, lmmc_vec_t *F, void *user_data)
非线性函数回调:计算 F(x)。
lmmc_optimize_failure_t failure_reason
lmmc_status_t(*) lmmc_opt_jac_t(const lmmc_vec_t *x, lmmc_mat_t *J, void *user_data)
Jacobian 回调:计算 J(x)。
lmmc_diagnostic_sink_t diagnostics
lmmc_status_t lmmc_optimize_default_config(lmmc_optimize_config_t *cfg)
初始化默认优化配置。
lmmc_real_t(*) lmmc_opt_obj_t(const lmmc_vec_t *x, void *user_data)
目标函数回调:计算标量 f(x)。
lmmc_real_t final_residual
工作区由本次调用拥有,视图仅借用存储,释放由调用方负责。
lmmc_status_t
LMMC 库统一返回的状态码.
@ LMMC_STATUS_NUMERICAL_FAILURE
@ LMMC_STATUS_ALLOCATION_FAILED
@ LMMC_STATUS_INVALID_ARGUMENT