跳到主要内容

代码生成

当完成问题定义后, 需通过OPTIMake的代码生成函数生成问题定义与求解器的C/C++代码. 该章节主要介绍了如何配置代码生成.

OPTIMake的代码生成流程如下:

Overview of code generation

其中, 代码生成分为问题生成与求解器生成两个步骤:

  • 问题生成: 生成问题相关的函数, 如约束的函数值及其梯度. 该过程在用户本地进行
  • 求解器生成: 生成问题对应的求解器. 该过程在OPTIMake服务器进行 (该过程需要联网). 当调用生成的求解器时, 不需要联网

在本地完成问题生成后, 客户端会将问题脱敏后发送至OPTIMake服务器进行求解器生成, 即用户的具体问题定义及数据不会被发送至OPTIMake服务器. 所有上传的数据均对用户透明 (客户端上传部分的代码开源) . 以下为具体发送至服务器的数据:

  • 脱敏后的问题 (masked_multi_stage_problem):
    • 维度
    • 稀疏性: 为0/1的矩阵, 用于稀疏求解加速运算
    • 性质 (如是否线性): 用于选择更好的求解策略
  • 用户信息 (user_info), 用于license check:
    • mac地址
    • 计算机名
    • OS
    • CPU
  • 代码生成option (codegen_option): 定义了需要生成的求解器类型, 硬件平台等信息

代码生成

下面首先介绍代码生成的option, 主要可被分类为生成配置相关, 求解算法相关与性能相关.

生成配置相关

codegen_path: 代码生成路径 (默认值为当前目录下名称与问题名称同名的文件夹)

overwrite: 是否overwrite已生成的代码 (默认True)

verbose: 是否打印代码生成相关的信息 (默认False)

enable_printing: 是否开启打印功能

  • True: 生成代码中包含printf函数, 在求解器print_level设置为非0时, 求解器可打印求解状态 (默认)
  • False: 生成代码中不包含printf函数, 即使在求解器print_level设置为非0时, 求解器亦不可以可打印求解状态

enable_timing: 是否在生成代码中包含计时功能 (默认True)

enable_serialization: 是否开启序列化功能 (可将求解设定存储为二进制文件并读取复现, 默认False)

platform: 求解器运行的平台及其编译器

  • 'linux-x86_64-gcc' (默认): Linux x86_64平台, gcc编译器
  • 'windows-x86_64-mingw': Windows x86_64平台, mingw编译器
  • 'linux-arm64-gcc': Linux ARM64平台, gcc编译器
  • 'linux-armv7-gcc': Linux ARMv7平台, gcc编译器
信息

OPTIMake使用交叉编译生成不同平台的求解器, 可支持多种平台的求解器生成.

如上述的平台或编译器不满足需求, 请联系OPTIMake获取支持.

lib_type

  • 'static': 生成求解器的静态链接库 (默认)
  • 'shared': 生成求解器的动态链接库

求解算法相关

solver: 求解算法

  • 'pdipm': primal-dual interior-point method (默认)
  • 'sqp': sequential quadratic programming method (当前暂未支持)

hessian_approximation: Hessian计算方法

  • 'exact' (默认)
  • 'gauss-newton'
  • 'bfgs'
信息
  1. 当objective为least square类型且残差较小, 或问题的非线性较低时, 选择'gauss-newton'. 当非上述情况, 需要计算Hessian才能收敛时, 选择'exact''bfgs'.
  2. 当Hessian很容易得到 (比如问题通过符号定义, OPTIMake会自动生成exact Hessian), 选择'exact'一般比'bfgs'更高效且鲁棒
  3. 如下的情况OPTIMake不能自动生成exact Hessian:
    • 外部函数, 此时Hessian需要用户自己提供. (见建模接口 > 外部C/C++函数支持了解OPTIMake中的外部函数)
    • differential_equationdiscretization_method'irk2''irk4'

bfgs_init_hessian: bfgs的Hessian初始值, 可以为常数或关于参数p的维度为[nv, nv]的对称矩阵 (通过list传入, list的元素为nv维的list);其默认值单位矩阵

信息

求解过程中计算的Hessian值被存储在workspace中, 可以求解优化问题后访问该值来优化bfgs_init_hessian的选取.

性能相关

optimization_level: 编译优化等级

  • 0,1,2,3 (默认3)

common_subexpression_elimination: 提取公共表达式, 减少运算量

  • 'on'
  • 'off'
  • 'auto' (默认)

会导致计算顺序变化, 当问题对数值敏感时, 可以尝试不同的选项求解.

simplify_expression: 简化表达式, 可能会导致本地问题时间过长

  • True
  • False (默认)

default_tolerance_level: 默认的求解精度 (设置后求解精度亦可手动调整)

  • 'low'
  • 'medium' (默认)
  • 'high'

示例

下面为代码生成的例子:

option = codegen_option()
option.solver = 'pdipm' # primal-dual interior-point method
option.enable_printing = True
option.optimization_level = 3
# 'windows-x86_64-mingw', 'linux-x86_64-gcc', 'linux-arm64-gcc', 'linux-armv7-gcc'
option.platform = 'linux-x86_64-gcc'

codegen = code_generator()
codegen.codegen(prob, option)

假设问题的名称为 'vehicle', 生成platform'linux-x86_64-gcc', OPTIMake会生成以下文件:

  • vehicle_prob.h: 问题的头文件, 定义了维度, 优化变量与参数index的enum值等
  • vehicle_prob.c: 问题的源码文件, 定义了各函数, 如objective及其梯度的实现
  • vehicle_prob_ext.c.template: 只当问题定义中出现外部函数时会生成该文件, 包含了外部函数的模板. 用户完成外部函数的实现后需要去掉.template后缀编译
  • vehicle_solver.h: 求解代码的接口头文件
  • libvehicle_solver_shared.so: 求解代码的动态链接库 (platform为Windows时后缀为.dll)
  • libvehicle_solver_static.a: 求解代码的静态链接库 (platform为Windows时后缀为.lib)
信息

每一次代码生成都会有唯一的session uuid. 当前代码生成失败时, 请提供该id以及返回状态至OPTIMake以获取技术支持.