Go to file
2025-04-08 08:37:45 +08:00
example tmp 2025-04-08 08:37:45 +08:00
lib tmp 2025-04-08 08:37:45 +08:00
tool tmp 2025-04-08 08:37:45 +08:00
.gitignore initial upload 2024-09-10 20:04:47 +08:00
CMakeLists.txt tmp update 2024-10-25 11:23:42 +08:00
config.h.in initial upload 2024-09-10 20:04:47 +08:00
GCTL_logo.jpg update readme 2025-02-03 12:22:40 +08:00
GCTL_OPTIMIZATIONConfig.cmake.in initial upload 2024-09-10 20:04:47 +08:00
installer initial upload 2024-09-10 20:04:47 +08:00
README.md update readme 2025-02-03 12:22:40 +08:00

logo

GCTL Optimization Library

注意: 本文档由 Cursor AI 自动生成。文档中的函数名称、参数和用法说明可能存在错误,请以头文件(.h)中的实际函数声明为准。如发现任何不一致,请以源代码为准。

GCTL Optimization Library 是一个高效的数值优化算法库,提供了多种优化算法实现和求解器。该库是 Generic Scientific Template Library (GSTL) 的一部分。

主要特性

  • 多种优化算法实现

    • LCG (Linear Conjugate Gradient): 线性共轭梯度法
    • CLCG (Complex Linear Conjugate Gradient): 复数域线性共轭梯度法
    • L-BFGS (Limited-memory BFGS): 限制内存BFGS算法
    • SGD (Stochastic Gradient Descent): 随机梯度下降
    • LGD (Lévy Gradient Descent): 基于Lévy飞行的随机搜索方法具有全局收敛性
    • SVD (Singular Value Decomposition): 奇异值分解
  • 矩阵分解工具

    • Cholesky分解
    • LU分解
    • SVD分解
  • 损失函数支持

    • 提供多种常用损失函数
    • 支持自定义损失函数

安装

项目使用CMake构建系统。安装步骤如下

mkdir build
cd build
cmake ..
make

使用方法

1. 配置求解器

所有求解器都支持通过TOML配置文件设置参数

[solver]
max_iterations=1000    # 最大迭代次数
epsilon=1e-6          # 收敛阈值
abs_diff=1            # 是否使用绝对差异
restart_epsilon=1e-4  # 重启阈值
step=0.1             # 步长
sigma=0.9            # sigma参数
beta=0.1             # beta参数
maxi_m=10            # 最大M值用于L-BFGS

2. 定义优化问题

GCTL优化库通过类的虚函数接口来定义具体的优化问题。不同类型的优化问题需要实现不同的虚函数接口

2.1 线性问题接口

对于求解线性方程组 Ax = b 的问题:

class LinearProblem : public gctl::lcg_solver {
public:
    // 必须实现:定义矩阵向量乘积 Ax
    virtual void LCG_Ax(const gctl::array<double> &x, 
                       gctl::array<double> &ax) override {
        // 示例:实现 ax = A * x
        for(size_t i = 0; i < n; ++i) {
            ax[i] = 0.0;
            for(size_t j = 0; j < n; ++j) {
                ax[i] += A[i][j] * x[j];
            }
        }
    }
    
    // 可选实现定义预处理矩阵M的作用
    virtual void LCG_Mx(const gctl::array<double> &x, 
                       gctl::array<double> &mx) override {
        // 示例:对角预处理
        for(size_t i = 0; i < n; ++i) {
            mx[i] = x[i] / A[i][i];
        }
    }
};

2.2 非线性优化问题接口

对于求解非线性优化问题 min f(x) 的情况:

class NonlinearProblem : public gctl::lbfgs_solver {
public:
    // 必须实现:计算目标函数值和梯度
    virtual double LBFGS_Evaluate(const gctl::array<double> &x,
                                gctl::array<double> &g) override {
        // 示例Rosenbrock函数及其梯度
        double fx = 0.0;
        for(size_t i = 0; i < n-1; ++i) {
            fx += 100.0 * pow(x[i+1] - x[i]*x[i], 2) + 
                  pow(1.0 - x[i], 2);
        }
        
        // 计算梯度
        for(size_t i = 0; i < n; ++i) {
            if(i == 0) {
                g[i] = -400.0*x[i]*(x[i+1] - x[i]*x[i]) - 
                       2.0*(1.0 - x[i]);
            }
            else if(i == n-1) {
                g[i] = 200.0*(x[i] - x[i-1]*x[i-1]);
            }
            else {
                g[i] = 200.0*(x[i] - x[i-1]*x[i-1]) - 
                       400.0*x[i]*(x[i+1] - x[i]*x[i]) - 
                       2.0*(1.0 - x[i]);
            }
        }
        return fx;
    }
    
    // 可选实现:定义预处理
    virtual void LBFGS_Precondition(const gctl::array<double> &x,
                                  const gctl::array<double> &g,
                                  const gctl::array<double> &d,
                                  gctl::array<double> &d_pre) override {
        // 实现预处理
        d_pre = d;  // 默认不做预处理
    }
};

2.3 全局优化问题接口

对于需要进行全局搜索的优化问题:

class GlobalProblem : public gctl::lgd_solver {
public:
    // 必须实现:计算目标函数值和梯度
    virtual double LGD_Evaluate(const gctl::array<double> &x,
                              gctl::array<double> &g) override {
        // 示例:多峰函数及其梯度
        double fx = 0.0;
        for(size_t i = 0; i < n; ++i) {
            fx += sin(x[i]) * exp(-0.1 * x[i]*x[i]);
        }
        
        // 计算梯度
        for(size_t i = 0; i < n; ++i) {
            g[i] = cos(x[i]) * exp(-0.1 * x[i]*x[i]) - 
                   0.2 * x[i] * sin(x[i]) * exp(-0.1 * x[i]*x[i]);
        }
        return -fx;  // 最小化负值等价于最大化原函数
    }
    
    // 可选实现:监控优化进度
    virtual int LGD_Progress(const int curr_t, const double curr_fx,
                           const double mean_fx, const double best_fx,
                           const lgd_para &param) override {
        // 返回非零值将终止优化
        return 0;
    }
};

2.4 随机优化问题接口

对于需要随机采样或批量处理的优化问题:

class StochasticProblem : public gctl::sgd_solver {
public:
    // 必须实现:计算单个批次的损失
    virtual double evaluate_batch(const gctl::array<double> &x,
                                const gctl::array<size_t> &batch_indices) override {
        // 示例:均方误差损失
        double loss = 0.0;
        for(auto idx : batch_indices) {
            double pred = predict(x, data[idx]);
            loss += 0.5 * pow(pred - target[idx], 2);
        }
        return loss / batch_indices.size();
    }
    
    // 必须实现:计算单个批次的梯度
    virtual void gradient_batch(const gctl::array<double> &x,
                              const gctl::array<size_t> &batch_indices,
                              gctl::array<double> &grad) override {
        // 示例:均方误差损失的梯度
        grad.fill(0.0);
        for(auto idx : batch_indices) {
            double pred = predict(x, data[idx]);
            update_gradient(x, data[idx], pred - target[idx], grad);
        }
        grad *= (1.0 / batch_indices.size());
    }
};

3. 基本用法

2.1 线性共轭梯度法 (LCG)

#include <gctl/optimization.h>

// 继承lcg_solver类并实现必要的虚函数
class MyProblem : public gctl::lcg_solver {
public:
    // 实现矩阵向量乘法 Ax
    virtual void LCG_Ax(const gctl::array<double> &x, gctl::array<double> &ax) override {
        // 实现 ax = A * x
    }
    
    // 实现预处理矩阵乘法 Mx可选
    virtual void LCG_Mx(const gctl::array<double> &x, gctl::array<double> &mx) override {
        // 实现预处理如果不需要预处理可以简单地将mx = x
        mx = x;
    }
};

// 使用求解器
void solve() {
    MyProblem solver;
    solver.set_max_iterations(1000);
    solver.set_epsilon(1e-6);
    solver.solve(b, x);  // b为右端向量x为解向量
}

