非线性规划

这篇案例将介绍使用 MindOpt 来求解一般性的非线性规划(Non-Linear Programming,NLP)问题。

我们使用 MindOpt 团队自研的代数建模语言软件 MindOpt APL (MAPL)来实现一般性非线性问题的建模,并与 MindOpt 求解器间进行求解交互。

非线性规划建模

一般性的非线性规划(Non-linear Programming,NLP)问题可以用以下数学形式表示:

其中

  • 是决策变量,

  • 分别为的下界和上界,

  • 是目标函数,

  • 是第条约束,

  • 是第条约束的上界。

说明

非线性规划问题中的目标函数与约束一般被假定是连续光滑函数。尽管如此,一些包含不连续导数函数的问题 MindOpt 也可以成功求解。

MindOpt APL 与 MindOpt 目前支持由以下算术操作符或数学函数所复合而成的非线性问题的建模与求解。

支持的数学操作符

数学形式

解释

MAPL中的表示

加减法运算符/正负号

+ 或 -

乘除法运算符

* 或 /

幂次运算符(a是常量)

^ 或 **

求和运算符

sum

支持的非线性数学函数

数学形式

解释

MAPL中的表示

正弦函数

sin

余弦函数

cos

正切函数

tan

反正弦函数

asin

反余弦函数

acos

反正切函数

atan

双曲正弦函数

sinh

双曲余弦函数

cosh

双曲正切函数

tanh

反双曲正弦函数

asinh

反双曲余弦函数

acosh

反双曲正切函数

atanh

指数函数

exp

e为底的对数函数

log 或 ln

10为底的对数函数

log10

2为底的对数函数

log2

开平方函数

sqrt

绝对值函数

abs

使用 MindOpt APL 及 MindOpt 的步骤为:

  1. 利用 MindOpt APL 创建优化模型;

  2. 输入优化模型到 MindOpt 中,并设置算法参数;

  3. MindOpt 求解优化问题并获取解。

非线性规划问题示例

在下文中,我们将考虑下面的非线性约束规划问题,这是一个简单的带正则化约束的逻辑回归:

我们将展示两种方式调用 MindOpt 求解这个优化问题,分别基于 MindOpt APL 及其Python扩展包 MaplPy 来实现。

基于MAPL的问题建模及优化

目前, MindOpt APL 支持云平台及本地版两种使用方式,可参考 MindOpt APL 的建模与优化章节的介绍。 MindOpt APL 的详细使用语法,可以参考 用户手册

首先,创建 .mapl 文件,声明问题的待优化变量

var x;
var y;
var z;

声明目标函数

minimize ln(1+exp(x+2*y+z)) + ln(1+exp(x-y-z)) + ln(1+exp(-3*x+y-z)) + ln(1+exp(3*x+z));

声明约束

subto x^2 + y^2 <= 1;

而后,运行求解指令,则会自动实现优化模型的构建及 MindOpt 的调用求解。

solve;

MindOpt 求解过程的日志如下

MindOpt Version 2.1.0 (Build date: xxxxxxxx)

Start license validation (current time : xxxxxxxx xx:xx:xx).
License validation terminated. Time : 0.002s

wantsol=1
Model summary.
 - Num. variables     : 3
 - Num. constraints   : 1
 - Num. nonzeros      : 8
 - Bound range        : [1.00e+00,1.00e+00]

