4.2. 使用 C 语言调用 MindOpt 动态库

4.2.1. 简要示意

// 方法1:从0.19.0版本开始引入新式的创建模型方式
MdoEnvPtr env;
MdoMdlPtr model;
Mdo_createEnv(&env);
Mdo_createMdlWithEnv(&model, env);
Mdo_readProb(model, filename);
Mdo_solveProb(model);
Mdo_displayResults(model);
Mdo_freeMdl(&model);
// C SDK 需要手动释放 env
Mdo_freeEnv(&env);

// 方法2:旧式的创建模型方式仍然支持
/*
MdoMdlPtr model;
Mdo_createMdl(&model);
Mdo_readProb(model, filename);
Mdo_solveProb(model);
Mdo_displayResults(model);
Mdo_freeMdl(&model);
*/

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

Note

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

4.2.2. Windows

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

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

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

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

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

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

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

4.2.3. Linux

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

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

以下编译时用的 makefile 文件:

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

CCOPT=
LDOPT=-Wl,-rpath-link,./../../linux64-x86/lib -Wl,-rpath,'$$ORIGIN/../../linux64-x86/include' -pthread -lc -lm -Wl,--no-as-needed -ldl
CC=cc -m64
LD=cc -m64

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

4.2.4. OSX

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

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

以下编译时用的 makefile 文件:

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

CCOPT=
LDOPT=-Wl,-headerpad,128
CC=clang
LD=clang

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

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 $@

4.2.5. C 语言编译示例: MdoMps

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

首先导入 C 头文件:

8#include "Mindopt.h"

然后,创建优化模型:

41    /*------------------------------------------------------------------*/
42    /* Step 1. Create a model and change the parameters.                */
43    /*------------------------------------------------------------------*/
44    /* Create an empty model. */
45    MDO_CHECK_CALL(Mdo_createMdl(&model));

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

47    /*------------------------------------------------------------------*/
48    /* Step 2. Input model.                                             */
49    /*------------------------------------------------------------------*/
50    /* Read model from file. */
51    MDO_CHECK_CALL(Mdo_readProb(model, filename));

再来,使用 Mdo_solveProb() 来求解问题,并调用 Mdo_displayResults() 来查看优化结果。

53    /*------------------------------------------------------------------*/
54    /* Step 3. Solve the problem and populate the result.               */
55    /*------------------------------------------------------------------*/
56    /* Solve the problem. */
57    MDO_CHECK_CALL(Mdo_solveProb(model));
58    Mdo_displayResults(model);

最后,使用 Mdo_freeMdl() 来释放内存空间。

60    /*------------------------------------------------------------------*/
61    /* Step 4. Free the model.                                          */
62    /*------------------------------------------------------------------*/
63    /* Free the model. */
64    Mdo_freeMdl(&model);

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

 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 "Mindopt.h"
 9
10/* Macro to check the return code */
11#define MDO_CHECK_CALL(MDO_CALL)                                    \
12    code = MDO_CALL;                                                \
13    if (code != MDO_OKAY)                                           \
14    {                                                               \
15        Mdo_explainResult(model, code, str);                        \
16        Mdo_freeMdl(&model);                                        \
17        fprintf(stderr, "===================================\n");   \
18        fprintf(stderr, "Error   : code <%d>\n", code);             \
19        fprintf(stderr, "Reason  : %s\n", str);                     \
20        fprintf(stderr, "===================================\n");   \
21        return (int)code;                                           \
22    }
23
24int main(
25    int argc,
26    char * argv[])
27{
28    if (argc != 2)
29    {
30        return 0;
31    }
32
33    /* Variables. */
34    char str[1024] = { "\0" };
35    char * filename = argv[1];
36    double val = 0.0;
37    MdoMdl * model = NULL;
38    MdoResult code = MDO_OKAY;
39    MdoStatus status = MDO_UNKNOWN;
40     
41    /*------------------------------------------------------------------*/
42    /* Step 1. Create a model and change the parameters.                */
43    /*------------------------------------------------------------------*/
44    /* Create an empty model. */
45    MDO_CHECK_CALL(Mdo_createMdl(&model));
46    
47    /*------------------------------------------------------------------*/
48    /* Step 2. Input model.                                             */
49    /*------------------------------------------------------------------*/
50    /* Read model from file. */
51    MDO_CHECK_CALL(Mdo_readProb(model, filename));
52
53    /*------------------------------------------------------------------*/
54    /* Step 3. Solve the problem and populate the result.               */
55    /*------------------------------------------------------------------*/
56    /* Solve the problem. */
57    MDO_CHECK_CALL(Mdo_solveProb(model));
58    Mdo_displayResults(model);
59
60    /*------------------------------------------------------------------*/
61    /* Step 4. Free the model.                                          */
62    /*------------------------------------------------------------------*/
63    /* Free the model. */
64    Mdo_freeMdl(&model);
65       
66    return (int)code;
67}

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