2.2 复数域线性共轭梯度法 (CLCG)

#include <gctl/optimization.h>

class ComplexProblem : public gctl::clcg_solver {
public:
    virtual void CLCG_Ax(const gctl::array<std::complex<double>> &x,
                        gctl::array<std::complex<double>> &ax) override {
        // 实现复数域的矩阵向量乘法
    }
};

2.3 L-BFGS优化器

#include <gctl/optimization.h>

class OptProblem : public gctl::lbfgs_solver {
public:
    // 计算目标函数值
    virtual double evaluate(const gctl::array<double> &x) override {
        // 返回在点x处的函数值
    }
    
    // 计算梯度
    virtual void gradient(const gctl::array<double> &x, 
                         gctl::array<double> &grad) override {
        // 计算在点x处的梯度
    }
};

2.4 Lévy梯度下降 (LGD)

#include <gctl/optimization.h>

class LGDProblem : public gctl::lgd_solver {
public:
    // 计算目标函数值
    virtual double evaluate(const gctl::array<double> &x) override {
        // 返回在点x处的函数值
    }
    
    // 计算梯度
    virtual void gradient(const gctl::array<double> &x, 
                         gctl::array<double> &grad) override {
        // 计算在点x处的梯度
    }
    
    // 设置Lévy飞行参数
    void setup() {
        set_levy_alpha(1.5);  // 设置Lévy分布的α参数
        set_step_size(0.1);   // 设置步长
    }
};

2.5 随机梯度下降 (SGD)

#include <gctl/optimization.h>

class SGDProblem : public gctl::sgd_solver {
public:
    // 计算随机批次的损失
    virtual double evaluate_batch(const gctl::array<double> &x,
                                const gctl::array<size_t> &batch_indices) override {
        // 返回当前批次的损失值
    }
    
    // 计算随机批次的梯度
    virtual void gradient_batch(const gctl::array<double> &x,
                              const gctl::array<size_t> &batch_indices,
                              gctl::array<double> &grad) override {
        // 计算当前批次的梯度
    }
    
    // 配置SGD参数
    void setup() {
        set_batch_size(32);           // 设置批次大小
        set_learning_rate(0.01);      // 设置学习率
        set_momentum(0.9);            // 设置动量(可选)
    }
};

3. 高级功能

3.1 自定义损失函数

#include <gctl/optimization.h>

class CustomLoss : public gctl::loss_function {
public:
    virtual double evaluate(const gctl::array<double> &pred,
                          const gctl::array<double> &target) override {
        // 实现自定义损失函数计算
    }
    
    virtual void gradient(const gctl::array<double> &pred,
                         const gctl::array<double> &target,
                         gctl::array<double> &grad) override {
        // 实现损失函数关于预测值的梯度计算
    }
};

3.2 矩阵分解工具使用

#include <gctl/optimization.h>

void matrix_operations() {
    // SVD分解
    gctl::matrix<double> A, U, S, V;
    gctl::svd_decomp(A, U, S, V);
    
    // LU分解
    gctl::matrix<double> L, U;
    gctl::lu_decomp(A, L, U);
    
    // Cholesky分解
    gctl::matrix<double> L;
    gctl::cholesky_decomp(A, L);
}

更多详细示例请参考 example 目录下的示例代码。

示例说明

  • ex1.cpp: 基本的共轭梯度求解示例
  • ex2.cpp: L-BFGS优化示例
  • ex3.cpp: SVD分解应用
  • ex4.cpp: 随机梯度下降示例
  • ex5.cpp: 约束优化问题
  • ex6.cpp: 莱维梯度下降示例
  • ex7.cpp-ex10.cpp: 更多高级应用示例

许可证

该项目采用双重许可:

  1. GNU Lesser General Public License v2.0
  2. 商业许可(需单独申请)

联系方式

作者Yi Zhang (yizhang-geo@zju.edu.cn)

参与贡献

欢迎提交Issue和Pull Request来帮助改进项目。