CppAD安装和Ipopt安装(亲测有用!!!)

本文详细指导了如何在Ubuntu20.04系统上源码安装Ipopt和cppAD,包括依赖项安装、第三方库如ASL、HSL和MUMPS的构建,并通过实例展示了如何使用CppAD与Ipopt求解非线性规划问题,以及如何验证求解结果。
摘要由CSDN通过智能技术生成

参考博客:
Linux | Ubuntu 20.04安装ipopt和cppAD | 安装全流程+报错解决

IPOPT+cppad求解优化问题例子(C++)

1 Ipopt安装

源码安装
(1)安装依赖

sudo apt-get install gcc g++ gfortran git patch wget pkg-config liblapack-dev libmetis-dev libblas-dev 

(2)创建一个存放所有跟Ipopt相关的文件夹,便于管理

mkdir ~/Ipopt_pkg
cd Ipopt_pkg

(3)安装ASL

git clone https://github.com/coin-or-tools/ThirdParty-ASL.git
cd ThirdParty-ASL
sudo ./get.ASL
sudo ./configure
sudo make
sudo make install
cd ..

(4)安装HSL

git clone https://github.com/coin-or-tools/ThirdParty-HSL.git
cd ThirdParty-HSL
# 接下来需要下载coinhsl文件,并解压到ThirdParty-HSL目录下

下载coinhsl文件,并解压到ThirdParty-HSL目录下
在ThirdParty-HSL目录下,执行以下命令

sudo ./configure
sudo make
sudo make install
cd ..

(5)安装MUMPS

git clone https://github.com/coin-or-tools/ThirdParty-Mumps.git
cd ThirdParty-Mumps
sudo ./get.Mumps
sudo ./configure
sudo make
sudo make install
cd ..

(6)安装Ipopt

git clone https://github.com/coin-or/Ipopt.git
cd Ipopt
mkdir build
cd build
sudo ../configure
sudo make
sudo make test
sudo make install

(7)完善环境

cd /usr/local/include
sudo cp coin-or coin -r
sudo ln -s /usr/local/lib/libcoinmumps.so.3 /usr/lib/libcoinmumps.so.3
sudo ln -s /usr/local/lib/libcoinhsl.so.2 /usr/lib/libcoinhsl.so.2
sudo ln -s /usr/local/lib/libipopt.so.3 /usr/lib/libipopt.so.3

2 Ipopt测试

进入 IPOPT 源码文件夹如下位置,用官方例子测试

cd Ipopt/build/examples/Cpp_example
sudo make
./cpp_example

出现以下界面安装成功

******************************************************************************
This program contains Ipopt, a library for large-scale nonlinear optimization.
 Ipopt is released as open source code under the Eclipse Public License (EPL).
         For more information visit https://github.com/coin-or/Ipopt
******************************************************************************

This is Ipopt version 3.14.14, running with linear solver ma27.

Number of nonzeros in equality constraint Jacobian...:        2
Number of nonzeros in inequality constraint Jacobian.:        0
Number of nonzeros in Lagrangian Hessian.............:        2

Total number of variables............................:        2
                     variables with only lower bounds:        0
                variables with lower and upper bounds:        1
                     variables with only upper bounds:        0
Total number of equality constraints.................:        1
Total number of inequality constraints...............:        0
        inequality constraints with only lower bounds:        0
   inequality constraints with lower and upper bounds:        0
        inequality constraints with only upper bounds:        0

iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
   0 -2.5000000e-01 7.50e-01 5.00e-01  -1.0 0.00e+00    -  0.00e+00 0.00e+00   0
   1 -1.8981454e+00 6.12e-01 1.55e+00  -1.0 1.72e+00   0.0 6.27e-01 5.10e-01f  1
   2 -3.6781503e+00 1.32e-03 1.60e-01  -1.0 5.40e-01    -  1.00e+00 1.00e+00f  1
   3 -3.9900218e+00 1.67e-03 1.22e-02  -1.7 7.98e-02    -  1.00e+00 9.99e-01f  1
   4 -3.9998554e+00 1.56e-07 3.88e-06  -3.8 2.46e-03    -  1.00e+00 1.00e+00h  1
   5 -3.9999982e+00 3.16e-10 2.54e-09  -5.7 3.57e-05    -  1.00e+00 1.00e+00h  1
   6 -4.0000001e+00 5.28e-14 4.23e-13  -8.6 4.60e-07    -  1.00e+00 1.00e+00h  1

Number of Iterations....: 6

                                   (scaled)                 (unscaled)
Objective...............:  -4.0000000774945192e+00   -4.0000000774945192e+00
Dual infeasibility......:   4.2277292777725961e-13    4.2277292777725961e-13
Constraint violation....:   5.2846615972157451e-14    5.2846615972157451e-14
Variable bound violation:   9.6868413290707167e-09    9.6868413290707167e-09
Complementarity.........:   2.5056919964012917e-09    2.5056919964012917e-09
Overall NLP error.......:   2.5056919964012917e-09    2.5056919964012917e-09


