二次规划问题用MindOpt C++怎么进行建模优化

简介: MindOpt是达摩院决策智能实验室研究的一款优化求解器,目前在优化求解线性规划问题这一功能上取得不错的成绩,希望大家能够帮我们多多打磨其他功能(混合整数线性规划、二次规划、半定规划目前都在公测),让我们的MindOpt在优化求解器这板块成为国产之光。

二次规划问题在生活中非常常见,广泛体现在时间调度、时间调度,规模经济学,工程设计以及控制领域,设施分配问题,选址问题,目前MindOpt优化求解器求解二次规划问题的功能正在公测,感兴趣的小伙伴可以去了解一下。本文将会重点讲述如何使用mindopt c++ 语言的api来建模优化二次规划问题。


MindOpt Python、C、C++语言求解LP、MILP、QP问题系列


下载安装

用户可以点这里下载安装MindOpt优化求解器

开通算法服务控制台(免费的)

MindOpt的更多信息官网


二次规划

在前文线性规划问题示例中,讲述到线性规划在我个人认为是在线性的目标和约束中,找出一个最优解。而本文的二次规划,是非线性规划中的一类。具体地说,是一个线性约束的、二次规划问题,就是优化(最小化或最大化)二次函数目标的问题。


关于优化的类别,有很多,比如MindOpt的案例广场的标签里面提到的问题标签,就列出了常见的数学规划的类型。其中关于变量、约束、目标这建模三要素,进行罗列:

  • 关于变量:取值有连续的,有整数的,还有更特殊的二进制(0或1)的,
  • 关于约束和目标:一般用变量的函数变换来表达,其中约束再增加它函数的取值范围。
  • 当函数是变量的线性关系时,比如x的1次方相加,我们称呼为线性约束、线性的目标。(如果变量也是连续的,这个就是线性规划问题啦。)
  • 当函数是变量的是二次关系的时候,比如函数中有 x的2次方项。我们称呼为二次约束,或二次目标。
  • 函数还会有凸函数和非凸函数,数学里面都代表不同的特性,大家可以再多去查阅材料。

image.png

本文主要讲 凸二次规划,Convex Quadratic Programming。

数学形式下的二次规划问题:

image.png

公式参考自MindOpt文档:https://solver.damo.alibaba.com/doc/html/model/qp/quadratic%20problem.html

案例

讲一个简单的例子,使用二次规划方法优化汽车轨迹,自动化驾驶车辆行驶在道路比较狭窄的路径上,还有其他障碍物阻碍的情况下,如果需要快速通过的话,我们需要暂时借用相邻车道通过,这个情况需要考虑自身车辆的情况、交通规则、保障远离障碍物距离的信息,然后找出一条通道。那么这个例子的解决办法是先考虑自身车辆的位置和周围障碍物,精确处理前一步可用车道,得到路径的边界,然后对路径边界进行优化(比如把车辆和障碍物之间的距离最大化,以允许车辆安全通过间隙)。

image.png


数学算例

接下来我们举一个简单的数学算例,和如何用MindOpt优化求解器进行求解。

二次规划问题示例:

image.png

C++和MindOpt代码实现

核心使用的几个APIs是:

 MdoModel model;

model.setIntAttr(MDO_INT_ATTR::MIN_SENSE, MDO_YES);

model.addCons(1.0, MDO_INFINITY, 1.0 * x[0] + 1.0 * x[1] + 2.0 * x[2] + 3.0 * x[3], "c0");
model.addCons(1.0, 1.0,          1.0 * x[0]              - 1.0 * x[2] + 6.0 * x[3], "c1");

model.solveProb();
model.displayResults();

下面是完整的例子,可复制存为MdoQoEx1.cpp文件。

#include <iostream>
#include <vector>
/*引入头文件*/
#include "MindoptCpp.h"

using namespace mindopt;