Interior point method started.
 Iter         PrimObj         DualObj PrimFea DualFea  GapFea      Mu   Time
    0 +2.77258874e+00 +3.77258875e+00 0.0e+00 1.0e+00 1.0e+00 1.0e+00   0.00s
    1 +2.10107174e+00 +2.23028984e+00 0.0e+00 7.8e-01 1.0e-01 1.0e-01   0.00s
    2 +1.42075610e+00 +1.52543264e+00 6.7e-01 2.7e-01 1.8e-03 1.8e-03   0.00s
    3 +1.65885758e+00 +1.72802441e+00 0.0e+00 1.2e-01 3.6e-02 3.6e-02   0.00s
    4 +1.65511048e+00 +1.69576276e+00 0.0e+00 6.6e-02 2.1e-02 2.1e-02   0.00s
    5 +1.65736811e+00 +1.66000850e+00 0.0e+00 2.6e-04 2.6e-03 2.6e-03   0.00s
    6 +1.65490062e+00 +1.65506485e+00 0.0e+00 9.0e-06 1.6e-04 1.6e-04   0.00s
    7 +1.65474536e+00 +1.65474726e+00 0.0e+00 3.6e-08 1.9e-06 1.9e-06   0.00s
    8 +1.65474358e+00 +1.65474367e+00 0.0e+00 4.9e-12 9.1e-08 9.1e-08   0.00s
Terminated.
 - Method             : Interior point method.
 - Primal objective   : 1.6547435766246e+00
 - Dual objective     : 1.6547436675411e+00
 - Num. threads       : 1
 - Num. iterations    : 8
 - Solver details     : Solver terminated with a primal/dual optimal status.
Interior point method terminated. Time : 0.003883s

Optimizer summary.
 - Optimizer used     : Interior point method
 - Optimizer status   : OPTIMAL

Solution summary.       Primal solution 
 - Objective          : +1.6547435766e+00

OPTIMAL; objective 1.654744
Completed.

成功求解后,MindOpt APL 会获取到问题的最优解 (optimal solution),我们可以将其打印出来进行查看:

print "x={}" % x;
print "y={}" % y;
print "z={}" % z;

上述命令的输出为

x = -0.5728551903261085
y = -0.8196564705817261
z = 1.2728750741453017

我们还可以根据得到的最优解,计算对应的最优目标函数值(此处保留三位小数)

param obj = ln(1+exp(x+2*y+z)) + ln(1+exp(x-y-z)) + ln(1+exp(-3*x+y-z)) + ln(1+exp(3*x+z));
print "obj={:.3f}" % obj;

上述代码的输出如下

obj=1.655

示例 MAPLLR.mapl提供了完整的 MindOpt APL 源代码:

# Example: 2D Regularized Logistic Regression Classifcation
# 
# data points: 
# - label=1: {(1,2), (3,0)}
# - label=-1: {(-1,1),(3,-1)}

var x;
var y;
var z;

minimize ln(1+exp(x+2*y+z)) + ln(1+exp(x-y-z)) + ln(1+exp(-3*x+y-z)) + ln(1+exp(3*x+z));

subto x^2 + y^2 <= 1;

solve;

print "x={}" % x;
print "y={}" % y;
print "z={}" % z;

param obj = ln(1+exp(x+2*y+z)) + ln(1+exp(x-y-z)) + ln(1+exp(-3*x+y-z)) + ln(1+exp(3*x+z));
print "obj={:.3f}" % obj;

基于MaplPy的问题建模及优化

目前,MindOpt APL 支持云平台及本地版两种使用方式,可参考 MindOpt APL 的建模与优化章节的介绍。 MaplPy 的完整API介绍,可以参考 MaplPy 手册

首先,创建.mapl文件,编写待优化问题的数学形式。

# Example: 2D Regularized Logistic Regression Classifcation
# 
# data points: 
# - label=1: {(1,2), (3,0)}
# - label=-1: {(-1,1),(3,-1)}

var x;
var y;
var z;

minimize 
    ln(1+exp(x+2*y+z)) + ln(1+exp(x-y-z)) + ln(1+exp(-3*x+y-z)) + ln(1+exp(3*x+z));
subto 
    x^2 + y^2 <= 1;

Python代码中,导入 MaplPy 依赖包

import maplpy as mp

创建一个新的 MAPL 模型,命名为“lr”

    m = mp.MAPL('lr')  # Create MAPL model

读入我们声明的数学形式到模型中

    m.read(modelfile)  # Read model file