Number of objective function evaluations             = 7
Number of objective gradient evaluations             = 7
Number of equality constraint evaluations            = 7
Number of inequality constraint evaluations          = 0
Number of equality constraint Jacobian evaluations   = 7
Number of inequality constraint Jacobian evaluations = 0
Number of Lagrangian Hessian evaluations             = 6
Total seconds in IPOPT                               = 0.001

EXIT: Optimal Solution Found.


*** The problem solved in 6 iterations!


*** The final value of the objective function is -4.

3 CppAD

3.1 安装

命令行安装:

sudo apt-get install cppad
3.2 CppAD测试

CppAD_demo.cpp

# include <iostream>        // standard input/output
# include <vector>          // standard vector
# include <cppad/cppad.hpp> // the CppAD package

namespace { // begin the empty namespace
    // define the function Poly(a, x) = a[0] + a[1]*x[1] + ... + a[k-1]*x[k-1]
    template <class Type>
    Type Poly(const CPPAD_TESTVECTOR(double) &a, const Type &x)
    {   size_t k  = a.size();
        Type y   = 0.;  // initialize summation
        Type x_i = 1.;  // initialize x^i
        for(size_t i = 0; i < k; i++)
        {   y   += a[i] * x_i;  // y   = y + a_i * x^i
            x_i *= x;           // x_i = x_i * x
        }
        return y;
    }
}
// main program
int main(void)
{   using CppAD::AD;   // use AD as abbreviation for CppAD::AD
    using std::vector; // use vector as abbreviation for std::vector

    // vector of polynomial coefficients
    size_t k = 5;                  // number of polynomial coefficients
    CPPAD_TESTVECTOR(double) a(k); // vector of polynomial coefficients
    for(size_t i = 0; i < k; i++)
        a[i] = 1.;                 // value of polynomial coefficients

    // domain space vector
    size_t n = 1;               // number of domain space variables
    vector< AD<double> > ax(n); // vector of domain space variables
    ax[0] = 3.;                 // value at which function is recorded

    // declare independent variables and start recording operation sequence
    CppAD::Independent(ax);

    // range space vector
    size_t m = 1;               // number of ranges space variables
    vector< AD<double> > ay(m); // vector of ranges space variables
    ay[0] = Poly(a, ax[0]);     // record operations that compute ay[0]

    // store operation sequence in f: X -> Y and stop recording
    CppAD::ADFun<double> f(ax, ay);

    // compute derivative using operation sequence stored in f
    vector<double> jac(m * n); // Jacobian of f (m by n matrix)
    vector<double> x(n);       // domain space vector
    x[0] = 3.;                 // argument value for computing derivative
    jac  = f.Jacobian(x);      // Jacobian for operation sequence

    // print the results
    std::cout << "f'(3) computed by CppAD = " << jac[0] << std::endl;

    // check if the derivative is correct
    int error_code;
    if( jac[0] == 142. )
        error_code = 0;      // return code for correct case
    else  error_code = 1;    // return code for incorrect case

    return error_code;
}

CMakeList.txt

cmake_minimum_required(VERSION 3.02)

project(testCPP)

set(CMAKE_CXX_STANDARD 14)

add_executable(CppAD_demo src/CppAD_demo.cpp)

出现以下命令测试成功

f'(3) computed by CppAD = 142

4 测试Ipopt与CppAD

IPOPT+cppad求解优化问题例子(C++)
利用CppAD与Ipopt求解以下非线性规划问题
在这里插入图片描述
cppad_ipopt_demo.cpp

#include <iostream>
// 头文件,用于使用 CppAD 和 Ipopt 库
#include <cppad/ipopt/solve.hpp>

