4.3. 使用 C++ 语言调用 MindOpt 动态库

4.3.1. 简要示意

// 方法1:从0.19.0版本开始引入新式的创建模型方式
using mindopt::MdoEnv;
MdoEnv env;
MdoModel model(env);
model.readProb(filename);
model.solveProb();
model.displayResults();

// 方法2:旧式的创建模型方式仍然支持
/*
MdoModel model;
model.readProb(filename);
model.solveProb();
model.displayResults();
*/

后文将说明如何使用 C++ 语言编译和链接 MindOpt 动态库,并提供 C++ 语言的编译示例。该示例将读取 MPS 文件中的优化模型并进行优化求解。

Note

由于动态库只在应用程序实际运行时才进行链接,因此,用户必须在环境变量中指定动态库的路径,以便应用程序能够正确地定位到动态库。若环境变量未指定,则用户必须将动态库放置于应用程序旁。关于环境变量的设置说明,请参阅 安装说明。关于 C++ 语言编译器版本的支持,请参阅 支持平台 中的说明。

Warning

mindoptcpp 的 Linux/OSX 动态库将在运行下面的示例时自动生成。换言之,用户在使用 C++ API 之前必须 至少运行一次 这个例子。

4.3.2. Windows

MindOpt 已在 Visual Studio 2017/2019 上进行过测试。关于C++ 语言的编译示例,请参考 <MDOHOME>/<VERSION>/examples/CPP

如果要用 Visual Studio 来编译, 用户需要进行如下设置:

  1. 创建一个空的 Visual Studio 项目。

  2. 选用 x64 为解决方案平台。

  3. 设置 include 目录 (<MDOHOME>/<VERSION>/win64-x86/include)。

  4. 设置 library 目录 (<MDOHOME>/<VERSION>/win64-x86/lib)。

  5. 添加 library 文件 (Release模式: mindopt_x_x_x.libmindoptcpp_x_x_x.lib; Debug模式: mindopt_x_x_x.libmindoptcpp_x_x_xd.lib)。

Note

Visual Studio 在不同编译环境下(Release或Debug)会采用不同的动态库(msvcrt.lib (multi-threaded DLL)或 msvcrtd.lib (multi-threaded DLL debug));用户请务必选用正确的 MindOpt 动态库(mindoptcpp_x_x_x.libmindoptcpp_x_x_xd.lib)避免运行错误。

Note

使用旧版本的Visual Studio编译器在执行时可能会遇到DLL执行错误,此时可自行编译 mindoptcpp C++ API来避免问题。编译方式如下:

  1. 创建一个空的 Visual Studio 项目。

  2. 选用 x64 为解决方案平台。

  3. 设置 include 目录 (<MDOHOME>/<VERSION>/win64-x86/include<MDOHOME>/<VERSION>/win64-x86/src)。

  4. 设置 library 目录 (<MDOHOME>/<VERSION>/win64-x86/lib)。

  5. 添加 library 文件 (mindopt_x_x_x.lib)。

  6. 添加 mindoptcpp C++ API 源代码 (<MDOHOME>/<VERSION>/win64-x86/src/MindoptCppModel.cpp)。

  7. 右键单击目节点,然后选择 属性-> C/C++ -> 预处理器 -> 预处理器定义,添增 MDO_BUILDING_DLL

4.3.3. Linux

关于 C++ 语言的编译示例,请参考 <MDOHOME>/<VERSION>/examples/CPP。以下为编译方法和测试命令:

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

Note

用户需要至少运行此示例一次,以生成 mindoptcpp 动态库。

以下编译时用的 makefile 文件:

INCPATHS=-I../../linux64-x86/include -I.
LIBPATHS=-L../../linux64-x86/lib
MINDOPTLIB=-lmindopt -lmindoptcpp

CCOPT=-std=c++11
LDOPT=-Wl,-rpath-link,./../../linux64-x86/lib -Wl,-rpath,'$$ORIGIN/../../linux64-x86/lib' -pthread -lm -lstdc++ -Wl,--no-as-needed -ldl
CC=g++ -m64
LD=g++ -m64

EXAMPLES=mindoptcpp\
      MdoMps

mindoptcpp:
      make install -C ../../linux64-x86/src

MdoMps: MdoMps.cpp
      $(CC) -c $(INCPATHS) $(CCOPT) -o MdoMps.o MdoMps.cpp
      $(LD) $(LIBPATHS) MdoMps.o  $(MINDOPTLIB) $(LDOPT) -o MdoMps