int main(void)
{
    /*------------------------------------------------------------------*/
    /* Step 1. 创建模型并更改参数。                */
    /*------------------------------------------------------------------*/
    /* 创建一个空模型。 */
    MdoModel model;

    try 
    {
        /*------------------------------------------------------------------*/
        /* Step 2. 输入模型。                                             */
        /*------------------------------------------------------------------*/
        /* 通过 mindopt::MdoModel::setIntAttr() 将目标函数设置为 最小化 */
        model.setIntAttr(MDO_INT_ATTR::MIN_SENSE, MDO_YES);

        /* 调用 mindopt::MdoModel::addVar() 来添加四个优化变量,定义其下界、上界、名称和类型 */
        std::vector<MdoVar> x;
        x.push_back(model.addVar(0.0, 10.0,         1.0, "x0", MDO_NO));
        x.push_back(model.addVar(0.0, MDO_INFINITY, 1.0, "x1", MDO_NO));
        x.push_back(model.addVar(0.0, MDO_INFINITY, 1.0, "x2", MDO_NO));
        x.push_back(model.addVar(0.0, MDO_INFINITY, 1.0, "x3", MDO_NO));

        /* 添加约束 */
        model.addCons(1.0, MDO_INFINITY, 1.0 * x[0] + 1.0 * x[1] + 2.0 * x[2] + 3.0 * x[3], "c0");
        model.addCons(1.0, 1.0,          1.0 * x[0]              - 1.0 * x[2] + 6.0 * x[3], "c1");

        /* 添加二次目标矩阵 Q.
         *
         * 1. 目标函数定义为c^Tx + 1/2 x^TQx,其中Q以坐标格式存储。
         * 2. Q 将在内部缩放 1/2。
         * 3. 为保证Q的对称性,用户只需输入下三角部分即可
         *
         * Q = [ 1.0  0.5  0    0   ]
         *     [ 0.5  1.0  0    0   ]
         *     [ 0.0  0.0  1.0  0   ]
         *     [ 0    0    0    1.0 ]
         */
        /*调用 mindopt::MdoModel::setQuadraticElements() 来设置目标的二次项系数 。
          前两组输入向量分别表示二次项中所有非零项的两个变量的索引,
          最后一组输入向量是与之相对应的非零系数值。*/
        model.setQuadraticElements
        (
            { x[0], x[1], x[1], x[2], x[3] },
            { x[0], x[0], x[1], x[2], x[3] },
            {  1.0,  0.5,  1.0,  1.0,  1.0 }
        );

        /*------------------------------------------------------------------*/
        /* Step 3.  解决问题并填充结果。               */
        /*------------------------------------------------------------------*/
        /* 调用 mindopt::MdoModel::solveProb() 求解优化问题,
           并通过 mindopt::MdoModel::displayResults() 查看优化结果 
          */
        model.solveProb();
        model.displayResults();
    }
    catch (MdoException & e)
    {
        std::cerr << "===================================" << std::endl;
        std::cerr << "Error   : code <" << e.getResult() << ">" << std::endl;
        std::cerr << "Reason  : " << model.explainResult(e.getResult()) << std::endl;
        std::cerr << "===================================" << std::endl;

        return static_cast<int>(e.getResult());
    }

    return static_cast<int>(MDO_OKAY);
}

MindOpt求解的结果

运行MdoQoEx1.cpp文件的步骤

linux和mac系统直接在命令行输入

cd <MDOHOME>/<VERSION>/examples/CPP
make -f Makefile all
./MdoQoEx1

windows系统本例是在Visual Studio上运行,版本为2019

#运行方式与前文    一致,只需要修改文件就好;把MdoLoEx1.cpp换成MdoQoEx1.cpp

C++.gif

如上文所述,运行MdoMiloEx1.cpp文件,得到求解的结果如下所示,/**/号里面是我添加的注释。

Model summary.               /*模型摘要*/
 - Num. variables     : 4
 - Num. constraints   : 2
 - Num. nonzeros      : 7
 - Bound range        : [1.0e+00,1.0e+01]
 - Objective range    : [1.0e+00,1.0e+00]
 - Quad. obj. range   : [5.0e-01,1.0e+00]
 - Matrix range       : [1.0e+00,6.0e+00]

Presolver started.
Presolver terminated. Time : 0.001s

Interior point method started.   /*内点法*/
 Iter         PrimObj         DualObj PrimFea DualFea  GapFea      Mu   Time
    0 +5.21950421e+01 -5.93593455e+01 1.3e+00 8.0e-01 2.1e+00 1.5e+01   0.03s
    1 +5.75093325e+00 -3.28624247e+00 3.2e-02 2.0e-02 2.8e+00 1.5e+00   0.04s
    2 +1.19681205e+00 +1.03397025e-04 8.1e-04 3.7e-03 1.2e+00 2.0e-01   0.04s
    3 +6.52164783e-01 +3.52420863e-01 1.7e-04 3.7e-03 3.0e-01 4.9e-02   0.05s
    4 +4.65540318e-01 +4.35143347e-01 4.2e-06 9.3e-05 3.0e-02 5.1e-03   0.06s
    5 +4.40907312e-01 +4.39861230e-01 1.0e-07 2.3e-06 1.0e-03 1.7e-04   0.07s
    6 +4.40022716e-01 +4.39996554e-01 2.6e-09 5.8e-08 2.6e-05 4.4e-06   0.08s
    7 +4.40000569e-01 +4.39999914e-01 6.5e-11 1.5e-09 6.6e-07 1.1e-07   0.08s
    8 +4.40000014e-01 +4.39999998e-01 1.6e-12 3.7e-11 1.6e-08 2.7e-09   0.09s
    9 +4.40000000e-01 +4.40000000e-01 4.1e-14 9.1e-13 4.1e-10 6.9e-11   0.10s