using namespace std;
// 定义仿函数,用于计算目标函数和约束
namespace {
using CppAD::AD;
class FG_eval {
public:
    // CPPAD_TESTVECTOR 是 CppAD 中定义的一个宏,用于创建 AD 向量。
    typedef CPPAD_TESTVECTOR(AD<double>) ADvector;
    // operator() 函数实现了仿函数的功能,计算目标函数和约束。在这里,目标函数和约束的数量都是 3 个。
    void operator()(ADvector& fg, const ADvector& x)
    {
        // assert 语句用于确保 fg 向量和 x 向量的大小分别为 3 和 4。
        assert(fg.size() == 3);
        assert(x.size() == 4);
        // variables
        // 将决策变量从 x 向量中提取出来,分别赋值给 x1、x2、x3 和 x4
        AD<double> x1 = x[0];
        AD<double> x2 = x[1];
        AD<double> x3 = x[2];
        AD<double> x4 = x[3];
        // f(x) objective function
        fg[0] = x1 * x4 * (x1 + x2 + x3) + x3;
        // constraints
        fg[1] = x1 * x2 * x3 * x4;
        fg[2] = x1 * x1 + x2 * x2 + x3 * x3 + x4 * x4;
        return;
    }

};

}
// get_started 函数是程序的入口。它初始化了问题的参数,包括变量的数量(nx),约束的数量(ng),以及初始条件(x0 向量)。
bool get_started(void)
{
    bool ok = true;
    size_t i;
    typedef CPPAD_TESTVECTOR(double) Dvector;

    size_t nx = 4; // 决策变量个数
    size_t ng = 2; // 决策约束个数
    Dvector x0(nx); // 变量初始值
    x0[0] = 1.0;
    x0[1] = 5.0;
    x0[2] = 5.0;
    x0[3] = 1.0;

    // 决策变量界限设置
    Dvector xl(nx), xu(nx);
    for(i = 0; i < nx; i++)
    {
        xl[i] = 1.0;
        xu[i] = 5.0;
    }
    Dvector gl(ng), gu(ng);
    gl[0] = 25.0;    gu[0] = 1.0e19;
    gl[1] = 40.0;    gu[1] = 40.0;//等式约束描述为等式约束
    // 创建了 FG_eval 类的实例,用于计算目标函数和约束
    FG_eval fg_eval;

    // options
    string options;// 字符串,用于存储 Ipopt 求解器的选项。
    // turn off any printing
    options += "Integer print_level  0\n";
    options += "String sb            yes\n";
    // maximum iterations
    // 设置最大迭代次数为 10。这是一个控制求解器运行时间的参数。
    //如果求解器达到了最大迭代次数而没有找到满足收敛标准的解,求解器将提前退出。
    options += "Integer max_iter     10\n";
    //approximate accuracy in first order necessary conditions;
    // see Mathematical Programming, Volume 106, Number 1,
    // Pages 25-57, Equation (6)
    //设置收敛容许误差。这个参数控制求解器停止迭代的条件,
    //当当前迭代的优化进度足够小(小于 tol)时,求解器将停止运行。
    options += "Numeric tol          1e-6\n";
    //derivative tesing
    options += "String derivative_test   second-order\n";
    // maximum amount of random pertubation; e.g.,
    // when evaluation finite diff
    //置数值微分的随机扰动半径。在进行数值微分时,为了计算梯度和黑塞矩阵,
    //可能会对变量进行小幅度的扰动。这个选项设置了扰动的最大半径。将其设置为 0 表示关闭数值微分。
    options += "Numeric point_perturbation_radius   0.\n";

	// 将结果存储在 solution 
    CppAD::ipopt::solve_result<Dvector> solution; // solution
    // 求解问题
    CppAD::ipopt::solve<Dvector, FG_eval>(options, x0, xl, xu, gl, gu, fg_eval, solution); // solve the problem

    cout<<"solution: "<<solution.x<<endl;

    //
    //check some of the solution values
    //
    //进行最优解的检查,确保求解器成功并且最优解在预期范围内。
    ok &= solution.status == CppAD::ipopt::solve_result<Dvector>::success;
    //预期的最优解。这是在已知问题的情况下提前计算的一个参考解。
    double check_x[]  = {1.000000, 4.743000, 3.82115, 1.379408};
    double check_zl[] = {1.087871, 0.,       0.,       0.      };
    double check_zu[] = {0.,       0.,       0.,       0.      };
    //相对容差和绝对容差。在进行近似相等性比较时,通常会使用相对容差和绝对容差。这两个参数用于定义两个值在多大程度上被认为是相等的。
    double rel_tol    = 1e-6; // relative tolerance
    double abs_tol    = 1e-6; // absolute tolerance
    //对最优解的逐个分量进行检查。使用 CppAD::NearEqual 函数进行比较
    //如果解与预期解在相对容差和绝对容差内足够接近,则 ok 变量会保持为 true,否则为 false。
    for(i = 0; i < nx; i++)
    {
        ok &= CppAD::NearEqual(
                    check_x[i], solution.x[i], rel_tol, abs_tol);
        ok &= CppAD::NearEqual(
                    check_zl[i], solution.zl[i], rel_tol, abs_tol);
        ok &= CppAD::NearEqual(
                    check_zu[i], solution.zu[i], rel_tol, abs_tol);
    }

    return ok;
}

int main()
{
    cout << "CppAD : Hello World Demo!" << endl;
    get_started();
    return 0;
}

CMakeList.txt

cmake_minimum_required(VERSION 3.0.2)
project(cppa)

find_package(catkin REQUIRED COMPONENTS
  roscpp
)

set(CMAKE_CXX_STANDARD 14)
include_directories(/usr/local/include)
link_directories(/usr/local/lib)

add_executable(CppAD_demo src/CppAD_demo.cpp)
target_link_libraries(CppAD_demo ipopt)

其中:

include_directories(/usr/local/include)
link_directories(/usr/local/lib)

很重要,因为不加这个,找不到ipopt,会出现段错误
输出以下结果测试成功:

CppAD : Hello World Demo!
solution: { 1, 4.743, 3.82115, 1.37941 }

文章详细介绍了CppAD和Ipopt求解器的安装

  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值