4.3.4. OSX

关于 C++ 语言的编译示例,请参考 <MDOHOME>/<VERSION>/examples/CPP。以下为编译方法和测试命令:

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

Note

用户必须至少运行此例子一次,用来生成 mindoptcpp 动态库。

用来编译的 makefile 文件的内容如下所示:

INCPATHS=-I../../osx64-x86/include
LIBPATHS=-L../../osx64-x86/lib
MINDOPTLIB=-lmindopt.x.x.x -lmindoptcpp.x.x.x -rpath @executable_path/../../osx64-x86/lib/ -lpthread

CCOPT=-std=c++11
LDOPT=-Wl,-headerpad,128
CC=clang++
LD=clang++

%.o: %.cpp
      $(CC) -c -g $(INCPATHS) $(CCOPT) -o $@ $<

mindoptcpp:
      make install -C ../../osx64-x86/src

MdoMps: MdoMps.o
      $(CC) -g $(LIBPATHS) $(LDOPT) -o $@ $< $(MINDOPTLIB)
      install_name_tool -change libmindopt.x.x.x.dylib `pwd`/../../osx64-x86/lib/libmindopt.x.x.x.dylib $@
      install_name_tool -change libmindoptcpp.x.x.x.dylib `pwd`/../../osx64-x86/lib/libmindoptcpp.x.x.x.dylib $@

4.3.5. C++ 语言编译示例: MdoMps

以下,我们将展示如何用 MindOpt C++ API 来读取 MPS/LP 格式的优化问题并进行求解。

首先导入 C++ 头文件:

8#include "MindoptCpp.h"

然后,创建优化模型:

21    /*------------------------------------------------------------------*/
22    /* Step 1. Create a model and change the parameters.                */
23    /*------------------------------------------------------------------*/
24    /* Create an empty model. */
25    MdoModel model;

并使用 mindopt::MdoModel::readProb() 来读取 MPS/LP 格式的优化问题:

29        /*------------------------------------------------------------------*/
30        /* Step 2. Input model.                                             */
31        /*------------------------------------------------------------------*/
32        /* Read model from file. */
33        model.readProb(argv[1]);

最后,使用 mindopt::MdoModel::solveProb() 来求解问题,并调用 mindopt::MdoModel::displayResults() 来查看优化结果。

35        /*------------------------------------------------------------------*/
36        /* Step 3. Solve the problem and populate the result.               */
37        /*------------------------------------------------------------------*/
38        /* Solve the problem. */
39        model.solveProb();
40        model.displayResults();

以下为完整的源代码文件 MdoMps.cpp

 1/**
 2 *  Description
 3 *  -----------
 4 *
 5 *  Read model from an MPS/LP file, and call optimizer to solve the problem.
 6 */
 7#include <stdio.h>
 8#include "MindoptCpp.h"
 9
10using namespace mindopt;
11
12int main(
13    int argc,
14    char * argv[])
15{
16    if (argc != 2)
17    {
18        return 0;
19    }
20    
21    /*------------------------------------------------------------------*/
22    /* Step 1. Create a model and change the parameters.                */
23    /*------------------------------------------------------------------*/
24    /* Create an empty model. */
25    MdoModel model;
26
27    try 
28    {
29        /*------------------------------------------------------------------*/
30        /* Step 2. Input model.                                             */
31        /*------------------------------------------------------------------*/
32        /* Read model from file. */
33        model.readProb(argv[1]);
34
35        /*------------------------------------------------------------------*/
36        /* Step 3. Solve the problem and populate the result.               */
37        /*------------------------------------------------------------------*/
38        /* Solve the problem. */
39        model.solveProb();
40        model.displayResults();
41    }
42    catch (MdoException & e)
43    {
44        std::cerr << "===================================" << std::endl;
45        std::cerr << "Error   : code <" << e.getResult() << ">" << std::endl;
46        std::cerr << "Reason  : " << model.explainResult(e.getResult()) << std::endl;
47        std::cerr << "===================================" << std::endl;
48
49        return static_cast<int>(e.getResult());
50    }
51
52    return static_cast<int>(MDO_OKAY);
53}

在安装包的 <MDOHOME>/<VERSION>/examples/CPP 中可以找到更多 C++ 相关示例文件。