Terminated.
 - Method             : Interior point method.
 - Primal objective   : 4.3999999966807E-01
 - Dual objective     : 4.3999999996074E-01
 - Num. threads       : 2
 - Num. iterations    : 9
 - Solver details     : Solver terminated with a primal/dual optimal status.

Interior point method terminated. Time : 0.107s

Optimizer summary.
 - Optimizer used     : Interior point method
 - Optimizer status   : OPTIMAL
 - Total time         : 0.116s

Solution summary.       Primal solution
 - Objective          : 4.3999999967e-01       /*目标函数最优解*/


联系我们

钉钉:damodi

邮箱地址:solver.damo@list.alibaba-inc.com


相关文章
|
8月前
|
机器学习/深度学习 算法
【机器学习】无约束最优化问题
【1月更文挑战第24天】【机器学习】无约束最优化问题
|
8月前
|
人工智能 自然语言处理 达摩院
MindOpt 云上建模求解平台:多求解器协同优化
数学规划是一种数学优化方法,主要是寻找变量的取值在特定的约束情况下,使我们的决策目标得到一个最大或者最小值的决策。
|
算法 安全 机器人
Python语言如何使用MindOpt建模并求解二次规划问题
MindOpt是一款高效的优化算法软件包,求解算法实现了线性规划(LP)、混合整数线性规划(MILP)、二次规划(QP),可以支持命令行、c、c++、java和python调用。接下来我们将发布一系列文章,讲述各个语言如何使用 MindOpt 来求解数学规划问题。
Python语言如何使用MindOpt建模并求解二次规划问题
|
大数据
数学建模1:lingo软件求解优化模型
数学建模1:lingo软件求解优化模型
139 0
|
达摩院 供应链
「达摩院MindOpt」用于多目标规划(加权和法)
多目标规划(Multi-objective programming)是指在一个优化问题中需要同时考虑多个目标函数的优化。在多目标规划问题中,目标函数之间通常是互相冲突的,即在优化一个目标函数的过程中,另一个或几个目标函数可能会受到影响。因此,多目标规划问题的目标是找到一个解x,使得在满足约束的前提下,所有目标函数达到一个相对满意的折中。
「达摩院MindOpt」用于多目标规划(加权和法)
|
8月前
|
达摩院 算法 Java
选择优化求解器的关键因素:以MindOpt为例
选择一款适合自己业务需求的求解器我们一般需要考量什么呢?可求解的问题类型?问题规模?本文将介绍一些需要考虑的重要因素,并且介绍阿里达摩院MindOpt优化求解器在这些因素下的表现。
MindOpt V1.0优化种植计划问题,新的建模方法
种植计划是指农业生产中针对不同农作物的种植时间、面积和种植方式等方面的规划安排。根据具体情况进行合理的规划和安排,以实现农作物的高产、优质和可持续发展。
MindOpt V1.0优化种植计划问题,新的建模方法
|
8月前
|
人工智能 算法 决策智能
MindOpt云上建模求解平台功能的简单介绍
MindOpt云上建模求解平台是阿里巴巴达摩院研发的一款“优化领域”的云平台。它结合了最新的算法研究和云技术,为用户提供了一个易于使用的界面和强大的后台计算能力。该平台支持广泛的优化问题,包括线性规划、整数规划、非线性规划和混合整数规划等。
|
存储 算法 Java
建筑工地的水泥分配和料场选址问题(Cplex求解线性规划模型+粒子群搜索算法)【Java实现】
建筑工地的水泥分配和料场选址问题(Cplex求解线性规划模型+粒子群搜索算法)【Java实现】
98 0
|
存储 算法 对象存储
MindOpt Tuner调参器,提升求解速度、性能(一)
优化求解器往往拥有很多配置参数,例如启发式方法的开关、割平面方法的开关、预处理的配置以及各种误差容忍度等等。MindOpt Tuner会尝试不同的参数组合,评估每组参数的性能,然后基于这些结果来确定最佳参数。这样可以大大减少手动调整参数的时间和精力,并且可以帮助提升求解性能。
MindOpt Tuner调参器,提升求解速度、性能(一)

热门文章

最新文章