指定 MindOpt 求解器,并设定其对应的路径地址

    m.setOption(mp.StrOption.SOLVER, "mindopt")m.setOption(mp.StrOption.SOLVER_PATH, "/home/mindopt/mindopt/2.1.0/linux64-x86/bin") #you can set your own solver-path here

调用模型的求解函数,这会自动实现优化模型的构建及 MindOpt 的调用求解。

    m.solve() # Solve

执行Python代码,MindOpt 求解过程的日志如下

[mindopt@idec mindopt] python mapl_lr.py
Running mindoptampl
MindOpt Version 2.1.0 (Build date: xxxxxxxx)
Copyright (c) 2020-2025 Alibaba Cloud.

Start license validation (current time : xxxxxxxx).
License validation terminated. Time : 0.002s

wantsol=1
Model summary.
 - Num. variables     : 3
 - Num. constraints   : 1
 - Num. nonzeros      : 8
 - Bound range        : [1.00e+00,1.00e+00]

Interior point method started.
 Iter         PrimObj         DualObj PrimFea DualFea  GapFea      Mu   Time
    0 +2.77258874e+00 +3.77258875e+00 0.0e+00 1.0e+00 1.0e+00 1.0e+00   0.00s
    1 +2.10107174e+00 +2.23028984e+00 0.0e+00 7.8e-01 1.0e-01 1.0e-01   0.00s
    2 +1.42075610e+00 +1.52543264e+00 6.7e-01 2.7e-01 1.8e-03 1.8e-03   0.00s
    3 +1.65885758e+00 +1.72802441e+00 0.0e+00 1.2e-01 3.6e-02 3.6e-02   0.00s
    4 +1.65511048e+00 +1.69576276e+00 0.0e+00 6.6e-02 2.1e-02 2.1e-02   0.00s
    5 +1.65736811e+00 +1.66000850e+00 0.0e+00 2.6e-04 2.6e-03 2.6e-03   0.00s
    6 +1.65490062e+00 +1.65506485e+00 0.0e+00 9.0e-06 1.6e-04 1.6e-04   0.00s
    7 +1.65474536e+00 +1.65474726e+00 0.0e+00 3.6e-08 1.9e-06 1.9e-06   0.00s
    8 +1.65474358e+00 +1.65474367e+00 0.0e+00 4.9e-12 9.1e-08 9.1e-08   0.00s
Terminated.
 - Method             : Interior point method.
 - Primal objective   : 1.6547435766246e+00
 - Dual objective     : 1.6547436675411e+00
 - Num. threads       : 1
 - Num. iterations    : 8
 - Solver details     : Solver terminated with a primal/dual optimal status.
Interior point method terminated. Time : 0.004203s

Optimizer summary.
 - Optimizer used     : Interior point method
 - Optimizer status   : OPTIMAL

Solution summary.       Primal solution 
 - Objective          : +1.6547435766e+00

OPTIMAL; objective 1.654744
Completed.

成功求解后, MAPL 模型会获取到问题的最优解 (optimal solution),我们可以通过API获取其值并打印:

x = m.getVariable("x").valuey = m.getVariable("y").valuez = m.getVariable("z").valueprint("x = {}".format(x))print("y = {}".format(y))print("z = {}".format(z))

则会输出

x = -0.5728551903261085
y = -0.8196564705817261
z = 1.2728750741453017

示例 MaplPy-LR.py提供了完整的 Python 源代码:

import maplpy as mp

def lr_solve(modelfile):
    m = mp.MAPL('lr')  # Create MAPL model
    m.read(modelfile)  # Read model file

    m.setOption(mp.StrOption.SOLVER, "mindopt")  
    m.setOption(mp.StrOption.SOLVER_PATH, "/home/mindopt/mindopt/2.1.0/linux64-x86/bin") #you can set your own solver-path here
    m.solve() # Solve
    
    return m

m = lr_solve("mapl_lr.mapl")

x = m.getVariable("x").value
y = m.getVariable("y").value
z = m.getVariable("z").value

print("x = {}".format(x))
print("y = {}".format(y))
print("z = {}".format(z))