You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用ensmallen优化约束函数遇问题:求解后变量未更新

解决ensmallen约束优化中AugLagrangian未更新变量的问题

我尝试用ensmallen实现约束优化,目标函数是f(x)=x²,约束条件为x=3,初始值设为x=-1,预期结果是x=3,但实际求解后x没有变化。编写了最小可运行示例但未找到错误,请求帮助。

原代码如下:

#include <iostream>
#include "ensmallen.hpp"

using namespace ens;

class ConstrainedFunctionType
{
public:
    // f(x) = x * x
    double Evaluate(const arma::mat& x){
        return x(0,0) * x(0,0);
    }

    // f'(x) = 2x
    void Gradient(const arma::mat& x, arma::mat& g){
        g(0,0) = 2*x(0,0);
    }

    // 1 Constraint, x = 3
    size_t NumConstraints(){
        return 1;
    }
    
    // Return distance from x to 3
    double EvaluateConstraint(const size_t i, const arma::mat& x){
        if(x(0,0) < 3){
            return 3 - x(0,0);
        }
        else if(x(0,0) > 3){
            return x(0,0) - 3;
        }
        return 0;
    }

    // If x was too small, gradient = 1 so it increases
    // If x was too big, gradient =-1 so it decreases
    void GradientConstraint(const size_t i, const arma::mat& x, arma::mat& g){
        g.reshape(1,1);
        if(x(0,0) < 3){
            g(0,0) = 1;
        }
        else if (x(0,0) > 3){
            g(0,0) = -1;
        }
    }
};

int main() {
    ConstrainedFunctionType f;
    arma::mat x (1,1);
    x(0,0) = -1;
    arma::cout << "init = " << x << arma::endl;

    AugLagrangian optimizer;
    optimizer.Optimize(f, x);
    arma::cout << "result = " << x << arma::endl;
    return 0;
}

问题分析

代码存在两个核心问题导致优化失效:

  • 约束函数形式不符合要求:AugLagrangian对等式约束的处理需要标准的h(x)=0形式,原代码返回绝对值将等式约束转化为非光滑的不等式约束,破坏了优化算法的收敛条件。
  • 约束梯度存在未定义情况:当x=3时,GradientConstraint未对梯度赋值,会产生未初始化的内存值,干扰优化迭代。
  • 默认优化器参数强度不足:默认的惩罚参数、迭代次数无法驱动变量从初始点-1移动到约束点3。

修正后的代码

#include <iostream>
#include "ensmallen.hpp"

using namespace ens;

class ConstrainedFunctionType
{
public:
    // f(x) = x * x
    double Evaluate(const arma::mat& x){
        return x(0,0) * x(0,0);
    }

    // f'(x) = 2x
    void Gradient(const arma::mat& x, arma::mat& g){
        g(0,0) = 2*x(0,0);
    }

    // 1 个等式约束:x = 3
    size_t NumConstraints(){
        return 1;
    }
    
    // 等式约束标准形式:h(x) = x - 3 = 0
    double EvaluateConstraint(const size_t i, const arma::mat& x){
        return x(0,0) - 3;
    }

    // 约束的梯度:d(h(x))/dx = 1,无需分支判断
    void GradientConstraint(const size_t i, const arma::mat& x, arma::mat& g){
        g.resize(1, 1); // 确保梯度矩阵尺寸正确
        g(0,0) = 1.0;
    }
};

int main() {
    ConstrainedFunctionType f;
    arma::mat x (1,1);
    x(0,0) = -1;
    arma::cout << "init = " << x << arma::endl;

    // 调整优化器参数,增强约束惩罚力度与迭代次数
    AugLagrangian optimizer(
        1000,    // 最大迭代次数
        1e-6,    // 收敛阈值
        10.0,    // 初始惩罚参数
        2.0,     // 惩罚参数缩放因子
        1e-6,    // 约束容忍度
        true     // 打印迭代信息(可选,便于调试)
    );
    optimizer.Optimize(f, x);
    arma::cout << "result = " << x << arma::endl;
    return 0;
}

关键修正说明

  1. 约束函数标准化:将约束改为x-3,符合AugLagrangian要求的等式约束h(x)=0形式,保证函数可微性。
  2. 约束梯度完整性:直接设置梯度为1,避免未赋值的未定义行为,确保梯度计算稳定。
  3. 优化器参数调优:
    • 提升最大迭代次数,保证优化有足够步骤收敛
    • 提高初始惩罚参数,增强约束的优先级
    • 设置惩罚参数缩放因子,迭代中逐步加大约束力度
    • 开启迭代日志,方便追踪优化过程

内容的提问来源于stack exchange,提问作者Adrian8

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 13:54:21