example_2.md 144 KB

使用过程提示

Tips:

  • 您可点击右下角“下一步”,查看后续的建模讲解和源代码。
  • 本教程文档是 .md 格式,此讲解窗口采用阿里云 CloudShell 的teachme指令打开,如命令行输入 teachme doc/fileName.md 命令打开。
  • CloudShell 默认模式是登录失效后线上机器内信息删除,建议您在本地机器上编辑和保存自己的代码,然后通过 CloudShell 左上角上传文件的方式上传,也可进行下载。CloudShell 窗口关闭后原登录信息会清除,建议同时开两个窗口,防止误操作关闭;同时不建议离开窗口太久导致登录失效。
  • 如果想体验运行MindOpt求解器代码,请①在天池-决策优化MindOpt网址申请免费的授权Token,并替换掉示例代码里的Token;②并安装MindOpt优化求解器的SDK:安装指导。如已安装,可跳过。

^___^ 还没体验过安装和运行求解器的同学,可以直接点击链接:一键安装MindOpt求解器,并一键用令行求解.mps或.lp文件~~

案例问题背景

营养调配问题的的目标是利用优化模型来设定每日饮食菜单,在满足各类营养的需求同时更能优化总成本.营养调配问题是可用线性优化来表达.本案例参考自:链接。其中

  • 决策变量为:起司汉堡 (Cheeseburger)、汉堡 (Hamburger)、火腿三明治 (Ham-sandwich)、鱼肉三民治 (Fish-sandwich)、鸡肉三民治 (Chicken-sandwich)、薯条 (Fries)、香肠比司吉 (Sausage biscuit)、低脂牛乳 (Low-fat milk)、和橙汁 (Orange juice);
  • 约束条件为:卡路里 (Cal.)、碳水化合物 (Carbo.)、蛋白质 (Portien)、维生素A/D (Vit. A/D)、铁 (Iron)和钙质 (Calc.)的每日摄取上/下限制,以及总量 (Volume) 限制;
  • 目标函数则为:总成本的最小化.

    问题定义

    类型

    线性优化问题

    集合

    image.png

    参数

    image.png

    决策变量

    image.png

    目标函数

    image.png

    约束条件

    image.png

    数据

  • 为简化表达,以下以食物的简称替代

食物 Cheese burger Ham sandwich Ham-burger Fish sandwich Chicken sandwich Fries Sausage biscuit Lowfat milk Orange juice
简称 CB HS H FS CS F SB LM OJ
  • 每单位食物的成本价
食物 CB HS H FS CS F SB LM OJ
成本 1.84 2.19 1.84 1.44 2.29 0.77 1.29 0.60 0.72
  • 各营养的单日摄取上限和下限
营养 Cal Carbo Protein VitA VitC Calc Iron Volume
下界 2000 355 55 100 100 100 100 -∞
上界 375 75
  • 各种食物的营养含量与容积量
食物 CB HS H FS CS F SB LM OJ
Cal 510 370 500 370 400 220 345 110 80
Carbo 34 55 42 38 42 26 27 12 20
Protein 28 24 25 14 31 3 15 9 1
VitA 15 15 6 2 8 0 4 10 2
VitC 6 10 2 0 15 15 0 4 120
Calc 30 20 25 15 15 0 20 30 2
Iron 20 20 20 10 8 2 15 0 2
Volume 4 7.5 3.5 5 7.3 2.6 4.1 8 12

Tips:案例内容可能参考自互联网,如有侵权,请联系我们删除。

源代码示例清单

当前MindOpt的远端计算版本(Client/Server版本)具备C、C++、Python 三种编程语言。下面将通过12个代码示例来展示,您可以直接查看自己熟悉的编程语言。

C MakeFile文件

  • 1.C语言范例1: 行输入方式
  • 2.C语言范例2: 列输入方式
  • 3.C语言范例3: .mps或.lp文件输入方式

C++ MakeFile文件

  • 4.C++语言范例1: 行输入方式
  • 5.C++语言范例2: 列输入方式
  • 6.C++语言范例3: 建模表达输入方式
  • 7.C++语言范例4: .mps或.lp文件输入方式

Python

  • 8.Python语言范例1: 行输入方式
  • 9.Python语言范例2: 列输入方式
  • 10.Python语言范例3: 建模表达输入方式
  • 11.Python语言范例4: .mps或.lp文件输入方式
  • 12.Python语言范例5:带Token参数运行求解.mps或.lp文件

C MakeFile 文件

step 1:建立一个makefile文件

如下。除示例nano指令外,编辑文件可使用vi、vim、nano、emacs等不同编辑器指令,或touch创建文件,也可采用CloudShell右上角的“笔”的编辑图标来选择对应的文档进行新增和修改。

mkdir c
cd c
mkdir tmp
nano makefile

然后复制下面的makefile的代码粘贴至makefile文件里,代码右上角有复制按钮(注意根据软件版本或安装地址来调整内容):

.RECIPEPREFIX = >
INCPATHS=-I$${HOME}/mindopt/linux64-x86/include
LIBPATHS=-L$${HOME}/mindopt/linux64-x86/lib

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

# the build target executable:
TARGET = example_2

all: $(TARGET)

$(TARGET).o: $(TARGET).c
>$(CC) -c -g $(INCPATHS) $(CCOPT) -o $@ $<

$(TARGET): $(TARGET).o
>$(CC) -g $(LIBPATHS) $(LDOPT) -o $@ $< $(MINDOPTLIB)

根据提示来修改和保存文件,如ctrl+o保存,然后看到对应名字OK后摁enter即可,如ctrl+x退出,如有修改保存按Y,再看到对应名字OK后摁enter即可退出。

也可采用CloudShell右上角的“笔”的编辑图标来选择对应的文档进行修改。

step 2: 创建一个c文件

此makefile编译的文件名默认为 example_2.c。可以通过以下指令新建文件,然后复制下面几页对应的C代码保存。(除示例nano指令外,编辑文件可使用vi、vim、nano、emacs等不同编辑器指令,或touch创建文件,也可采用CloudShell右上角的“笔”的编辑图标来选择对应的文档进行新增和修改。)

nano example_2.c

复制后面某页中的一个C代码粘贴,注意根据提示修改代码中的Token或jobID等信息。可根据nano的快捷键提示来修改和保存文件,如ctrl+o保存,再看到对应名字OK后摁enter即可,如ctrl+x退出,如有修改保存按Y,再看到对应名字OK后摁enter即可退出。

也可采用CloudShell右上角的“笔”的编辑图标来选择对应的文档进行修改。

此时得到文件如下示意:

ls

makefile  example_2.c ​

step 3:编译和运行

make编译代码和运行方法:

make
./example_2

注:问题提交远端计算Server后,会需要求解时间,请耐心等待。由于计算资源限制,同一Token同时间只能求解一个问题,请勿同时段提交太多次。如果代码运行失败,可能是mindopt环境变量链接失败,可重新走一遍安装步骤(安装指导)。

C语言范例1: 行输入方式

Tips:  如果想体验运行MindOpt求解器代码,请先在天池-决策优化MindOpt-免费使用上申请授权Token,并替换掉示例代码里的Token。

make编译的方法见前面页。

/**
 *  example_2_c1.c
 *  Description
 *  -----------
 *
 *  Linear optimization (diet problem).
 * 
 *  The goal is to select foods that satisfy daily nutritional requirements while minimizing the total cost. 
 *  The constraints in this problem limit the number of calories, the volume of good consumed, and the amount of 
 *  vitamins, protein, carbohydrates, calcium, and iron in the diet.
 *
 *  Note
 *  ----
 * 
 *  The model below will be inputted in a row-wise order.
 * 
 *  Formulation
 *  -----------
 *
 * Minimize
 * Obj:        1.840000000 Cheeseburger + 2.190000000 HamSandwich + 1.840000000 Hamburger + 1.440000000 FishSandwich +
 *             2.290000000 ChickenSandwich + 0.770000000 Fries + 1.290000000 SausageBiscuit + 0.600000000 LowfatMilk + 
 *             0.720000000 OrangeJuice
 * Subject To
 * Cal:        510 Cheeseburger + 370 HamSandwich + 500 Hamburger + 370 FishSandwich +
 *             400 ChickenSandwich + 220 Fries + 345 SausageBiscuit + 110 LowfatMilk + 80 OrangeJuice >= 2000
 * Carbo:      34 Cheeseburger + 35 HamSandwich + 42 Hamburger + 38 FishSandwich + 42 ChickenSandwich + 
 *             26 Fries + 27 SausageBiscuit + 12 LowfatMilk + 20 OrangeJuice <= 375
 * Carbo_low:  34 Cheeseburger + 35 HamSandwich + 42 Hamburger + 38 FishSandwich + 42 ChickenSandwich + 
 *             26 Fries + 27 SausageBiscuit + 12 LowfatMilk + 20 OrangeJuice >= 350
 * Protein:    28 Cheeseburger + 24 HamSandwich + 25 Hamburger + 14 FishSandwich + 31 ChickenSandwich + 
 *             3 Fries + 15 SausageBiscuit + 9 LowfatMilk + OrangeJuice >= 55
 * VitA:       15 Cheeseburger + 15 HamSandwich + 6 Hamburger + 2 FishSandwich + 8 ChickenSandwich + 
 *             4 SausageBiscuit + 10 LowfatMilk + 2 OrangeJuice >= 100
 * VitC:       6 Cheeseburger + 10 HamSandwich + 2 Hamburger + 15 ChickenSandwich + 
 *             15 Fries + 4 LowfatMilk + 120 OrangeJuice >= 100
 * Calc:       30 Cheeseburger + 20 HamSandwich + 25 Hamburger + 15 FishSandwich + 
 *             15 ChickenSandwich + 20 SausageBiscuit + 30 LowfatMilk + 2 OrangeJuice >= 100
 * Iron:       20 Cheeseburger + 20 HamSandwich + 20 Hamburger + 10 FishSandwich + 
 *             8 ChickenSandwich + 2 Fries + 15 SausageBiscuit + 2 OrangeJuice >= 100
 * Volume:     4 Cheeseburger + 7.500000000 HamSandwich + 3.500000000 Hamburger + 5 FishSandwich + 
 *             7.300000000 ChickenSandwich + 2.600000000 Fries + 4.100000000 SausageBiscuit + 8 LowfatMilk + 12 OrangeJuice <= 75
 * Bounds
 * End
 */
#include <stdio.h>
#if defined(__APPLE__) || defined(__linux__)
#   include <unistd.h>
#   define SLEEP_10_SEC sleep(10)
#else
#   include <windows.h>
#   define SLEEP_10_SEC Sleep(10000)
#endif
#include "Mindopt.h"

/* Macro to check the return code */
#define MDO_CHECK_CALL(MDO_CALL)                                    \
    code = MDO_CALL;                                                \
    if (code != MDO_OKAY)                                           \
    {                                                               \
        Mdo_explainResult(model, code, str);                        \
        Mdo_freeMdl(&model);                                        \
        fprintf(stderr, "===================================\n");   \
        fprintf(stderr, "Error   : code <%d>\n", code);             \
        fprintf(stderr, "Reason  : %s\n", str);                     \
        fprintf(stderr, "===================================\n");   \
        return (int)code;                                           \
    }

int main(void)
{
#define num_foods 9
#define num_reqs  8

    /* Remote computing related information. */
    const char * filepath = "./tmp/";
    const char * token = "xxxxxxxxxtokenxxxxxxxx";
    const char * server = "mindopt.tianchi.aliyun.com";
    const char * desc = "tianchi example2 MdoRemotLdDiet C1";

    /* Variables. */
    char         str[1024] = { "\0" };
    MdoResult    code = MDO_OKAY;
    MdoStatus    model_status = MDO_UNKNOWN;    
    char         model_status_details[1024] = { "\0" };    
    MdoResult    result = MDO_OKAY;    
    char         result_details[1024] = { "\0" };    
    MdoBool      has_soln = MDO_NO;        
    MdoMdl *     model = NULL;
    char         job_id[1024] = { "\0" };
    double       val = 0.0;    
    char         status[1024] = { "\0" };    
    double       soln[num_foods];
    int          i, j;

    /* Data. */                             
    const char food[num_foods][30] = 
    {
        "Cheeseburger", "HamSandwich", "Hamburger", "FishSandwich", 
        "ChickenSandwich", "Fries", "SausageBiscuit", "LowfatMilk", 
        "OrangeJuice"
    };
    const char req[num_reqs][30] = 
    {
        "Cal", "Carbo", "Protein", "VitA",
        "VitC", "Calc", "Iron", "Volume"
    };
    const double obj[num_foods] =
    { 
        1.84, 2.19, 1.84, 1.44, 2.29, 0.77, 1.29, 0.60, 0.72 
    };
    const double lb[num_foods] = 
    { 
        0, 0, 0, 0, 0, 0, 0, 0, 0 
    };
    const double ub[num_foods] = 
    {
        MDO_INFINITY, MDO_INFINITY, MDO_INFINITY, MDO_INFINITY,
        MDO_INFINITY, MDO_INFINITY, MDO_INFINITY, MDO_INFINITY,
        MDO_INFINITY
    };

    const double lhs[num_reqs] =
    { 
        2000, 350, 55,            100, 
        100,  100, 100, -MDO_INFINITY 
    };
    const double rhs[num_reqs] = 
    { 
        MDO_INFINITY,          375, MDO_INFINITY, MDO_INFINITY,
        MDO_INFINITY, MDO_INFINITY, MDO_INFINITY,            75 
    };

    const int idx_req[num_foods] = 
    {  
        0, 1, 2, 3, 4, 5, 6, 7, 8 
    };    
    const double val_req[num_reqs][num_foods] = 
    {
        { 510, 370, 500, 370, 400, 220, 345, 110,  80 },
        {  34,  35,  42,  38,  42,  26,  27,  12,  20 },
        {  28,  24,  25,  14,  31,   3,  15,   9,   1 },
        {  15,  15,   6,   2,   8,   0,   4,  10,   2 },
        {   6,  10,   2,   0,  15,  15,   0,   4, 120 },
        {  30,  20,  25,  15,  15,   0,  20,  30,   2 },
        {  20,  20,  20,  10,   8,   2,  15,   0,   2 },
        {   4, 7.5, 3.5,   5, 7.3, 2.6, 4.1,   8,  12 } 
    };

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

    /*------------------------------------------------------------------*/
    /* Step 2. Input model.                                             */
    /*------------------------------------------------------------------*/
    /* Change to minimization problem. */
    Mdo_setIntAttr(model, "MinSense", MDO_YES);

    /* Add variables. */
    for (j = 0; j < num_foods; ++j)
    {
        MDO_CHECK_CALL(Mdo_addCol(model, lb[j], ub[j], obj[j], 0, NULL, NULL, food[j], MDO_NO));
    }

    /* Add constraints. */
    for (i = 0; i < num_reqs; ++i)
    {
        MDO_CHECK_CALL(Mdo_addRow(model, lhs[i], rhs[i], num_foods, idx_req, val_req[i], req[i] ));
    }

    /*------------------------------------------------------------------*/
    /* Step 3. Input parameters related to the remote computing server. */
    /*------------------------------------------------------------------*/
    /* Input parameters related to remote computing. */
    Mdo_setStrParam(model, "Remote/Token", token);
    Mdo_setStrParam(model, "Remote/Desc", desc);
    Mdo_setStrParam(model, "Remote/Server", server); 
    Mdo_setStrParam(model, "Remote/File/Path", filepath);

    /*------------------------------------------------------------------*/
    /* Step 4. Upload the serialized model and parameters to server, and*/
    /*         then optimize the model.                                 */
    /*------------------------------------------------------------------*/
    MDO_CHECK_CALL(Mdo_submitTask(model, job_id));
    if (job_id[0] == '\0')
    {
        printf("ERROR: Invalid job ID: %s\n", job_id);
        MDO_CHECK_CALL(MDO_ERROR);
    }
    else
    {
        printf("Job was submitted to server successfully.\n");
        printf("User may query the optimization result with the following job ID: %s\n", job_id);
    }

    /*------------------------------------------------------------------*/
    /* Step 5. Check the solution status periodically, and              */
    /*         download the its upon availability.                      */
    /*------------------------------------------------------------------*/
    do 
    {        
        MDO_CHECK_CALL(Mdo_retrieveTask(model, job_id, status, &model_status, &result, &has_soln));

        /* Sleep for 10 seconds. */
        SLEEP_10_SEC;
    }
    while (status[0] == 'S'); /* Continue the loop if the status is in either Submitted status or Solving status. */

    /*------------------------------------------------------------------*/
    /* Step 6. Retrieve the solution and then populate the result.      */
    /*------------------------------------------------------------------*/  
    printf("\nPopulating optimization results.\n");    
    Mdo_explainStatus(model, model_status, model_status_details);
    Mdo_explainResult(model, result, result_details);

    printf(" - Job status             : %s\n", status);    
    printf(" - Model status           : %s (%d)\n", model_status_details, model_status);
    printf(" - Optimization status    : %s (%d)\n", result_details, result);
    printf(" - Solution availability  : %s\n", has_soln ? "available" : "not available");
    if (has_soln)
    {
        printf("\nPopulating solution.\n");    
        Mdo_displayResults(model);

        switch (Mdo_getStatus(model))
        {
        case MDO_UNKNOWN:
            printf("Optimizer terminated with an UNKNOWN status.\n");
            break;
        case MDO_OPTIMAL:
            MDO_CHECK_CALL(Mdo_getRealAttr(model, "PrimalObjVal", &val));
            printf("Optimizer terminated with an OPTIMAL status.\n");
            printf("%-20s: $%.2f\n", "Daily cost", val);
            MDO_CHECK_CALL(Mdo_getRealAttrArray(model, "PrimalSoln", 0, num_foods, soln));
            for (j = 0; j < num_foods; ++j)
            {
                if (soln[j] > 0.01)
                {
                    printf(" - %-17s: %.2f\n", food[j], soln[j]);
                }
            }
            break;
        case MDO_INFEASIBLE:
            printf("Optimizer terminated with an INFEASIBLE status.\n");
            break;
        case MDO_UNBOUNDED:
            printf("Optimizer terminated with an UNBOUNDED status.\n");
            break;
        case MDO_INF_OR_UBD:
            printf("Optimizer terminated with an INFEASIBLE or UNBOUNDED status.\n");
            break;
        }
    }

    /*------------------------------------------------------------------*/
    /* Step 7. Free the model.                                          */
    /*------------------------------------------------------------------*/
    /* Free the model. */
    Mdo_freeMdl(&model);

    return (int)code;
}

C语言范例2: 列输入方式

Tips:  如果想体验运行MindOpt求解器代码,请先在天池-决策优化MindOpt-免费使用上申请授权Token,并替换掉示例代码里的Token。

make编译的方法见前面页。

/**
 *  example_2_c2.c
 *  Description
 *  -----------
 *
 *  Linear optimization (diet problem).
 * 
 *  The goal is to select foods that satisfy daily nutritional requirements while minimizing the total cost. 
 *  The constraints in this problem limit the number of calories, the volume of good consumed, and the amount of 
 *  vitamins, protein, carbohydrates, calcium, and iron in the diet.
 *
 *  Note
 *  ----
 * 
 *  The model below will be inputted in a row-wise order.
 * 
 *  Formulation
 *  -----------
 *
 * Minimize
 * Obj:        1.840000000 Cheeseburger + 2.190000000 HamSandwich + 1.840000000 Hamburger + 1.440000000 FishSandwich +
 *             2.290000000 ChickenSandwich + 0.770000000 Fries + 1.290000000 SausageBiscuit + 0.600000000 LowfatMilk + 
 *             0.720000000 OrangeJuice
 * Subject To
 * Cal:        510 Cheeseburger + 370 HamSandwich + 500 Hamburger + 370 FishSandwich +
 *             400 ChickenSandwich + 220 Fries + 345 SausageBiscuit + 110 LowfatMilk + 80 OrangeJuice >= 2000
 * Carbo:      34 Cheeseburger + 35 HamSandwich + 42 Hamburger + 38 FishSandwich + 42 ChickenSandwich + 
 *             26 Fries + 27 SausageBiscuit + 12 LowfatMilk + 20 OrangeJuice <= 375
 * Carbo_low:  34 Cheeseburger + 35 HamSandwich + 42 Hamburger + 38 FishSandwich + 42 ChickenSandwich + 
 *             26 Fries + 27 SausageBiscuit + 12 LowfatMilk + 20 OrangeJuice >= 350
 * Protein:    28 Cheeseburger + 24 HamSandwich + 25 Hamburger + 14 FishSandwich + 31 ChickenSandwich + 
 *             3 Fries + 15 SausageBiscuit + 9 LowfatMilk + OrangeJuice >= 55
 * VitA:       15 Cheeseburger + 15 HamSandwich + 6 Hamburger + 2 FishSandwich + 8 ChickenSandwich + 
 *             4 SausageBiscuit + 10 LowfatMilk + 2 OrangeJuice >= 100
 * VitC:       6 Cheeseburger + 10 HamSandwich + 2 Hamburger + 15 ChickenSandwich + 
 *             15 Fries + 4 LowfatMilk + 120 OrangeJuice >= 100
 * Calc:       30 Cheeseburger + 20 HamSandwich + 25 Hamburger + 15 FishSandwich + 
 *             15 ChickenSandwich + 20 SausageBiscuit + 30 LowfatMilk + 2 OrangeJuice >= 100
 * Iron:       20 Cheeseburger + 20 HamSandwich + 20 Hamburger + 10 FishSandwich + 
 *             8 ChickenSandwich + 2 Fries + 15 SausageBiscuit + 2 OrangeJuice >= 100
 * Volume:     4 Cheeseburger + 7.500000000 HamSandwich + 3.500000000 Hamburger + 5 FishSandwich + 
 *             7.300000000 ChickenSandwich + 2.600000000 Fries + 4.100000000 SausageBiscuit + 8 LowfatMilk + 12 OrangeJuice <= 75
 * Bounds
 * End
 */
#include <stdio.h>
#if defined(__APPLE__) || defined(__linux__)
#   include <unistd.h>
#   define SLEEP_10_SEC sleep(10)
#else
#   include <windows.h>
#   define SLEEP_10_SEC Sleep(10000)
#endif
#include "Mindopt.h"

/* Macro to check the return code */
#define MDO_CHECK_CALL(MDO_CALL)                                    \
    code = MDO_CALL;                                                \
    if (code != MDO_OKAY)                                           \
    {                                                               \
        Mdo_explainResult(model, code, str);                        \
        Mdo_freeMdl(&model);                                        \
        fprintf(stderr, "===================================\n");   \
        fprintf(stderr, "Error   : code <%d>\n", code);             \
        fprintf(stderr, "Reason  : %s\n", str);                     \
        fprintf(stderr, "===================================\n");   \
        return (int)code;                                           \
    }

int main(void)
{
#define num_foods 9
#define num_reqs  8

    /* Remote computing related information. */
    const char * filepath = "./tmp/";
    const char * token = "xxxxxxxxxtokenxxxxxxxx";
    const char * server = "mindopt.tianchi.aliyun.com";
    const char * desc = "tianchi example2 MdoRemotLdDiet C2";

    /* Variables. */
    char         str[1024] = { "\0" };
    MdoResult    code = MDO_OKAY;
    MdoStatus    model_status = MDO_UNKNOWN;    
    char         model_status_details[1024] = { "\0" };    
    MdoResult    result = MDO_OKAY;    
    char         result_details[1024] = { "\0" };    
    MdoBool      has_soln = MDO_NO;        
    MdoMdl *     model = NULL;
    char         job_id[1024] = { "\0" };
    double       val = 0.0;    
    char         status[1024] = { "\0" };    
    double       soln[num_foods];
    int          i, j;

    /* Data. */                         
    const char food[num_foods][30] = 
    {
        "Cheeseburger", "HamSandwich", "Hamburger", "FishSandwich", 
        "ChickenSandwich", "Fries", "SausageBiscuit", "LowfatMilk", 
        "OrangeJuice"
    };
    const char req[num_reqs][30] = 
    {
        "Cal", "Carbo", "Protein", "VitA",
        "VitC", "Calc", "Iron", "Volume"
    };
    const double obj[num_foods] =
    { 
        1.84, 2.19, 1.84, 1.44, 2.29, 0.77, 1.29, 0.60, 0.72 
    };
    const double lb[num_foods] = 
    { 
        0, 0, 0, 0, 0, 0, 0, 0, 0 
    };
    const double ub[num_foods] = 
    {
        MDO_INFINITY, MDO_INFINITY, MDO_INFINITY, MDO_INFINITY,
        MDO_INFINITY, MDO_INFINITY, MDO_INFINITY, MDO_INFINITY,
        MDO_INFINITY
    };

    const double lhs[num_reqs] =
    { 
        2000, 350, 55,            100, 
        100,  100, 100, -MDO_INFINITY 
    };
    const double rhs[num_reqs] = 
    { 
        MDO_INFINITY,          375, MDO_INFINITY, MDO_INFINITY,
        MDO_INFINITY, MDO_INFINITY, MDO_INFINITY,            75 
    };

    const int idx_col[num_reqs] = 
    {  
        0, 1, 2, 3, 4, 5, 6, 7
    };    
    double val_col[num_reqs];
    const double val_req[num_reqs][num_foods] = 
    {
        { 510, 370, 500, 370, 400, 220, 345, 110,  80 },
        {  34,  35,  42,  38,  42,  26,  27,  12,  20 },
        {  28,  24,  25,  14,  31,   3,  15,   9,   1 },
        {  15,  15,   6,   2,   8,   0,   4,  10,   2 },
        {   6,  10,   2,   0,  15,  15,   0,   4, 120 },
        {  30,  20,  25,  15,  15,   0,  20,  30,   2 },
        {  20,  20,  20,  10,   8,   2,  15,   0,   2 },
        {   4, 7.5, 3.5,   5, 7.3, 2.6, 4.1,   8,  12 } 
    };

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

    /*------------------------------------------------------------------*/
    /* Step 2. Input model.                                             */
    /*------------------------------------------------------------------*/
    /* Change to minimization problem. */
    Mdo_setIntAttr(model, "MinSense", MDO_YES);

    /* Add variables. */
    for (j = 0; j < num_foods; ++j)
    {
        for (i = 0; i < num_reqs; ++i)
        {
            val_col[i] = val_req[i][j];
        }        
        MDO_CHECK_CALL(Mdo_addCol(model, lb[j], ub[j], obj[j], num_reqs, idx_col, val_col, food[j], MDO_NO));
    }

    /* Change the LHS and RHS values of the constraints. */
    for (i = 0; i < num_reqs; ++i)
    {
        MDO_CHECK_CALL(Mdo_setRealAttrIndex(model, "LHS", i, lhs[i]));
        MDO_CHECK_CALL(Mdo_setRealAttrIndex(model, "RHS", i, rhs[i]));
    }

    /*------------------------------------------------------------------*/
    /* Step 3. Input parameters related to the remote computing server. */
    /*------------------------------------------------------------------*/
    /* Input parameters related to remote computing. */
    Mdo_setStrParam(model, "Remote/Token", token);
    Mdo_setStrParam(model, "Remote/Desc", desc);
    Mdo_setStrParam(model, "Remote/Server", server); 
    Mdo_setStrParam(model, "Remote/File/Path", filepath);

    /*------------------------------------------------------------------*/
    /* Step 4. Upload the serialized model and parameters to server, and*/
    /*         then optimize the model.                                 */
    /*------------------------------------------------------------------*/
    MDO_CHECK_CALL(Mdo_submitTask(model, job_id));
    if (job_id[0] == '\0')
    {
        printf("ERROR: Invalid job ID: %s\n", job_id);
        MDO_CHECK_CALL(MDO_ERROR);
    }
    else
    {
        printf("Job was submitted to server successfully.\n");
        printf("User may query the optimization result with the following job ID: %s\n", job_id);
    }

    /*------------------------------------------------------------------*/
    /* Step 5. Check the solution status periodically, and              */
    /*         download the its upon availability.                      */
    /*------------------------------------------------------------------*/
    do 
    {        
        MDO_CHECK_CALL(Mdo_retrieveTask(model, job_id, status, &model_status, &result, &has_soln));

        /* Sleep for 10 seconds. */
        SLEEP_10_SEC;
    }
    while (status[0] == 'S'); /* Continue the loop if the status is in either Submitted status or Solving status. */

    /*------------------------------------------------------------------*/
    /* Step 6. Retrieve the solution and then populate the result.      */
    /*------------------------------------------------------------------*/  
    printf("\nPopulating optimization results.\n");    
    Mdo_explainStatus(model, model_status, model_status_details);
    Mdo_explainResult(model, result, result_details);

    printf(" - Job status             : %s\n", status);    
    printf(" - Model status           : %s (%d)\n", model_status_details, model_status);
    printf(" - Optimization status    : %s (%d)\n", result_details, result);
    printf(" - Solution availability  : %s\n", has_soln ? "available" : "not available");
    if (has_soln)
    {
        printf("\nPopulating solution.\n");    
        Mdo_displayResults(model);

        switch (Mdo_getStatus(model))
        {
        case MDO_UNKNOWN:
            printf("Optimizer terminated with an UNKNOWN status.\n");
            break;
        case MDO_OPTIMAL:
            MDO_CHECK_CALL(Mdo_getRealAttr(model, "PrimalObjVal", &val));
            printf("Optimizer terminated with an OPTIMAL status.\n");
            printf("%-20s: $%.2f\n", "Daily cost", val);
            MDO_CHECK_CALL(Mdo_getRealAttrArray(model, "PrimalSoln", 0, num_foods, soln));
            for (j = 0; j < num_foods; ++j)
            {
                if (soln[j] > 0.01)
                {
                    printf(" - %-17s: %.2f\n", food[j], soln[j]);
                }
            }
            break;
        case MDO_INFEASIBLE:
            printf("Optimizer terminated with an INFEASIBLE status.\n");
            break;
        case MDO_UNBOUNDED:
            printf("Optimizer terminated with an UNBOUNDED status.\n");
            break;
        case MDO_INF_OR_UBD:
            printf("Optimizer terminated with an INFEASIBLE or UNBOUNDED status.\n");
            break;
        }
    }

    /*------------------------------------------------------------------*/
    /* Step 7. Free the model.                                          */
    /*------------------------------------------------------------------*/
    /* Free the model. */
    Mdo_freeMdl(&model);

    return (int)code;
}

C语言范例3: .mps或.lp文件输入方式

模型文件

本案例讲解如何采用导入文件模型的方式来提交求解。当前支持.mps.lp文件。 ​

示例数据:data/example2_mps_file_model.mps
这个文件是根据前面的API建模然后Mdo_writeProb(model, "my_model.{mps/lp}") 创建的。也可以用其他的求解器软件来导出.mps或者.lp文件。

您也可以上传自己的模型文件,可通过CloudShell左上角的图标来上传和下载文件。上传文件图标截图如下。

此方法目前仅能支持不超过 10M 的文件。如果有更大的文件,可以wget、git clone等方式来下载导入(参考软件安装里面的 git clone 和 unzip),也可以绑定阿里云的NAS。

image.png

C 代码

代码如下,make编译的方法见前面页。 ​

Tips:  如果想体验运行MindOpt求解器代码,请先在天池-决策优化MindOpt-免费使用上申请授权Token,并替换掉示例代码里的Token。

/**
 *  example_2_c3.c
 *  Description
 *  -----------
 *
 *  Linear optimization (diet problem).
 * 
 *  The goal is to select foods that satisfy daily nutritional requirements while minimizing the total cost. 
 *  The constraints in this problem limit the number of calories, the volume of good consumed, and the amount of 
 *  vitamins, protein, carbohydrates, calcium, and iron in the diet.
 *
 *  Note
 *  ----
 * 
 *  The model below will be inputted in a row-wise order.
 * 
 *  Formulation
 *  -----------
 *
 * Minimize
 * Obj:        1.840000000 Cheeseburger + 2.190000000 HamSandwich + 1.840000000 Hamburger + 1.440000000 FishSandwich +
 *             2.290000000 ChickenSandwich + 0.770000000 Fries + 1.290000000 SausageBiscuit + 0.600000000 LowfatMilk + 
 *             0.720000000 OrangeJuice
 * Subject To
 * Cal:        510 Cheeseburger + 370 HamSandwich + 500 Hamburger + 370 FishSandwich +
 *             400 ChickenSandwich + 220 Fries + 345 SausageBiscuit + 110 LowfatMilk + 80 OrangeJuice >= 2000
 * Carbo:      34 Cheeseburger + 35 HamSandwich + 42 Hamburger + 38 FishSandwich + 42 ChickenSandwich + 
 *             26 Fries + 27 SausageBiscuit + 12 LowfatMilk + 20 OrangeJuice <= 375
 * Carbo_low:  34 Cheeseburger + 35 HamSandwich + 42 Hamburger + 38 FishSandwich + 42 ChickenSandwich + 
 *             26 Fries + 27 SausageBiscuit + 12 LowfatMilk + 20 OrangeJuice >= 350
 * Protein:    28 Cheeseburger + 24 HamSandwich + 25 Hamburger + 14 FishSandwich + 31 ChickenSandwich + 
 *             3 Fries + 15 SausageBiscuit + 9 LowfatMilk + OrangeJuice >= 55
 * VitA:       15 Cheeseburger + 15 HamSandwich + 6 Hamburger + 2 FishSandwich + 8 ChickenSandwich + 
 *             4 SausageBiscuit + 10 LowfatMilk + 2 OrangeJuice >= 100
 * VitC:       6 Cheeseburger + 10 HamSandwich + 2 Hamburger + 15 ChickenSandwich + 
 *             15 Fries + 4 LowfatMilk + 120 OrangeJuice >= 100
 * Calc:       30 Cheeseburger + 20 HamSandwich + 25 Hamburger + 15 FishSandwich + 
 *             15 ChickenSandwich + 20 SausageBiscuit + 30 LowfatMilk + 2 OrangeJuice >= 100
 * Iron:       20 Cheeseburger + 20 HamSandwich + 20 Hamburger + 10 FishSandwich + 
 *             8 ChickenSandwich + 2 Fries + 15 SausageBiscuit + 2 OrangeJuice >= 100
 * Volume:     4 Cheeseburger + 7.500000000 HamSandwich + 3.500000000 Hamburger + 5 FishSandwich + 
 *             7.300000000 ChickenSandwich + 2.600000000 Fries + 4.100000000 SausageBiscuit + 8 LowfatMilk + 12 OrangeJuice <= 75
 * Bounds
 * End
 */
#include <stdio.h>
#if defined(__APPLE__) || defined(__linux__)
#   include <unistd.h>
#   define SLEEP_10_SEC sleep(10)
#else
#   include <windows.h>
#   define SLEEP_10_SEC Sleep(10000)
#endif
#include "Mindopt.h"

/* Macro to check the return code */
#define MDO_CHECK_CALL(MDO_CALL)                                    \
    code = MDO_CALL;                                                \
    if (code != MDO_OKAY)                                           \
    {                                                               \
        Mdo_explainResult(model, code, str);                        \
        Mdo_freeMdl(&model);                                        \
        fprintf(stderr, "===================================\n");   \
        fprintf(stderr, "Error   : code <%d>\n", code);             \
        fprintf(stderr, "Reason  : %s\n", str);                     \
        fprintf(stderr, "===================================\n");   \
        return (int)code;                                           \
    }

int main(void)
{
#define num_foods 9
#define num_reqs  8

    /* Remote computing related information. */
    const char * filepath = "./tmp/";
    const char * token = "xxxxxxxxxtokenxxxxxxxx";
    const char * server = "mindopt.tianchi.aliyun.com";
    const char * desc = "tianchi example2 MdoRemotLdDiet C3";

    /* Input mps file (optimization problem) */
    const char * input_file = "~/mindopt-open-examples/data/example2_mps_file_model.mps";

    /* Variables. */
    char         str[1024] = { "\0" };
    MdoResult    code = MDO_OKAY;
    MdoStatus    model_status = MDO_UNKNOWN;    
    char         model_status_details[1024] = { "\0" };    
    MdoResult    result = MDO_OKAY;    
    char         result_details[1024] = { "\0" };    
    MdoBool      has_soln = MDO_NO;        
    MdoMdl *     model = NULL;
    char         job_id[1024] = { "\0" };
    double       val = 0.0;    
    char         status[1024] = { "\0" };    
    double       soln[num_foods];
    char         food[num_foods][1024] = { "\0" };

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

    /*------------------------------------------------------------------*/
    /* Step 2. Input model.                                             */
    /*------------------------------------------------------------------*/
    /* Read model from file. */
    MDO_CHECK_CALL(Mdo_readProb(model, input_file));

    /* Input parameters. */
    Mdo_setIntParam(model, "NumThreads", 4);
    Mdo_setRealParam(model, "MaxTime", 3600);

    /*------------------------------------------------------------------*/
    /* Step 3. Input parameters related to the remote computing server. */
    /*------------------------------------------------------------------*/
    /* Input parameters related to remote computing. */
    Mdo_setStrParam(model, "Remote/Token", token);
    Mdo_setStrParam(model, "Remote/Desc", desc);
    Mdo_setStrParam(model, "Remote/Server", server); 
    Mdo_setStrParam(model, "Remote/File/Path", filepath);

    /*------------------------------------------------------------------*/
    /* Step 4. Upload the serialized model and parameters to server, and*/
    /*         then optimize the model.                                 */
    /*------------------------------------------------------------------*/
    MDO_CHECK_CALL(Mdo_submitTask(model, job_id));
    if (job_id[0] == '\0')
    {
        printf("ERROR: Invalid job ID: %s\n", job_id);
        MDO_CHECK_CALL(MDO_ERROR);
    }
    else
    {
        printf("Job was submitted to server successfully.\n");
        printf("User may query the optimization result with the following job ID: %s\n", job_id);
    }

    /*------------------------------------------------------------------*/
    /* Step 5. Check the solution status periodically, and              */
    /*         download the its upon availability.                      */
    /*------------------------------------------------------------------*/
    do 
    {        
        MDO_CHECK_CALL(Mdo_retrieveTask(model, job_id, status, &model_status, &result, &has_soln));

        /* Sleep for 10 seconds. */
        SLEEP_10_SEC;
    }
    while (status[0] == 'S'); /* Continue the loop if the status is in either Submitted status or Solving status. */

    /*------------------------------------------------------------------*/
    /* Step 6. Retrieve the solution and then populate the result.      */
    /*------------------------------------------------------------------*/  
    printf("\nPopulating optimization results.\n");    
    Mdo_explainStatus(model, model_status, model_status_details);
    Mdo_explainResult(model, result, result_details);

    printf(" - Job status             : %s\n", status);    
    printf(" - Model status           : %s (%d)\n", model_status_details, model_status);
    printf(" - Optimization status    : %s (%d)\n", result_details, result);
    printf(" - Solution availability  : %s\n", has_soln ? "available" : "not available");
    if (has_soln)
    {
        printf("\nPopulating solution.\n");    
        Mdo_displayResults(model);

        switch (Mdo_getStatus(model))
        {
        case MDO_UNKNOWN:
            printf("Optimizer terminated with an UNKNOWN status.\n");
            break;
        case MDO_OPTIMAL:
            MDO_CHECK_CALL(Mdo_getRealAttr(model, "PrimalObjVal", &val));
            printf("Optimizer terminated with an OPTIMAL status.\n");
            printf("%-20s: $%.2f\n", "Daily cost", val);
            MDO_CHECK_CALL(Mdo_getRealAttrArray(model, "PrimalSoln", 0, num_foods, soln));
            for (int j = 0; j < num_foods; ++j)
            {
                MDO_CHECK_CALL(Mdo_getStrAttrIndex(model, "ColName", j, 1024, food[j]));
                if (soln[j] > 0.01)
                {
                    printf(" - %-17s: %.2f\n", food[j], soln[j]);
                }
            }
            break;
        case MDO_INFEASIBLE:
            printf("Optimizer terminated with an INFEASIBLE status.\n");
            break;
        case MDO_UNBOUNDED:
            printf("Optimizer terminated with an UNBOUNDED status.\n");
            break;
        case MDO_INF_OR_UBD:
            printf("Optimizer terminated with an INFEASIBLE or UNBOUNDED status.\n");
            break;
        }
    }

    /*------------------------------------------------------------------*/
    /* Step 7. Free the model.                                          */
    /*------------------------------------------------------------------*/
    /* Free the model. */
    Mdo_freeMdl(&model);

    return (int)code;
}

C++ MakeFile 文件

step 1:建立一个makefile文件

如下。除示例nano指令外,编辑文件可使用vi、vim、nano、emacs等不同编辑器指令,或touch创建文件,也可采用CloudShell右上角的“笔”的编辑图标来选择对应的文档进行新增和修改。

mkdir cpp
cd cpp
mkdir tmp
nano Makefile

然后复制下面的makefile的代码,代码右上角有复制按钮(注意根据安装地址来调整):

注意:mindoptcpp 动态库将在运行软件包中的示例时自动生成。换言之,用户在使用 C++ API 之前必须至少运行一次例子软件包中的例子,因此下面的makefile代码中有mindoptcpp的编译部分。

.RECIPEPREFIX = >
INCPATHS=-I$${HOME}/mindopt/linux64-x86/include -I.
LIBPATHS=-L$${HOME}/mindopt/linux64-x86/lib
MINDOPTLIB=-lmindopt -lmindoptcpp

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

MINDOPTCPP=mindoptcpp
EXAMPLES=example_2

mindoptcpp:
>make install -C $${HOME}/mindopt/linux64-x86/src

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


ALL-TESTS := @echo "Started testing MindOpt package."

#########################################################################
# Clean up and testing                                                  #
#########################################################################
.PHONY: all clean cleanall test

all: $(EXAMPLES)

clean:
>rm -f *.o $(EXAMPLES)

mindoptcpp: $(MINDOPTCPP)

test: $(EXAMPLES)
>@echo "###################################"
>@echo "# Started testing MindOpt package.#"
>@echo "###################################"
>@echo ""
>@echo "###################################"
>@echo "# TEST: MdoMps                    #"
>@echo "###################################"
>./example_2

根据提示来修改和保存文件,如ctrl+o保存,然后看到对应名字OK后摁enter即可,如ctrl+x退出,如有修改保存按Y,再看到对应名字OK后摁enter即可退出。

也可采用CloudShell右上角的“笔”的编辑图标来选择对应的文档进行修改。

step 2: 创建一个cpp文件

此makefile编译的文件名默认为 example_2.cpp。可以通过以下指令新建文件,然后复制对应的代码保存。除示例nano指令外,编辑文件可使用vi、vim、nano、emacs等不同编辑器指令,或touch创建文件,也可采用CloudShell右上角的“笔”的编辑图标来选择对应的文档进行新增和修改。

nano example_2.cpp

复制后面3页中的一个C++代码粘贴。然后根据提示来修改和保存文件,如ctrl+o保存,然后看到对应名字OK后摁enter即可,如ctrl+x退出,如有修改保存按Y,再看到对应名字OK后摁enter即可退出。

也可采用CloudShell右上角的“笔”的编辑图标来选择对应的文档进行修改。

step 3:编译和运行

make mindoptcpp的编译代码方法(编译一次即可,以后可跳过):

make -f Makefile mindoptcpp

make 编译示例代码和运行的方法:

make -f Makefile test

注:问题提交远端计算Server后,会需要求解时间,请耐心等待。由于计算资源限制,同一Token同时间只能求解一个问题,请勿同时段提交太多次。如果代码运行失败,可能是mindopt环境变量链接失败,可重新走一遍安装步骤(安装指导)。

C++语言范例1: 行输入方式

Tips:  如果想体验运行MindOpt求解器代码,请先在天池-决策优化MindOpt-免费使用上申请授权Token,并替换掉示例代码里的Token。

make编译的方法见前面页。

/**
 *  example_2_cpp1.cpp
 *  Description
 *  -----------
 *
 *  Linear optimization (diet problem).
 * 
 *  The goal is to select foods that satisfy daily nutritional requirements while minimizing the total cost. 
 *  The constraints in this problem limit the number of calories, the volume of good consumed, and the amount of 
 *  vitamins, protein, carbohydrates, calcium, and iron in the diet.
 *
 *  Note
 *  ----
 * 
 *  The model below will be inputted in a row-wise order.
 * 
 *  Formulation
 *  -----------
 *
 * Minimize
 * Obj:        1.840000000 Cheeseburger + 2.190000000 HamSandwich + 1.840000000 Hamburger + 1.440000000 FishSandwich +
 *             2.290000000 ChickenSandwich + 0.770000000 Fries + 1.290000000 SausageBiscuit + 0.600000000 LowfatMilk + 
 *             0.720000000 OrangeJuice
 * Subject To
 * Cal:        510 Cheeseburger + 370 HamSandwich + 500 Hamburger + 370 FishSandwich +
 *             400 ChickenSandwich + 220 Fries + 345 SausageBiscuit + 110 LowfatMilk + 80 OrangeJuice >= 2000
 * Carbo:      34 Cheeseburger + 35 HamSandwich + 42 Hamburger + 38 FishSandwich + 42 ChickenSandwich + 
 *             26 Fries + 27 SausageBiscuit + 12 LowfatMilk + 20 OrangeJuice <= 375
 * Carbo_low:  34 Cheeseburger + 35 HamSandwich + 42 Hamburger + 38 FishSandwich + 42 ChickenSandwich + 
 *             26 Fries + 27 SausageBiscuit + 12 LowfatMilk + 20 OrangeJuice >= 350
 * Protein:    28 Cheeseburger + 24 HamSandwich + 25 Hamburger + 14 FishSandwich + 31 ChickenSandwich + 
 *             3 Fries + 15 SausageBiscuit + 9 LowfatMilk + OrangeJuice >= 55
 * VitA:       15 Cheeseburger + 15 HamSandwich + 6 Hamburger + 2 FishSandwich + 8 ChickenSandwich + 
 *             4 SausageBiscuit + 10 LowfatMilk + 2 OrangeJuice >= 100
 * VitC:       6 Cheeseburger + 10 HamSandwich + 2 Hamburger + 15 ChickenSandwich + 
 *             15 Fries + 4 LowfatMilk + 120 OrangeJuice >= 100
 * Calc:       30 Cheeseburger + 20 HamSandwich + 25 Hamburger + 15 FishSandwich + 
 *             15 ChickenSandwich + 20 SausageBiscuit + 30 LowfatMilk + 2 OrangeJuice >= 100
 * Iron:       20 Cheeseburger + 20 HamSandwich + 20 Hamburger + 10 FishSandwich + 
 *             8 ChickenSandwich + 2 Fries + 15 SausageBiscuit + 2 OrangeJuice >= 100
 * Volume:     4 Cheeseburger + 7.500000000 HamSandwich + 3.500000000 Hamburger + 5 FishSandwich + 
 *             7.300000000 ChickenSandwich + 2.600000000 Fries + 4.100000000 SausageBiscuit + 8 LowfatMilk + 12 OrangeJuice <= 75
 * Bounds
 * End
 */
#include <stdio.h>
#if defined(__APPLE__) || defined(__linux__)
#   include <unistd.h>
#   define SLEEP_10_SEC sleep(10)
#else
#   include <windows.h>
#   define SLEEP_10_SEC Sleep(10000)
#endif
#include <iostream>
#include <vector>
#include <functional>
#include "MindoptCpp.h"

using namespace mindopt;

int main(void)
{
#define num_foods 9
#define num_reqs  8

    /* Remote computing related information. */
    const char * filepath = "./tmp/";
    const char * token = "xxxxxxxxxtokenxxxxxxxx";
    const char * server = "mindopt.tianchi.aliyun.com";
    const char * desc = "tianchi example2 MdoRemotLdDiet CPP1";

    /* Variables. */
    MdoStatus    model_status = MDO_UNKNOWN;    
    std::string  model_status_details;    
    MdoResult    result = MDO_OKAY;    
    std::string  result_details;    
    MdoBool      has_soln = MDO_NO;        
    std::string  job_id;
    std::string  status;    
    int          i, j;

    /* Data. */                                 
    const char food[num_foods][30] = 
    {
        "Cheeseburger", "HamSandwich", "Hamburger", "FishSandwich", 
        "ChickenSandwich", "Fries", "SausageBiscuit", "LowfatMilk", 
        "OrangeJuice"
    };
    const char req[num_reqs][30] = 
    {
        "Cal", "Carbo", "Protein", "VitA",
        "VitC", "Calc", "Iron", "Volume"
    };
    const double obj[num_foods] =
    { 
        1.84, 2.19, 1.84, 1.44, 2.29, 0.77, 1.29, 0.60, 0.72 
    };
    const double lb[num_foods] = 
    { 
        0, 0, 0, 0, 0, 0, 0, 0, 0 
    };
    const double ub[num_foods] = 
    {
        MDO_INFINITY, MDO_INFINITY, MDO_INFINITY, MDO_INFINITY,
        MDO_INFINITY, MDO_INFINITY, MDO_INFINITY, MDO_INFINITY,
        MDO_INFINITY
    };

    const double lhs[num_reqs] =
    { 
        2000, 350, 55,            100, 
        100,  100, 100, -MDO_INFINITY 
    };
    const double rhs[num_reqs] = 
    { 
        MDO_INFINITY,          375, MDO_INFINITY, MDO_INFINITY,
        MDO_INFINITY, MDO_INFINITY, MDO_INFINITY,            75 
    };

    const double req_value[num_foods][num_foods] = 
    {  
        { 510, 370, 500, 370, 400, 220, 345, 110,  80 }, /* Cal */
        {  34,  35,  42,  38,  42,  26,  27,  12,  20 }, /* Carbo */
        {  28,  24,  25,  14,  31,   3,  15,   9,   1 }, /* Protein */
        {  15,  15,   6,   2,   8,   0,   4,  10,   2 }, /* VitA */
        {   6,  10,   2,   0,  15,  15,   0,   4, 120 }, /* VitC */
        {  30,  20,  25,  15,  15,   0,  20,  30,   2 }, /* Calc */
        {  20,  20,  20,  10,   8,   2,  15,   0,   2 }, /* Iron */
        {   4, 7.5, 3.5,   5, 7.3, 2.6, 4.1,   8,  12 }  /* Volume */
    };    

    /*------------------------------------------------------------------*/
    /* Step 1. Create a model and change the parameters.                */
    /*------------------------------------------------------------------*/
    /* Create an empty model. */
    MdoModel model;
    std::vector<std::reference_wrapper<MdoVar> > var;

    try 
    {
        /*------------------------------------------------------------------*/
        /* Step 2. Input model.                                             */
        /*------------------------------------------------------------------*/
        /* Change to minimization problem. */
        model.setIntAttr("MinSense", MDO_YES);

        /* Add variables. */
        for (j = 0; j < num_foods; ++j)
        {
            var.push_back(model.addVar(lb[j], ub[j], obj[j], food[j], MDO_NO));
        }

        /* Add constraints. */
        for (i = 0; i < num_reqs; ++i)
        {
            MdoExprLinear expr;
            for (j = 0; j < num_foods; ++j)
            {
                expr += req_value[i][j] * var[j].get();
            }
            model.addCons(lhs[i], rhs[i], expr, req[i]);             
        }

        /*------------------------------------------------------------------*/
        /* Step 3. Input parameters related to the remote computing server. */
        /*------------------------------------------------------------------*/
        /* Input parameters related to remote computing. */
        model.setStrParam("Remote/Token", token);
        model.setStrParam("Remote/Desc", desc);
        model.setStrParam("Remote/Server", server); 
        model.setStrParam("Remote/File/Path", filepath);

        /*------------------------------------------------------------------*/
        /* Step 4. Upload the serialized model and parameters to server, and*/
        /*         then optimize the model.                                 */
        /*------------------------------------------------------------------*/
        job_id = model.submitTask();
        if (job_id.empty())
        {
            std::cerr << "ERROR: Invalid job ID: " << job_id << std::endl;
            return static_cast<int>(MDO_ERROR);
        }
        else
        {
            std::cout << "Job was submitted to server successfully." << std::endl;
            std::cout << "User may query the optimization result with the following job ID: " << job_id << std::endl;
        }

        /*------------------------------------------------------------------*/
        /* Step 5. Check the solution status periodically, and              */
        /*         download the its upon availability.                      */
        /*------------------------------------------------------------------*/
        do 
        {        
            status = model.retrieveTask(job_id, model_status, result, has_soln);

            /* Sleep for 10 seconds. */
            SLEEP_10_SEC;
        }
        while (status[0] == 'S'); /* Continue the loop if the status is in either Submitted status or Solving status. */

        /*------------------------------------------------------------------*/
        /* Step 6. Retrieve the solution and then populate the result.      */
        /*------------------------------------------------------------------*/  
        std::cout << std::endl << "Populating optimization results." << std::endl;   
        model_status_details = model.explainStatus(model_status);
        result_details = model.explainResult(result);

        std::cout << " - Job status             : " << status << std::endl;
        std::cout << " - Model status           : " << model_status_details << " (" << model_status << ")" << std::endl;
        std::cout << " - Optimization status    : " << result_details << " (" << result << ")" << std::endl;
        std::cout << " - Solution availability  : " << std::string(has_soln ? "available" : "not available") << std::endl;
        if (has_soln)
        {
            std::cout << "Populating solution." << std::endl;    
            model.displayResults();

            switch (model.getStatus())
            {
            case MDO_UNKNOWN:
                std::cout << "Optimizer terminated with an UNKNOWN status." << std::endl;
                break;
            case MDO_OPTIMAL:
                std::cout << "Optimizer terminated with an OPTIMAL status." << std::endl;
                std::cout << "Daily cost          : $" << model.getRealAttr("PrimalObjVal") << std::endl;
                var = model.getVars();
                for (j = 0; j < num_foods; ++j)
                {
                    double val = var[j].get().getRealAttr("PrimalSoln");
                    if (val > 0.01)
                    {
                        printf(" - %-17s: %.2f\n", food[j], val);
                    }
                }
                break;
            case MDO_INFEASIBLE:
                std::cout << "Optimizer terminated with an INFEASIBLE status." << std::endl;
                break;
            case MDO_UNBOUNDED:
                std::cout << "Optimizer terminated with an UNBOUNDED status." << std::endl;
                break;
            case MDO_INF_OR_UBD:
                std::cout << "Optimizer terminated with an INFEASIBLE or UNBOUNDED status." << std::endl;
                break;
            }
        }
    }
    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);
}

C++语言范例2: 列输入方式

Tips:  如果想体验运行MindOpt求解器代码,请先在天池-决策优化MindOpt-免费使用上申请授权Token,并替换掉示例代码里的Token。

make编译的方法见前面页。

/**
 *  example_2_cpp2.cpp
 *  Description
 *  -----------
 *
 *  Linear optimization (diet problem).
 * 
 *  The goal is to select foods that satisfy daily nutritional requirements while minimizing the total cost. 
 *  The constraints in this problem limit the number of calories, the volume of good consumed, and the amount of 
 *  vitamins, protein, carbohydrates, calcium, and iron in the diet.
 *
 *  Note
 *  ----
 * 
 *  The model below will be inputted in a row-wise order.
 * 
 *  Formulation
 *  -----------
 *
 * Minimize
 * Obj:        1.840000000 Cheeseburger + 2.190000000 HamSandwich + 1.840000000 Hamburger + 1.440000000 FishSandwich +
 *             2.290000000 ChickenSandwich + 0.770000000 Fries + 1.290000000 SausageBiscuit + 0.600000000 LowfatMilk + 
 *             0.720000000 OrangeJuice
 * Subject To
 * Cal:        510 Cheeseburger + 370 HamSandwich + 500 Hamburger + 370 FishSandwich +
 *             400 ChickenSandwich + 220 Fries + 345 SausageBiscuit + 110 LowfatMilk + 80 OrangeJuice >= 2000
 * Carbo:      34 Cheeseburger + 35 HamSandwich + 42 Hamburger + 38 FishSandwich + 42 ChickenSandwich + 
 *             26 Fries + 27 SausageBiscuit + 12 LowfatMilk + 20 OrangeJuice <= 375
 * Carbo_low:  34 Cheeseburger + 35 HamSandwich + 42 Hamburger + 38 FishSandwich + 42 ChickenSandwich + 
 *             26 Fries + 27 SausageBiscuit + 12 LowfatMilk + 20 OrangeJuice >= 350
 * Protein:    28 Cheeseburger + 24 HamSandwich + 25 Hamburger + 14 FishSandwich + 31 ChickenSandwich + 
 *             3 Fries + 15 SausageBiscuit + 9 LowfatMilk + OrangeJuice >= 55
 * VitA:       15 Cheeseburger + 15 HamSandwich + 6 Hamburger + 2 FishSandwich + 8 ChickenSandwich + 
 *             4 SausageBiscuit + 10 LowfatMilk + 2 OrangeJuice >= 100
 * VitC:       6 Cheeseburger + 10 HamSandwich + 2 Hamburger + 15 ChickenSandwich + 
 *             15 Fries + 4 LowfatMilk + 120 OrangeJuice >= 100
 * Calc:       30 Cheeseburger + 20 HamSandwich + 25 Hamburger + 15 FishSandwich + 
 *             15 ChickenSandwich + 20 SausageBiscuit + 30 LowfatMilk + 2 OrangeJuice >= 100
 * Iron:       20 Cheeseburger + 20 HamSandwich + 20 Hamburger + 10 FishSandwich + 
 *             8 ChickenSandwich + 2 Fries + 15 SausageBiscuit + 2 OrangeJuice >= 100
 * Volume:     4 Cheeseburger + 7.500000000 HamSandwich + 3.500000000 Hamburger + 5 FishSandwich + 
 *             7.300000000 ChickenSandwich + 2.600000000 Fries + 4.100000000 SausageBiscuit + 8 LowfatMilk + 12 OrangeJuice <= 75
 * Bounds
 * End
 */
#include <stdio.h>
#if defined(__APPLE__) || defined(__linux__)
#   include <unistd.h>
#   define SLEEP_10_SEC sleep(10)
#else
#   include <windows.h>
#   define SLEEP_10_SEC Sleep(10000)
#endif
#include <iostream>
#include <vector>
#include <functional>
#include "MindoptCpp.h"

using namespace mindopt;

int main(void)
{
#define num_foods 9
#define num_reqs  8

    /* Remote computing related information. */
    const char * filepath = "./tmp/";
    const char * token = "xxxxxxxxxtokenxxxxxxxx";
    const char * server = "mindopt.tianchi.aliyun.com";
    const char * desc = "tianchi example2 MdoRemotLdDiet CPP2";

    /* Variables. */
    MdoStatus    model_status = MDO_UNKNOWN;    
    std::string  model_status_details;    
    MdoResult    result = MDO_OKAY;    
    std::string  result_details;    
    MdoBool      has_soln = MDO_NO;        
    std::string  job_id;
    std::string  status;    
    int          i, j;

    /* Data. */                                 
    const char food[num_foods][30] = 
    {
        "Cheeseburger", "HamSandwich", "Hamburger", "FishSandwich", 
        "ChickenSandwich", "Fries", "SausageBiscuit", "LowfatMilk", 
        "OrangeJuice"
    };
    const char req[num_reqs][30] = 
    {
        "Cal", "Carbo", "Protein", "VitA",
        "VitC", "Calc", "Iron", "Volume"
    };
    const double obj[num_foods] =
    { 
        1.84, 2.19, 1.84, 1.44, 2.29, 0.77, 1.29, 0.60, 0.72 
    };
    const double lb[num_foods] = 
    { 
        0, 0, 0, 0, 0, 0, 0, 0, 0 
    };
    const double ub[num_foods] = 
    {
        MDO_INFINITY, MDO_INFINITY, MDO_INFINITY, MDO_INFINITY,
        MDO_INFINITY, MDO_INFINITY, MDO_INFINITY, MDO_INFINITY,
        MDO_INFINITY
    };

    const double lhs[num_reqs] =
    { 
        2000, 350, 55,            100, 
        100,  100, 100, -MDO_INFINITY 
    };
    const double rhs[num_reqs] = 
    { 
        MDO_INFINITY,          375, MDO_INFINITY, MDO_INFINITY,
        MDO_INFINITY, MDO_INFINITY, MDO_INFINITY,            75 
    }; 
    const double req_value[num_foods][num_foods] = 
    {  
        { 510, 370, 500, 370, 400, 220, 345, 110,  80 }, /* Cal */
        {  34,  35,  42,  38,  42,  26,  27,  12,  20 }, /* Carbo */
        {  28,  24,  25,  14,  31,   3,  15,   9,   1 }, /* Protein */
        {  15,  15,   6,   2,   8,   0,   4,  10,   2 }, /* VitA */
        {   6,  10,   2,   0,  15,  15,   0,   4, 120 }, /* VitC */
        {  30,  20,  25,  15,  15,   0,  20,  30,   2 }, /* Calc */
        {  20,  20,  20,  10,   8,   2,  15,   0,   2 }, /* Iron */
        {   4, 7.5, 3.5,   5, 7.3, 2.6, 4.1,   8,  12 }  /* Volume */
    };    

    /*------------------------------------------------------------------*/
    /* Step 1. Create a model and change the parameters.                */
    /*------------------------------------------------------------------*/
    /* Create an empty model. */
    MdoModel model;
    std::vector<std::reference_wrapper<MdoVar> > var;

    try 
    {
        /*------------------------------------------------------------------*/
        /* Step 2. Input model.                                             */
        /*------------------------------------------------------------------*/
        /* Change to minimization problem. */
        model.setIntAttr("MinSense", MDO_YES);

        /* Add constraints. */
        std::vector<MdoCons> cons;
        for (i = 0; i < num_reqs; ++i)
        {
            cons.push_back(model.addCons(lhs[i], rhs[i], req[i]));             
        }

        /* Add variables. */
        for (j = 0; j < num_foods; ++j)
        {
            MdoCol col;

            for (i = 0; i < num_reqs; ++i)
            {
                col.addTerm(cons[i], req_value[i][j]);            
            }
            var.push_back(model.addVar(lb[j], ub[j], obj[j], col, food[j], MDO_NO));
        }

        /*------------------------------------------------------------------*/
        /* Step 3. Input parameters related to the remote computing server. */
        /*------------------------------------------------------------------*/
        /* Input parameters related to remote computing. */
        model.setStrParam("Remote/Token", token);
        model.setStrParam("Remote/Desc", desc);
        model.setStrParam("Remote/Server", server); 
        model.setStrParam("Remote/File/Path", filepath);

        /*------------------------------------------------------------------*/
        /* Step 4. Upload the serialized model and parameters to server, and*/
        /*         then optimize the model.                                 */
        /*------------------------------------------------------------------*/
        job_id = model.submitTask();
        if (job_id.empty())
        {
            std::cerr << "ERROR: Invalid job ID: " << job_id << std::endl;
            return static_cast<int>(MDO_ERROR);
        }
        else
        {
            std::cout << "Job was submitted to server successfully." << std::endl;
            std::cout << "User may query the optimization result with the following job ID: " << job_id << std::endl;
        }

        /*------------------------------------------------------------------*/
        /* Step 5. Check the solution status periodically, and              */
        /*         download the its upon availability.                      */
        /*------------------------------------------------------------------*/
        do 
        {        
            status = model.retrieveTask(job_id, model_status, result, has_soln);

            /* Sleep for 10 seconds. */
            SLEEP_10_SEC;
        }
        while (status[0] == 'S'); /* Continue the loop if the status is in either Submitted status or Solving status. */

        /*------------------------------------------------------------------*/
        /* Step 6. Retrieve the solution and then populate the result.      */
        /*------------------------------------------------------------------*/  
        std::cout << std::endl << "Populating optimization results." << std::endl;   
        model_status_details = model.explainStatus(model_status);
        result_details = model.explainResult(result);

        std::cout << " - Job status             : " << status << std::endl;
        std::cout << " - Model status           : " << model_status_details << " (" << model_status << ")" << std::endl;
        std::cout << " - Optimization status    : " << result_details << " (" << result << ")" << std::endl;
        std::cout << " - Solution availability  : " << std::string(has_soln ? "available" : "not available") << std::endl;
        if (has_soln)
        {
            std::cout << "Populating solution." << std::endl;    
            model.displayResults();

            switch (model.getStatus())
            {
            case MDO_UNKNOWN:
                std::cout << "Optimizer terminated with an UNKNOWN status." << std::endl;
                break;
            case MDO_OPTIMAL:
                std::cout << "Optimizer terminated with an OPTIMAL status." << std::endl;
                std::cout << "Daily cost          : $" << model.getRealAttr("PrimalObjVal") << std::endl;
                var = model.getVars();
                for (j = 0; j < num_foods; ++j)
                {
                    double val = var[j].get().getRealAttr("PrimalSoln");
                    if (val > 0.01)
                    {
                        printf(" - %-17s: %.2f\n", food[j], val);
                    }
                }
                break;
            case MDO_INFEASIBLE:
                std::cout << "Optimizer terminated with an INFEASIBLE status." << std::endl;
                break;
            case MDO_UNBOUNDED:
                std::cout << "Optimizer terminated with an UNBOUNDED status." << std::endl;
                break;
            case MDO_INF_OR_UBD:
                std::cout << "Optimizer terminated with an INFEASIBLE or UNBOUNDED status." << std::endl;
                break;
            }
        }
    }
    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);
}

C++语言范例3: 建模表达输入方式

Tips:  如果想体验运行MindOpt求解器代码,请先在天池-决策优化MindOpt-免费使用上申请授权Token,并替换掉示例代码里的Token。

make编译的方法见前面页。

/**
 *  example_2_cpp3.cpp
 *  Description
 *  -----------
 *
 *  Linear optimization (diet problem).
 * 
 *  The goal is to select foods that satisfy daily nutritional requirements while minimizing the total cost. 
 *  The constraints in this problem limit the number of calories, the volume of good consumed, and the amount of 
 *  vitamins, protein, carbohydrates, calcium, and iron in the diet.
 *
 *  Note
 *  ----
 * 
 *  The model below will be inputted in a row-wise order.
 * 
 *  Formulation
 *  -----------
 *
 * Minimize
 * Obj:        1.840000000 Cheeseburger + 2.190000000 HamSandwich + 1.840000000 Hamburger + 1.440000000 FishSandwich +
 *             2.290000000 ChickenSandwich + 0.770000000 Fries + 1.290000000 SausageBiscuit + 0.600000000 LowfatMilk + 
 *             0.720000000 OrangeJuice
 * Subject To
 * Cal:        510 Cheeseburger + 370 HamSandwich + 500 Hamburger + 370 FishSandwich +
 *             400 ChickenSandwich + 220 Fries + 345 SausageBiscuit + 110 LowfatMilk + 80 OrangeJuice >= 2000
 * Carbo:      34 Cheeseburger + 35 HamSandwich + 42 Hamburger + 38 FishSandwich + 42 ChickenSandwich + 
 *             26 Fries + 27 SausageBiscuit + 12 LowfatMilk + 20 OrangeJuice <= 375
 * Carbo_low:  34 Cheeseburger + 35 HamSandwich + 42 Hamburger + 38 FishSandwich + 42 ChickenSandwich + 
 *             26 Fries + 27 SausageBiscuit + 12 LowfatMilk + 20 OrangeJuice >= 350
 * Protein:    28 Cheeseburger + 24 HamSandwich + 25 Hamburger + 14 FishSandwich + 31 ChickenSandwich + 
 *             3 Fries + 15 SausageBiscuit + 9 LowfatMilk + OrangeJuice >= 55
 * VitA:       15 Cheeseburger + 15 HamSandwich + 6 Hamburger + 2 FishSandwich + 8 ChickenSandwich + 
 *             4 SausageBiscuit + 10 LowfatMilk + 2 OrangeJuice >= 100
 * VitC:       6 Cheeseburger + 10 HamSandwich + 2 Hamburger + 15 ChickenSandwich + 
 *             15 Fries + 4 LowfatMilk + 120 OrangeJuice >= 100
 * Calc:       30 Cheeseburger + 20 HamSandwich + 25 Hamburger + 15 FishSandwich + 
 *             15 ChickenSandwich + 20 SausageBiscuit + 30 LowfatMilk + 2 OrangeJuice >= 100
 * Iron:       20 Cheeseburger + 20 HamSandwich + 20 Hamburger + 10 FishSandwich + 
 *             8 ChickenSandwich + 2 Fries + 15 SausageBiscuit + 2 OrangeJuice >= 100
 * Volume:     4 Cheeseburger + 7.500000000 HamSandwich + 3.500000000 Hamburger + 5 FishSandwich + 
 *             7.300000000 ChickenSandwich + 2.600000000 Fries + 4.100000000 SausageBiscuit + 8 LowfatMilk + 12 OrangeJuice <= 75
 * Bounds
 * End
 */
#include <stdio.h>
#if defined(__APPLE__) || defined(__linux__)
#   include <unistd.h>
#   define SLEEP_10_SEC sleep(10)
#else
#   include <windows.h>
#   define SLEEP_10_SEC Sleep(10000)
#endif
#include <iostream>
#include <vector>
#include <functional>
#include "MindoptCpp.h"

using namespace mindopt;

int main(void)
{
#define num_foods 9
#define num_reqs  8

    /* Remote computing related information. */
    const char * filepath = "./tmp/";
    const char * token = "xxxxxxxxxtokenxxxxxxxx";
    const char * server = "mindopt.tianchi.aliyun.com";
    const char * desc = "tianchi example2 MdoRemotLdDiet CPP3";

    /* Variables. */
    MdoStatus    model_status = MDO_UNKNOWN;    
    std::string  model_status_details;    
    MdoResult    result = MDO_OKAY;    
    std::string  result_details;    
    MdoBool      has_soln = MDO_NO;        
    std::string  job_id;
    std::string  status;    
    int          i, j;

    /*------------------------------------------------------------------*/
    /* Step 1. Create a model and change the parameters.                */
    /*------------------------------------------------------------------*/
    /* Create an empty model. */
    MdoModel model;

    try 
    {
        /*------------------------------------------------------------------*/
        /* Step 2. Input model.                                             */
        /*------------------------------------------------------------------*/
        /* Change to minimization problem. */
        model.setIntAttr("MinSense", MDO_YES);

        /* Add variables. */
        MdoVar Cheeseburger    = model.addVar(0, MDO_INFINITY, 1.84, "Cheeseburger",    MDO_NO);
        MdoVar HamSandwich     = model.addVar(0, MDO_INFINITY, 2.19, "HamSandwich",     MDO_NO);
        MdoVar Hamburger       = model.addVar(0, MDO_INFINITY, 1.84, "Hamburger",       MDO_NO);
        MdoVar FishSandwich    = model.addVar(0, MDO_INFINITY, 1.44, "FishSandwich",    MDO_NO);
        MdoVar ChickenSandwich = model.addVar(0, MDO_INFINITY, 2.29, "ChickenSandwich", MDO_NO);
        MdoVar Fries           = model.addVar(0, MDO_INFINITY, 0.77, "Fries",           MDO_NO);
        MdoVar SausageBiscuit  = model.addVar(0, MDO_INFINITY, 1.29, "SausageBiscuit",  MDO_NO);
        MdoVar LowfatMilk      = model.addVar(0, MDO_INFINITY, 0.60, "LowfatMilk",      MDO_NO);
        MdoVar OrangeJuice     = model.addVar(0, MDO_INFINITY, 0.72, "OrangeJuice",     MDO_NO);

        /* Add constraints. */
        model.addCons(200, MDO_INFINITY, 
            510 * Cheeseburger + 370 * HamSandwich + 500 * Hamburger + 370 * FishSandwich + 
            400 * ChickenSandwich + 220 * Fries + 345 * SausageBiscuit + 110 * LowfatMilk + 
            80 * OrangeJuice, 
            "Cal");
        model.addCons(350, 375, 
            34 * Cheeseburger + 35 * HamSandwich + 42 * Hamburger + 38 * FishSandwich + 
            42 * ChickenSandwich + 26 * Fries + 27 * SausageBiscuit + 12 * LowfatMilk +
            20 * OrangeJuice, 
            "Carbo"); 
        model.addCons(55, MDO_INFINITY, 
            28 * Cheeseburger + 24 * HamSandwich + 25 * Hamburger + 14 * FishSandwich + 
            31 * ChickenSandwich + 3 * Fries + 15 * SausageBiscuit + 9 * LowfatMilk + 
            OrangeJuice, 
            "Protein");
        model.addCons(100, MDO_INFINITY, 
            15 * Cheeseburger + 15 * HamSandwich + 6 * Hamburger + 2 * FishSandwich + 
            8 * ChickenSandwich + 4 * SausageBiscuit + 10 * LowfatMilk + 2 * OrangeJuice, 
            "VitA");
        model.addCons(100, MDO_INFINITY, 
            6 * Cheeseburger + 10 * HamSandwich + 2 * Hamburger + 15 * ChickenSandwich + 
            15 * Fries + 4 * LowfatMilk + 120 * OrangeJuice, "VitC");
        model.addCons(100, MDO_INFINITY,
            30 * Cheeseburger + 20 * HamSandwich + 25 * Hamburger + 15 * FishSandwich + 
            15 * ChickenSandwich + 20 * SausageBiscuit + 30 * LowfatMilk + 2 * OrangeJuice,
            "Calc");
        model.addCons(100, MDO_INFINITY, 
            20 * Cheeseburger + 20 * HamSandwich + 20 * Hamburger + 10 * FishSandwich + 
            8 * ChickenSandwich + 2 * Fries + 15 * SausageBiscuit + 2 * OrangeJuice, 
            "Iron");
        model.addCons(-MDO_INFINITY, 75,
             4 * Cheeseburger + 7.5 * HamSandwich + 3.5 * Hamburger + 5 * FishSandwich + 
            7.3 * ChickenSandwich + 2.6 * Fries + 4.1 * SausageBiscuit + 8 *  LowfatMilk + 
            12 * OrangeJuice , 
            "Volume");

        /*------------------------------------------------------------------*/
        /* Step 3. Input parameters related to the remote computing server. */
        /*------------------------------------------------------------------*/
        /* Input parameters related to remote computing. */
        model.setStrParam("Remote/Token", token);
        model.setStrParam("Remote/Desc", desc);
        model.setStrParam("Remote/Server", server); 
        model.setStrParam("Remote/File/Path", filepath);

        /*------------------------------------------------------------------*/
        /* Step 4. Upload the serialized model and parameters to server, and*/
        /*         then optimize the model.                                 */
        /*------------------------------------------------------------------*/
        job_id = model.submitTask();
        if (job_id.empty())
        {
            std::cerr << "ERROR: Invalid job ID: " << job_id << std::endl;
            return static_cast<int>(MDO_ERROR);
        }
        else
        {
            std::cout << "Job was submitted to server successfully." << std::endl;
            std::cout << "User may query the optimization result with the following job ID: " << job_id << std::endl;
        }

        /*------------------------------------------------------------------*/
        /* Step 5. Check the solution status periodically, and              */
        /*         download the its upon availability.                      */
        /*------------------------------------------------------------------*/
        do 
        {        
            status = model.retrieveTask(job_id, model_status, result, has_soln);

            /* Sleep for 10 seconds. */
            SLEEP_10_SEC;
        }
        while (status[0] == 'S'); /* Continue the loop if the status is in either Submitted status or Solving status. */

        /*------------------------------------------------------------------*/
        /* Step 6. Retrieve the solution and then populate the result.      */
        /*------------------------------------------------------------------*/  
        std::cout << std::endl << "Populating optimization results." << std::endl;   
        model_status_details = model.explainStatus(model_status);
        result_details = model.explainResult(result);

        std::cout << " - Job status             : " << status << std::endl;
        std::cout << " - Model status           : " << model_status_details << " (" << model_status << ")" << std::endl;
        std::cout << " - Optimization status    : " << result_details << " (" << result << ")" << std::endl;
        std::cout << " - Solution availability  : " << std::string(has_soln ? "available" : "not available") << std::endl;
        if (has_soln)
        {
            std::cout << "Populating solution." << std::endl;    
            model.displayResults();

            switch (model.getStatus())
            {
            case MDO_UNKNOWN:
                std::cout << "Optimizer terminated with an UNKNOWN status." << std::endl;
                break;
            case MDO_OPTIMAL:
                std::cout << "Optimizer terminated with an OPTIMAL status." << std::endl;
                std::cout << "Daily cost          : $" << model.getRealAttr("PrimalObjVal") << std::endl;
                std::cout << " - Cheeseburger     : " << Cheeseburger.getRealAttr("PrimalSoln") << std::endl;
                std::cout << " - Hamburger        : " << Hamburger.getRealAttr("PrimalSoln") << std::endl;
                std::cout << " - FishSandwich     : " << FishSandwich.getRealAttr("PrimalSoln") << std::endl;
                std::cout << " - ChickenSandwich  : " << ChickenSandwich.getRealAttr("PrimalSoln") << std::endl;
                std::cout << " - Fries            : " << Fries.getRealAttr("PrimalSoln") << std::endl;
                std::cout << " - SausageBiscuit   : " << SausageBiscuit.getRealAttr("PrimalSoln") << std::endl;
                std::cout << " - LowfatMilk       : " << LowfatMilk.getRealAttr("PrimalSoln") << std::endl;
                std::cout << " - OrangeJuice      : " << OrangeJuice.getRealAttr("PrimalSoln") << std::endl;
                break;
            case MDO_INFEASIBLE:
                std::cout << "Optimizer terminated with an INFEASIBLE status." << std::endl;
                break;
            case MDO_UNBOUNDED:
                std::cout << "Optimizer terminated with an UNBOUNDED status." << std::endl;
                break;
            case MDO_INF_OR_UBD:
                std::cout << "Optimizer terminated with an INFEASIBLE or UNBOUNDED status." << std::endl;
                break;
            }
        }
    }
    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);
}

C++语言范例4: .mps或.lp文件输入方式

模型文件

本案例讲解如何采用导入文件模型的方式来提交求解。当前支持.mps.lp文件。 示例数据:data/example2_mps_file_model.mps 是根据前面的API建模然后Mdo_writeProb(model, "my_model.{mps/lp}") 创建的。也可以用其他的求解器软件来导出.mps或者.lp文件。

您也可以上传自己的模型文件,可通过CloudShell左上角的图标来上传和下载文件。上传文件图标截图如下。

此方法目前仅能支持不超过 10M 的文件。如果有更大的文件,可以wget、git clone等方式来下载导入(参考软件安装里面的 git clone 和 unzip),也可以绑定阿里云的NAS。

image.png

C++ 代码

代码如下,make编译的方法见前面页。

Tips:  如果想体验运行MindOpt求解器代码,请先在天池-决策优化MindOpt-免费使用上申请授权Token,并替换掉示例代码里的Token。

/**
 *  example_2_cpp4.cpp
 *  Description
 *  -----------
 *
 *  Linear optimization (diet problem).
 * 
 *  The goal is to select foods that satisfy daily nutritional requirements while minimizing the total cost. 
 *  The constraints in this problem limit the number of calories, the volume of good consumed, and the amount of 
 *  vitamins, protein, carbohydrates, calcium, and iron in the diet.
 *
 *  Note
 *  ----
 * 
 *  The model below will be inputted in a row-wise order.
 * 
 *  Formulation
 *  -----------
 *
 * Minimize
 * Obj:        1.840000000 Cheeseburger + 2.190000000 HamSandwich + 1.840000000 Hamburger + 1.440000000 FishSandwich +
 *             2.290000000 ChickenSandwich + 0.770000000 Fries + 1.290000000 SausageBiscuit + 0.600000000 LowfatMilk + 
 *             0.720000000 OrangeJuice
 * Subject To
 * Cal:        510 Cheeseburger + 370 HamSandwich + 500 Hamburger + 370 FishSandwich +
 *             400 ChickenSandwich + 220 Fries + 345 SausageBiscuit + 110 LowfatMilk + 80 OrangeJuice >= 2000
 * Carbo:      34 Cheeseburger + 35 HamSandwich + 42 Hamburger + 38 FishSandwich + 42 ChickenSandwich + 
 *             26 Fries + 27 SausageBiscuit + 12 LowfatMilk + 20 OrangeJuice <= 375
 * Carbo_low:  34 Cheeseburger + 35 HamSandwich + 42 Hamburger + 38 FishSandwich + 42 ChickenSandwich + 
 *             26 Fries + 27 SausageBiscuit + 12 LowfatMilk + 20 OrangeJuice >= 350
 * Protein:    28 Cheeseburger + 24 HamSandwich + 25 Hamburger + 14 FishSandwich + 31 ChickenSandwich + 
 *             3 Fries + 15 SausageBiscuit + 9 LowfatMilk + OrangeJuice >= 55
 * VitA:       15 Cheeseburger + 15 HamSandwich + 6 Hamburger + 2 FishSandwich + 8 ChickenSandwich + 
 *             4 SausageBiscuit + 10 LowfatMilk + 2 OrangeJuice >= 100
 * VitC:       6 Cheeseburger + 10 HamSandwich + 2 Hamburger + 15 ChickenSandwich + 
 *             15 Fries + 4 LowfatMilk + 120 OrangeJuice >= 100
 * Calc:       30 Cheeseburger + 20 HamSandwich + 25 Hamburger + 15 FishSandwich + 
 *             15 ChickenSandwich + 20 SausageBiscuit + 30 LowfatMilk + 2 OrangeJuice >= 100
 * Iron:       20 Cheeseburger + 20 HamSandwich + 20 Hamburger + 10 FishSandwich + 
 *             8 ChickenSandwich + 2 Fries + 15 SausageBiscuit + 2 OrangeJuice >= 100
 * Volume:     4 Cheeseburger + 7.500000000 HamSandwich + 3.500000000 Hamburger + 5 FishSandwich + 
 *             7.300000000 ChickenSandwich + 2.600000000 Fries + 4.100000000 SausageBiscuit + 8 LowfatMilk + 12 OrangeJuice <= 75
 * Bounds
 * End
 */
#include <stdio.h>
#if defined(__APPLE__) || defined(__linux__)
#   include <unistd.h>
#   define SLEEP_10_SEC sleep(10)
#else
#   include <windows.h>
#   define SLEEP_10_SEC Sleep(10000)
#endif
#include <iostream>
#include <vector>
#include <functional>
#include "MindoptCpp.h"
using namespace mindopt;
int main(void)
{
#define num_foods 9
#define num_reqs  8
    /* Remote computing related information. */
    const char * filepath = "./tmp/";
    const char * token = "xxxxxxxxxtokenxxxxxxxx";
    const char * server = "mindopt.tianchi.aliyun.com";
    const char * desc = "tianchi example2 MdoRemotLdDiet CPP4";

    /* Input mps file (optimization problem) */
    const char * input_file = "~/mindopt-open-examples/data/example2_mps_file_model.mps";
    /* Variables. */
    MdoStatus    model_status = MDO_UNKNOWN;    
    std::string  model_status_details;    
    MdoResult    result = MDO_OKAY;    
    std::string  result_details;    
    MdoBool      has_soln = MDO_NO;        
    std::string  job_id;
    std::string  status;
    int          i, j;

    /* Data. */                                 
    const char food[num_foods][30] = 
    {
        "Cheeseburger", "HamSandwich", "Hamburger", "FishSandwich", 
        "ChickenSandwich", "Fries", "SausageBiscuit", "LowfatMilk", 
        "OrangeJuice"
    }; 

    /*------------------------------------------------------------------*/
    /* Step 1. Create a model and change the parameters.                */
    /*------------------------------------------------------------------*/
    /* Create an empty model. */
    MdoModel model;

    try 
    {
        /*------------------------------------------------------------------*/
        /* Step 2. Input model.                                             */
        /*------------------------------------------------------------------*/
        /* Read model from mps file */
        model.readProb(input_file);
        /* Input parameters. */
        model.setIntParam("NumThreads", 4);
        model.setRealParam("MaxTime", 3600);   
        /*------------------------------------------------------------------*/
        /* Step 3. Input parameters related to the remote computing server. */
        /*------------------------------------------------------------------*/
        /* Input parameters related to remote computing. */
        model.setStrParam("Remote/Token", token);
        model.setStrParam("Remote/Desc", desc);
        model.setStrParam("Remote/Server", server); 
        model.setStrParam("Remote/File/Path", filepath);
        /*------------------------------------------------------------------*/
        /* Step 4. Upload the serialized model and parameters to server, and*/
        /*         then optimize the model.                                 */
        /*------------------------------------------------------------------*/
        job_id = model.submitTask();
        if (job_id.empty())
        {
            std::cerr << "ERROR: Invalid job ID: " << job_id << std::endl;
            return static_cast<int>(MDO_ERROR);
        }
        else
        {
            std::cout << "Job was submitted to server successfully." << std::endl;
            std::cout << "User may query the optimization result with the following job ID: " << job_id << std::endl;
        }
        /*------------------------------------------------------------------*/
        /* Step 5. Check the solution status periodically, and              */
        /*         download the its upon availability.                      */
        /*------------------------------------------------------------------*/
        do 
        {        
            status = model.retrieveTask(job_id, model_status, result, has_soln);
            /* Sleep for 10 seconds. */
            SLEEP_10_SEC;
        }
        while (status[0] == 'S'); /* Continue the loop if the status is in either Submitted status or Solving status. */
        /*------------------------------------------------------------------*/
        /* Step 6. Retrieve the solution and then populate the result.      */
        /*------------------------------------------------------------------*/  
        std::cout << std::endl << "Populating optimization results." << std::endl;   
        model_status_details = model.explainStatus(model_status);
        result_details = model.explainResult(result);
        std::cout << " - Job status             : " << status << std::endl;
        std::cout << " - Model status           : " << model_status_details << " (" << model_status << ")" << std::endl;
        std::cout << " - Optimization status    : " << result_details << " (" << result << ")" << std::endl;
        std::cout << " - Solution availability  : " << std::string(has_soln ? "available" : "not available") << std::endl;
        if (has_soln)
        {
            std::cout << "Populating solution." << std::endl;    
            model.displayResults();
            switch (model.getStatus())
            {
            case MDO_UNKNOWN:
                std::cout << "Optimizer terminated with an UNKNOWN status." << std::endl;
                break;
            case MDO_OPTIMAL:
                std::cout << "Optimizer terminated with an OPTIMAL status." << std::endl;
                std::cout << "Daily cost          : $" << model.getRealAttr("PrimalObjVal") << std::endl;
                break;
            case MDO_INFEASIBLE:
                std::cout << "Optimizer terminated with an INFEASIBLE status." << std::endl;
                break;
            case MDO_UNBOUNDED:
                std::cout << "Optimizer terminated with an UNBOUNDED status." << std::endl;
                break;
            case MDO_INF_OR_UBD:
                std::cout << "Optimizer terminated with an INFEASIBLE or UNBOUNDED status." << std::endl;
                break;
            }
        }
    }
    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);
}

Python语言范例1: 行输入方式

创建py文件和运行

创建一个.py文件如下(文件夹已创建可删除前几句)。(除示例nano指令外,编辑文件可使用vi、vim、nano、emacs等不同编辑器指令,或touch创建文件,也可采用CloudShell右上角的“笔”的编辑图标来选择对应的文档进行新增和修改。)

mkdir python
cd python
mkdir tmp
nano mindopt_example_2_py1.py

然后复制后文的代码拷入,代码右上角有复制按钮。根据提示来修改token和保存文件,如ctrl+o保存,然后看到对应名字OK后摁enter即可,如ctrl+x退出,如有修改保存按Y,再看到对应名字OK后摁enter即可退出。

也可采用CloudShell右上角的“笔”的编辑图标来选择对应的文档进行修改。

运行程序可输入以下指令:

python mindopt_example_2_py1.py

注:问题提交远端计算Server后,会需要求解时间,请耐心等待。由于计算资源限制,同一Token同时间只能求解一个问题,请勿同时段提交太多次。如果代码运行失败,可能是mindopt环境变量链接失败,可重新走一遍安装步骤(安装指导)。

python 代码

Tips:  如果想体验运行MindOpt求解器代码,请先在天池-决策优化MindOpt-免费使用上申请授权Token,并替换掉示例代码里的Token。

"""
/**
 *  example_2_py1.py
 *  Description 
 *  -----------
 *
 *  Linear optimization (diet problem).
 * 
 *  The goal is to select foods that satisfy daily nutritional requirements while minimizing the total cost. 
 *  The constraints in this problem limit the number of calories, the volume of good consumed, and the amount of 
 *  vitamins, protein, carbohydrates, calcium, and iron in the diet.
 *
 *  Note
 *  ----
 * 
 *  The model below will be inputted in a row-wise order.
 *
 *  Formulation
 *  -----------
 *
 * Minimize
 * Obj:        1.840000000 Cheeseburger + 2.190000000 HamSandwich + 1.840000000 Hamburger + 1.440000000 FishSandwich +
 *             2.290000000 ChickenSandwich + 0.770000000 Fries + 1.290000000 SausageBiscuit + 0.600000000 LowfatMilk + 
 *             0.720000000 OrangeJuice
 * Subject To
 * Cal:        510 Cheeseburger + 370 HamSandwich + 500 Hamburger + 370 FishSandwich +
 *             400 ChickenSandwich + 220 Fries + 345 SausageBiscuit + 110 LowfatMilk + 80 OrangeJuice >= 2000
 * Carbo:      34 Cheeseburger + 35 HamSandwich + 42 Hamburger + 38 FishSandwich + 42 ChickenSandwich + 
 *             26 Fries + 27 SausageBiscuit + 12 LowfatMilk + 20 OrangeJuice <= 375
 * Carbo_low:  34 Cheeseburger + 35 HamSandwich + 42 Hamburger + 38 FishSandwich + 42 ChickenSandwich + 
 *             26 Fries + 27 SausageBiscuit + 12 LowfatMilk + 20 OrangeJuice >= 350
 * Protein:    28 Cheeseburger + 24 HamSandwich + 25 Hamburger + 14 FishSandwich + 31 ChickenSandwich + 
 *             3 Fries + 15 SausageBiscuit + 9 LowfatMilk + OrangeJuice >= 55
 * VitA:       15 Cheeseburger + 15 HamSandwich + 6 Hamburger + 2 FishSandwich + 8 ChickenSandwich + 
 *             4 SausageBiscuit + 10 LowfatMilk + 2 OrangeJuice >= 100
 * VitC:       6 Cheeseburger + 10 HamSandwich + 2 Hamburger + 15 ChickenSandwich + 
 *             15 Fries + 4 LowfatMilk + 120 OrangeJuice >= 100
 * Calc:       30 Cheeseburger + 20 HamSandwich + 25 Hamburger + 15 FishSandwich + 
 *             15 ChickenSandwich + 20 SausageBiscuit + 30 LowfatMilk + 2 OrangeJuice >= 100
 * Iron:       20 Cheeseburger + 20 HamSandwich + 20 Hamburger + 10 FishSandwich + 
 *             8 ChickenSandwich + 2 Fries + 15 SausageBiscuit + 2 OrangeJuice >= 100
 * Volume:     4 Cheeseburger + 7.500000000 HamSandwich + 3.500000000 Hamburger + 5 FishSandwich + 
 *             7.300000000 ChickenSandwich + 2.600000000 Fries + 4.100000000 SausageBiscuit + 8 LowfatMilk + 12 OrangeJuice <= 75
 * Bounds
 * End
 */
"""
from mindoptpy import *


if __name__ == "__main__":

    MDO_INFINITY = MdoModel.get_infinity()
    token = "xxxxxxxxxtokenxxxxxxxx"
    server = "mindopt.tianchi.aliyun.com"
    desc = "tianchi example2 MdoRemotLdDiet PY1"
    filepath = "./tmp/"

    req = \
    {   
        # requirement: ( lower bound,   upper bound)
        "Cal"        : (         2000, MDO_INFINITY), 
        "Carbo"      : (          350,          375),
        "Protein"    : (           55, MDO_INFINITY), 
        "VitA"       : (          100, MDO_INFINITY),
        "VitC"       : (          100, MDO_INFINITY),
        "Calc"       : (          100, MDO_INFINITY), 
        "Iron"       : (          100, MDO_INFINITY), 
        "Volume"     : (-MDO_INFINITY,           75)
    }

    food = \
    {
        # food            : ( lower bound,  upper bound, cost)
        "Cheeseburger"    : (           0, MDO_INFINITY, 1.84),
        "HamSandwich"     : (           0, MDO_INFINITY, 2.19),
        "Hamburger"       : (           0, MDO_INFINITY, 1.84),
        "FishSandwich"    : (           0, MDO_INFINITY, 1.44),
        "ChickenSandwich" : (           0, MDO_INFINITY, 2.29),
        "Fries"           : (           0, MDO_INFINITY, 0.77),
        "SausageBiscuit"  : (           0, MDO_INFINITY, 1.29),
        "LowfatMilk"      : (           0, MDO_INFINITY, 0.60),
        "OrangeJuice"     : (           0, MDO_INFINITY, 0.72)
    }

    req_value = \
    {  
        # (requirement, food              ) : value
        ( "Cal",        "Cheeseburger"    ) : 510,
        ( "Cal",        "HamSandwich"     ) : 370,
        ( "Cal",        "Hamburger"       ) : 500,
        ( "Cal",        "FishSandwich"    ) : 370,
        ( "Cal",        "ChickenSandwich" ) : 400,
        ( "Cal",        "Fries"           ) : 220,
        ( "Cal",        "SausageBiscuit"  ) : 345,
        ( "Cal",        "LowfatMilk"      ) : 110,
        ( "Cal",        "OrangeJuice"     ) : 80,

        ( "Carbo",      "Cheeseburger"    ) : 34,
        ( "Carbo",      "HamSandwich"     ) : 35,
        ( "Carbo",      "Hamburger"       ) : 42,
        ( "Carbo",      "FishSandwich"    ) : 38,
        ( "Carbo",      "ChickenSandwich" ) : 42,
        ( "Carbo",      "Fries"           ) : 26,
        ( "Carbo",      "SausageBiscuit"  ) : 27,
        ( "Carbo",      "LowfatMilk"      ) : 12,
        ( "Carbo",      "OrangeJuice"     ) : 20,

        ( "Protein",    "Cheeseburger"    ) : 28,
        ( "Protein",    "HamSandwich"     ) : 24,
        ( "Protein",    "Hamburger"       ) : 25,
        ( "Protein",    "FishSandwich"    ) : 14,
        ( "Protein",    "ChickenSandwich" ) : 31,
        ( "Protein",    "Fries"           ) : 3,
        ( "Protein",    "SausageBiscuit"  ) : 15,
        ( "Protein",    "LowfatMilk"      ) : 9,
        ( "Protein",    "OrangeJuice"     ) : 1,

        ( "VitA",       "Cheeseburger"    ) : 15,
        ( "VitA",       "HamSandwich"     ) : 15,
        ( "VitA",       "Hamburger"       ) : 6,
        ( "VitA",       "FishSandwich"    ) : 2,
        ( "VitA",       "ChickenSandwich" ) : 8,
        ( "VitA",       "Fries"           ) : 0,
        ( "VitA",       "SausageBiscuit"  ) : 4,
        ( "VitA",       "LowfatMilk"      ) : 10,
        ( "VitA",       "OrangeJuice"     ) : 2,

        ( "VitC",       "Cheeseburger"    ) : 6,
        ( "VitC",       "HamSandwich"     ) : 10,
        ( "VitC",       "Hamburger"       ) : 2,
        ( "VitC",       "FishSandwich"    ) : 0,
        ( "VitC",       "ChickenSandwich" ) : 15,
        ( "VitC",       "Fries"           ) : 15,
        ( "VitC",       "SausageBiscuit"  ) : 0,
        ( "VitC",       "OrangeJuice"     ) : 4,
        ( "VitC",       "LowfatMilk"      ) : 120,

        ( "Calc",       "Cheeseburger"    ) : 30,
        ( "Calc",       "HamSandwich"     ) : 20,
        ( "Calc",       "Hamburger"       ) : 25,
        ( "Calc",       "FishSandwich"    ) : 15,
        ( "Calc",       "ChickenSandwich" ) : 15,
        ( "Calc",       "Fries"           ) : 0,
        ( "Calc",       "SausageBiscuit"  ) : 20,
        ( "Calc",       "LowfatMilk"      ) : 30,
        ( "Calc",       "OrangeJuice"     ) : 2,

        ( "Iron",       "Cheeseburger"    ) : 20,
        ( "Iron",       "HamSandwich"     ) : 20,
        ( "Iron",       "Hamburger"       ) : 20,
        ( "Iron",       "FishSandwich"    ) : 10,
        ( "Iron",       "ChickenSandwich" ) : 8,
        ( "Iron",       "Fries"           ) : 2,
        ( "Iron",       "SausageBiscuit"  ) : 15,
        ( "Iron",       "LowfatMilk"      ) : 0,
        ( "Iron",       "OrangeJuice"     ) : 2,

        ( "Volume",     "Cheeseburger"    ) : 4,
        ( "Volume",     "HamSandwich"     ) : 7.5,
        ( "Volume",     "Hamburger"       ) : 3.5,
        ( "Volume",     "FishSandwich"    ) : 5,
        ( "Volume",     "ChickenSandwich" ) : 7.3,
        ( "Volume",     "Fries"           ) : 2.6,
        ( "Volume",     "SausageBiscuit"  ) : 4.1,
        ( "Volume",     "LowfatMilk"      ) : 8,
        ( "Volume",     "OrangeJuice"     ) : 12
    }

    # Step 1. Create a model and change the parameters.
    model = MdoModel()

    try:
        # Step 2. Input model.
        # Change to minimization problem.
        model.set_int_attr("MinSense", 1)

        # Add variables.
        var = {}
        for food_name, food_data in food.items():
            var[food_name] = model.add_var(food_data[0], food_data[1], food_data[2], None, food_name, False)

        # Add constraints.
        for req_name, req_data in req.items():
            expr = MdoExprLinear()
            for food_name in food.keys():
                expr += req_value[req_name, food_name] * var[food_name]
            model.add_cons(req_data[0], req_data[1], expr, req_name)

        # Step 3. Input parameters related to the remote computing server.
        model.set_str_param("Remote/Token", token)
        model.set_str_param("Remote/Desc", desc)
        model.set_str_param("Remote/Server", server)
        model.set_str_param("Remote/File/Path", filepath)

        # Step 4. Upload the serialized model and parameters to server, and then optimize the model.   
        job_id = model.submit_task()
        if job_id == "":
            print("ERROR: Empty job ID.")
            raise MdoError(-1)
        else:
            print("Job was submitted to server successfully.")
            print("User may query the optimization result with the following job ID: {}".format(job_id))

        # Step 5. Check the solution status periodically, and             
        #         download the its upon availability.       
        status = "Submitted"
        while status == 'Submitted' or status == 'Solving': 
            status, model_status, result, has_soln = model.retrieve_task(job_id)

            # Sleep for 10 seconds.
            time.sleep(10)

        model_status_details = model.explain_status(model_status)
        result_details = model.explain_result(result)

        print(" - Job status             : {}".format(status)) 
        print(" - Model status           : {0} ({1})".format(model_status_details, model_status))
        print(" - Optimization status    : {0} ({1})".format(result_details, result))
        print(" - Solution availability  : {0}".format("available" if has_soln else "not available"))

        if has_soln:
            print("\nPopulating solution.")

            model.display_results()
            status_code, status_msg = model.get_status()
            if status_msg == "OPTIMAL":
                print("Optimizer terminated with an OPTIMAL status (code {0}).".format(status_code))
                print("Daily cost           : ${0}".format(round(model.get_real_attr("PrimalObjVal"), 2)))
                for food_name, food_var in var.items():
                    val = round(food_var.get_real_attr("PrimalSoln"), 2)
                    if val > 0.01:
                        print(f" - {food_name: <17} : {val}")
            else:
                print("Optimizer terminated with a(n) {0} status (code {1}).".format(status_msg, status_code))

    except MdoError as e:
        print("Received Mindopt exception.")
        print(" - Code          : {}".format(e.code))
        print(" - Reason        : {}".format(e.message))
    except Exception as e:
        print("Received exception.")
        print(" - Reason        : {}".format(e))
    finally:
        pass

Python语言范例2: 列输入方式

创建py文件和运行

创建一个.py文件如下(文件夹已创建可删除前几句)。(除示例nano指令外,编辑文件可使用vi、vim、nano、emacs等不同编辑器指令,或touch创建文件,也可采用CloudShell右上角的“笔”的编辑图标来选择对应的文档进行新增和修改。)

mkdir python
cd python
mkdir tmp
nano mindopt_example_2_py2.py

然后复制后文的代码拷入,代码右上角有复制按钮。根据提示来修改和保存文件,如ctrl+o保存,然后看到对应名字OK后摁enter即可,如ctrl+x退出,如有修改保存按Y,再看到对应名字OK后摁enter即可退出。

也可采用CloudShell右上角的“笔”的编辑图标来选择对应的文档进行修改。

运行程序可输入以下指令:

python mindopt_example_2_py2.py

注:问题提交远端计算Server后,会需要求解时间,请耐心等待。由于计算资源限制,同一Token同时间只能求解一个问题,请勿同时段提交太多次。如果代码运行失败,可能是mindopt环境变量链接失败,可重新走一遍安装步骤(安装指导)。

python 代码

Tips:  如果想体验运行MindOpt求解器代码,请先在天池-决策优化MindOpt-免费使用上申请授权Token,并替换掉示例代码里的Token。

"""
/**
 *  example_2_py2.py
 *  Description
 *  -----------
 *
 *  Linear optimization (diet problem).
 * 
 *  The goal is to select foods that satisfy daily nutritional requirements while minimizing the total cost. 
 *  The constraints in this problem limit the number of calories, the volume of good consumed, and the amount of 
 *  vitamins, protein, carbohydrates, calcium, and iron in the diet.
 *
 *  Note
 *  ----
 * 
 *  The model below will be inputted in a row-wise order.
 *
 *  Formulation
 *  -----------
 *
 * Minimize
 * Obj:        1.840000000 Cheeseburger + 2.190000000 HamSandwich + 1.840000000 Hamburger + 1.440000000 FishSandwich +
 *             2.290000000 ChickenSandwich + 0.770000000 Fries + 1.290000000 SausageBiscuit + 0.600000000 LowfatMilk + 
 *             0.720000000 OrangeJuice
 * Subject To
 * Cal:        510 Cheeseburger + 370 HamSandwich + 500 Hamburger + 370 FishSandwich +
 *             400 ChickenSandwich + 220 Fries + 345 SausageBiscuit + 110 LowfatMilk + 80 OrangeJuice >= 2000
 * Carbo:      34 Cheeseburger + 35 HamSandwich + 42 Hamburger + 38 FishSandwich + 42 ChickenSandwich + 
 *             26 Fries + 27 SausageBiscuit + 12 LowfatMilk + 20 OrangeJuice <= 375
 * Carbo_low:  34 Cheeseburger + 35 HamSandwich + 42 Hamburger + 38 FishSandwich + 42 ChickenSandwich + 
 *             26 Fries + 27 SausageBiscuit + 12 LowfatMilk + 20 OrangeJuice >= 350
 * Protein:    28 Cheeseburger + 24 HamSandwich + 25 Hamburger + 14 FishSandwich + 31 ChickenSandwich + 
 *             3 Fries + 15 SausageBiscuit + 9 LowfatMilk + OrangeJuice >= 55
 * VitA:       15 Cheeseburger + 15 HamSandwich + 6 Hamburger + 2 FishSandwich + 8 ChickenSandwich + 
 *             4 SausageBiscuit + 10 LowfatMilk + 2 OrangeJuice >= 100
 * VitC:       6 Cheeseburger + 10 HamSandwich + 2 Hamburger + 15 ChickenSandwich + 
 *             15 Fries + 4 LowfatMilk + 120 OrangeJuice >= 100
 * Calc:       30 Cheeseburger + 20 HamSandwich + 25 Hamburger + 15 FishSandwich + 
 *             15 ChickenSandwich + 20 SausageBiscuit + 30 LowfatMilk + 2 OrangeJuice >= 100
 * Iron:       20 Cheeseburger + 20 HamSandwich + 20 Hamburger + 10 FishSandwich + 
 *             8 ChickenSandwich + 2 Fries + 15 SausageBiscuit + 2 OrangeJuice >= 100
 * Volume:     4 Cheeseburger + 7.500000000 HamSandwich + 3.500000000 Hamburger + 5 FishSandwich + 
 *             7.300000000 ChickenSandwich + 2.600000000 Fries + 4.100000000 SausageBiscuit + 8 LowfatMilk + 12 OrangeJuice <= 75
 * Bounds
 * End
 */
"""
from mindoptpy import *


if __name__ == "__main__":

    MDO_INFINITY = MdoModel.get_infinity()
    token = "xxxxxxxxxtokenxxxxxxxx"
    server = "mindopt.tianchi.aliyun.com"
    desc = "tianchi example2 MdoRemotLdDiet PY2"
    filepath = "./tmp/"

    req = \
    {   
        # requirement: ( lower bound,   upper bound)
        "Cal"        : (         2000, MDO_INFINITY), 
        "Carbo"      : (          350,          375),
        "Protein"    : (           55, MDO_INFINITY), 
        "VitA"       : (          100, MDO_INFINITY),
        "VitC"       : (          100, MDO_INFINITY),
        "Calc"       : (          100, MDO_INFINITY), 
        "Iron"       : (          100, MDO_INFINITY), 
        "Volume"     : (-MDO_INFINITY,           75)
    }

    food = \
    {
        # food            : ( lower bound,  upper bound, cost)
        "Cheeseburger"    : (           0, MDO_INFINITY, 1.84),
        "HamSandwich"     : (           0, MDO_INFINITY, 2.19),
        "Hamburger"       : (           0, MDO_INFINITY, 1.84),
        "FishSandwich"    : (           0, MDO_INFINITY, 1.44),
        "ChickenSandwich" : (           0, MDO_INFINITY, 2.29),
        "Fries"           : (           0, MDO_INFINITY, 0.77),
        "SausageBiscuit"  : (           0, MDO_INFINITY, 1.29),
        "LowfatMilk"      : (           0, MDO_INFINITY, 0.60),
        "OrangeJuice"     : (           0, MDO_INFINITY, 0.72)
    }

    req_value = \
    {  
        # (requirement, food              ) : value
        ( "Cal",        "Cheeseburger"    ) : 510,
        ( "Cal",        "HamSandwich"     ) : 370,
        ( "Cal",        "Hamburger"       ) : 500,
        ( "Cal",        "FishSandwich"    ) : 370,
        ( "Cal",        "ChickenSandwich" ) : 400,
        ( "Cal",        "Fries"           ) : 220,
        ( "Cal",        "SausageBiscuit"  ) : 345,
        ( "Cal",        "LowfatMilk"      ) : 110,
        ( "Cal",        "OrangeJuice"     ) : 80,

        ( "Carbo",      "Cheeseburger"    ) : 34,
        ( "Carbo",      "HamSandwich"     ) : 35,
        ( "Carbo",      "Hamburger"       ) : 42,
        ( "Carbo",      "FishSandwich"    ) : 38,
        ( "Carbo",      "ChickenSandwich" ) : 42,
        ( "Carbo",      "Fries"           ) : 26,
        ( "Carbo",      "SausageBiscuit"  ) : 27,
        ( "Carbo",      "LowfatMilk"      ) : 12,
        ( "Carbo",      "OrangeJuice"     ) : 20,

        ( "Protein",    "Cheeseburger"    ) : 28,
        ( "Protein",    "HamSandwich"     ) : 24,
        ( "Protein",    "Hamburger"       ) : 25,
        ( "Protein",    "FishSandwich"    ) : 14,
        ( "Protein",    "ChickenSandwich" ) : 31,
        ( "Protein",    "Fries"           ) : 3,
        ( "Protein",    "SausageBiscuit"  ) : 15,
        ( "Protein",    "LowfatMilk"      ) : 9,
        ( "Protein",    "OrangeJuice"     ) : 1,

        ( "VitA",       "Cheeseburger"    ) : 15,
        ( "VitA",       "HamSandwich"     ) : 15,
        ( "VitA",       "Hamburger"       ) : 6,
        ( "VitA",       "FishSandwich"    ) : 2,
        ( "VitA",       "ChickenSandwich" ) : 8,
        ( "VitA",       "Fries"           ) : 0,
        ( "VitA",       "SausageBiscuit"  ) : 4,
        ( "VitA",       "LowfatMilk"      ) : 10,
        ( "VitA",       "OrangeJuice"     ) : 2,

        ( "VitC",       "Cheeseburger"    ) : 6,
        ( "VitC",       "HamSandwich"     ) : 10,
        ( "VitC",       "Hamburger"       ) : 2,
        ( "VitC",       "FishSandwich"    ) : 0,
        ( "VitC",       "ChickenSandwich" ) : 15,
        ( "VitC",       "Fries"           ) : 15,
        ( "VitC",       "SausageBiscuit"  ) : 0,
        ( "VitC",       "OrangeJuice"     ) : 4,
        ( "VitC",       "LowfatMilk"      ) : 120,

        ( "Calc",       "Cheeseburger"    ) : 30,
        ( "Calc",       "HamSandwich"     ) : 20,
        ( "Calc",       "Hamburger"       ) : 25,
        ( "Calc",       "FishSandwich"    ) : 15,
        ( "Calc",       "ChickenSandwich" ) : 15,
        ( "Calc",       "Fries"           ) : 0,
        ( "Calc",       "SausageBiscuit"  ) : 20,
        ( "Calc",       "LowfatMilk"      ) : 30,
        ( "Calc",       "OrangeJuice"     ) : 2,

        ( "Iron",       "Cheeseburger"    ) : 20,
        ( "Iron",       "HamSandwich"     ) : 20,
        ( "Iron",       "Hamburger"       ) : 20,
        ( "Iron",       "FishSandwich"    ) : 10,
        ( "Iron",       "ChickenSandwich" ) : 8,
        ( "Iron",       "Fries"           ) : 2,
        ( "Iron",       "SausageBiscuit"  ) : 15,
        ( "Iron",       "LowfatMilk"      ) : 0,
        ( "Iron",       "OrangeJuice"     ) : 2,

        ( "Volume",     "Cheeseburger"    ) : 4,
        ( "Volume",     "HamSandwich"     ) : 7.5,
        ( "Volume",     "Hamburger"       ) : 3.5,
        ( "Volume",     "FishSandwich"    ) : 5,
        ( "Volume",     "ChickenSandwich" ) : 7.3,
        ( "Volume",     "Fries"           ) : 2.6,
        ( "Volume",     "SausageBiscuit"  ) : 4.1,
        ( "Volume",     "LowfatMilk"      ) : 8,
        ( "Volume",     "OrangeJuice"     ) : 12
    }

    # Step 1. Create a model and change the parameters.
    model = MdoModel()

    try:
        # Step 2. Input model.
        # Change to minimization problem.
        model.set_int_attr("MinSense", 1)

        # Add constraints.
        cons = {}
        for req_name, req_data in req.items():
            cons[req_name] = model.add_cons(req_data[0], req_data[1], None, req_name)

        # Add variables.
        var = {}
        for food_name, food_data in food.items():
            col = MdoCol()
            for req_name, req_data in req_value.items():
                if food_name == req_name[1]:
                    col.add_term(cons[req_name[0]], req_data)

            var[food_name] = model.add_var(food_data[0], food_data[1], food_data[2], col, food_name, False)

        # Step 3. Input parameters related to the remote computing server.
        model.set_str_param("Remote/Token", token)
        model.set_str_param("Remote/Desc", desc)
        model.set_str_param("Remote/Server", server)
        model.set_str_param("Remote/File/Path", filepath)

        # Step 4. Upload the serialized model and parameters to server, and then optimize the model.   
        job_id = model.submit_task()
        if job_id == "":
            print("ERROR: Empty job ID.")
            raise MdoError(-1)
        else:
            print("Job was submitted to server successfully.")
            print("User may query the optimization result with the following job ID: {}".format(job_id))

        # Step 5. Check the solution status periodically, and             
        #         download the its upon availability.       
        status = "Submitted"
        while status == 'Submitted' or status == 'Solving': 
            status, model_status, result, has_soln = model.retrieve_task(job_id)

            # Sleep for 10 seconds.
            time.sleep(10)

        model_status_details = model.explain_status(model_status)
        result_details = model.explain_result(result)

        print(" - Job status             : {}".format(status)) 
        print(" - Model status           : {0} ({1})".format(model_status_details, model_status))
        print(" - Optimization status    : {0} ({1})".format(result_details, result))
        print(" - Solution availability  : {0}".format("available" if has_soln else "not available"))

        if has_soln:
            print("\nPopulating solution.")

            model.display_results()
            status_code, status_msg = model.get_status()
            if status_msg == "OPTIMAL":
                print("Optimizer terminated with an OPTIMAL status (code {0}).".format(status_code))
                print("Daily cost           : ${0}".format(round(model.get_real_attr("PrimalObjVal"), 2)))
                for food_name, food_var in var.items():
                    val = round(food_var.get_real_attr("PrimalSoln"), 2)
                    if val > 0.01:
                        print(f" - {food_name: <17} : {val}")
            else:
                print("Optimizer terminated with a(n) {0} status (code {1}).".format(status_msg, status_code))

    except MdoError as e:
        print("Received Mindopt exception.")
        print(" - Code          : {}".format(e.code))
        print(" - Reason        : {}".format(e.message))
    except Exception as e:
        print("Received exception.")
        print(" - Reason        : {}".format(e))
    finally:
        pass

Python语言范例3: 建模表达输入方式

创建py文件和运行

创建一个.py文件如下(文件夹已创建可删除前几句)。(除示例nano指令外,编辑文件可使用vi、vim、nano、emacs等不同编辑器指令,或touch创建文件,也可采用CloudShell右上角的“笔”的编辑图标来选择对应的文档进行新增和修改。)

mkdir python
cd python
mkdir tmp
nano mindopt_example_2_py3.py

然后复制后文的代码拷入,代码右上角有复制按钮。根据提示来修改和保存文件,如ctrl+o保存,然后看到对应名字OK后摁enter即可,如ctrl+x退出,如有修改保存按Y,再看到对应名字OK后摁enter即可退出。

也可采用CloudShell右上角的“笔”的编辑图标来选择对应的文档进行修改。

运行程序可输入以下指令:

python mindopt_example_2_py3.py

注:问题提交远端计算Server后,会需要求解时间,请耐心等待。由于计算资源限制,同一Token同时间只能求解一个问题,请勿同时段提交太多次。如果代码运行失败,可能是mindopt环境变量链接失败,可重新走一遍安装步骤(安装指导)。

python 代码

Tips:  如果想体验运行MindOpt求解器代码,请先在天池-决策优化MindOpt-免费使用上申请授权Token,并替换掉示例代码里的Token。

"""
/**
 *  example_2_py3.py
 *  Description
 *  -----------
 *
 *  Linear optimization (diet problem).
 * 
 *  The goal is to select foods that satisfy daily nutritional requirements while minimizing the total cost. 
 *  The constraints in this problem limit the number of calories, the volume of good consumed, and the amount of 
 *  vitamins, protein, carbohydrates, calcium, and iron in the diet.
 *
 *  Note
 *  ----
 * 
 *  The model below will be inputted in a row-wise order.
 *
 *  Formulation
 *  -----------
 *
 * Minimize
 * Obj:        1.840000000 Cheeseburger + 2.190000000 HamSandwich + 1.840000000 Hamburger + 1.440000000 FishSandwich +
 *             2.290000000 ChickenSandwich + 0.770000000 Fries + 1.290000000 SausageBiscuit + 0.600000000 LowfatMilk + 
 *             0.720000000 OrangeJuice
 * Subject To
 * Cal:        510 Cheeseburger + 370 HamSandwich + 500 Hamburger + 370 FishSandwich +
 *             400 ChickenSandwich + 220 Fries + 345 SausageBiscuit + 110 LowfatMilk + 80 OrangeJuice >= 2000
 * Carbo:      34 Cheeseburger + 35 HamSandwich + 42 Hamburger + 38 FishSandwich + 42 ChickenSandwich + 
 *             26 Fries + 27 SausageBiscuit + 12 LowfatMilk + 20 OrangeJuice <= 375
 * Carbo_low:  34 Cheeseburger + 35 HamSandwich + 42 Hamburger + 38 FishSandwich + 42 ChickenSandwich + 
 *             26 Fries + 27 SausageBiscuit + 12 LowfatMilk + 20 OrangeJuice >= 350
 * Protein:    28 Cheeseburger + 24 HamSandwich + 25 Hamburger + 14 FishSandwich + 31 ChickenSandwich + 
 *             3 Fries + 15 SausageBiscuit + 9 LowfatMilk + OrangeJuice >= 55
 * VitA:       15 Cheeseburger + 15 HamSandwich + 6 Hamburger + 2 FishSandwich + 8 ChickenSandwich + 
 *             4 SausageBiscuit + 10 LowfatMilk + 2 OrangeJuice >= 100
 * VitC:       6 Cheeseburger + 10 HamSandwich + 2 Hamburger + 15 ChickenSandwich + 
 *             15 Fries + 4 LowfatMilk + 120 OrangeJuice >= 100
 * Calc:       30 Cheeseburger + 20 HamSandwich + 25 Hamburger + 15 FishSandwich + 
 *             15 ChickenSandwich + 20 SausageBiscuit + 30 LowfatMilk + 2 OrangeJuice >= 100
 * Iron:       20 Cheeseburger + 20 HamSandwich + 20 Hamburger + 10 FishSandwich + 
 *             8 ChickenSandwich + 2 Fries + 15 SausageBiscuit + 2 OrangeJuice >= 100
 * Volume:     4 Cheeseburger + 7.500000000 HamSandwich + 3.500000000 Hamburger + 5 FishSandwich + 
 *             7.300000000 ChickenSandwich + 2.600000000 Fries + 4.100000000 SausageBiscuit + 8 LowfatMilk + 12 OrangeJuice <= 75
 * Bounds
 * End
 */
"""
from mindoptpy import *


if __name__ == "__main__":

    MDO_INFINITY = MdoModel.get_infinity()
    token = "xxxxxxxxxtokenxxxxxxxx"
    server = "mindopt.tianchi.aliyun.com"
    desc = "tianchi example2 MdoRemotLdDiet PY3"
    filepath = "./tmp/"

    # Step 1. Create a model and change the parameters.
    model = MdoModel()

    try:
        # Step 2. Input model.
        # Change to minimization problem.
        model.set_int_attr("MinSense", 1)

        # Add variables.
        Cheeseburger    = model.add_var(0, MDO_INFINITY, 1.84, None, "Cheeseburger",    False);
        HamSandwich     = model.add_var(0, MDO_INFINITY, 2.19, None, "HamSandwich",     False);
        Hamburger       = model.add_var(0, MDO_INFINITY, 1.84, None, "Hamburger",       False);
        FishSandwich    = model.add_var(0, MDO_INFINITY, 1.44, None, "FishSandwich",    False);
        ChickenSandwich = model.add_var(0, MDO_INFINITY, 2.29, None, "ChickenSandwich", False);
        Fries           = model.add_var(0, MDO_INFINITY, 0.77, None, "Fries",           False);
        SausageBiscuit  = model.add_var(0, MDO_INFINITY, 1.29, None, "SausageBiscuit",  False);
        LowfatMilk      = model.add_var(0, MDO_INFINITY, 0.60, None, "LowfatMilk",      False);
        OrangeJuice     = model.add_var(0, MDO_INFINITY, 0.72, None, "OrangeJuice",     False);

        # Add constraints.
        model.add_cons(200, MDO_INFINITY, 
            510 * Cheeseburger + 370 * HamSandwich + 500 * Hamburger + 370 * FishSandwich + 
            400 * ChickenSandwich + 220 * Fries + 345 * SausageBiscuit + 110 * LowfatMilk + 
            80 * OrangeJuice, 
            "Cal");
        model.add_cons(350, 375, 
            34 * Cheeseburger + 35 * HamSandwich + 42 * Hamburger + 38 * FishSandwich + 
            42 * ChickenSandwich + 26 * Fries + 27 * SausageBiscuit + 12 * LowfatMilk +
            20 * OrangeJuice, 
            "Carbo"); 
        model.add_cons(55, MDO_INFINITY, 
            28 * Cheeseburger + 24 * HamSandwich + 25 * Hamburger + 14 * FishSandwich + 
            31 * ChickenSandwich + 3 * Fries + 15 * SausageBiscuit + 9 * LowfatMilk + 
            OrangeJuice, 
            "Protein");
        model.add_cons(100, MDO_INFINITY, 
            15 * Cheeseburger + 15 * HamSandwich + 6 * Hamburger + 2 * FishSandwich + 
            8 * ChickenSandwich + 4 * SausageBiscuit + 10 * LowfatMilk + 2 * OrangeJuice, 
            "VitA");
        model.add_cons(100, MDO_INFINITY, 
            6 * Cheeseburger + 10 * HamSandwich + 2 * Hamburger + 15 * ChickenSandwich + 
            15 * Fries + 4 * LowfatMilk + 120 * OrangeJuice, "VitC");
        model.add_cons(100, MDO_INFINITY,
            30 * Cheeseburger + 20 * HamSandwich + 25 * Hamburger + 15 * FishSandwich + 
            15 * ChickenSandwich + 20 * SausageBiscuit + 30 * LowfatMilk + 2 * OrangeJuice,
            "Calc");
        model.add_cons(100, MDO_INFINITY, 
            20 * Cheeseburger + 20 * HamSandwich + 20 * Hamburger + 10 * FishSandwich + 
            8 * ChickenSandwich + 2 * Fries + 15 * SausageBiscuit + 2 * OrangeJuice, 
            "Iron");
        model.add_cons(-MDO_INFINITY, 75,
             4 * Cheeseburger + 7.5 * HamSandwich + 3.5 * Hamburger + 5 * FishSandwich + 
            7.3 * ChickenSandwich + 2.6 * Fries + 4.1 * SausageBiscuit + 8 *  LowfatMilk + 
            12 * OrangeJuice , 
            "Volume");

        # Step 3. Input parameters related to the remote computing server.
        model.set_str_param("Remote/Token", token)
        model.set_str_param("Remote/Desc", desc)
        model.set_str_param("Remote/Server", server)
        model.set_str_param("Remote/File/Path", filepath)

        # Step 4. Upload the serialized model and parameters to server, and then optimize the model.   
        job_id = model.submit_task()
        if job_id == "":
            print("ERROR: Empty job ID.")
            raise MdoError(-1)
        else:
            print("Job was submitted to server successfully.")
            print("User may query the optimization result with the following job ID: {}".format(job_id))

        # Step 5. Check the solution status periodically, and             
        #         download the its upon availability.       
        status = "Submitted"
        while status == 'Submitted' or status == 'Solving': 
            status, model_status, result, has_soln = model.retrieve_task(job_id)

            # Sleep for 10 seconds.
            time.sleep(10)

        model_status_details = model.explain_status(model_status)
        result_details = model.explain_result(result)

        print(" - Job status             : {}".format(status)) 
        print(" - Model status           : {0} ({1})".format(model_status_details, model_status))
        print(" - Optimization status    : {0} ({1})".format(result_details, result))
        print(" - Solution availability  : {0}".format("available" if has_soln else "not available"))

        if has_soln:
            print("\nPopulating solution.")

            model.display_results()
            model.write_soln("./diet_soln.sol")
            status_code, status_msg = model.get_status()
            if status_msg == "OPTIMAL":
                print("Optimizer terminated with an OPTIMAL status (code {0}).".format(status_code))
                print("Daily cost          : ${0}".format(round(model.get_real_attr("PrimalObjVal"), 2)))
                print(" - Cheeseburger     : {0}".format(round(Cheeseburger.get_real_attr("PrimalSoln"), 2)))
                print(" - Hamburger        : {0}".format(round(Hamburger.get_real_attr("PrimalSoln"), 2)))
                print(" - FishSandwich     : {0}".format(round(FishSandwich.get_real_attr("PrimalSoln"), 2)))
                print(" - ChickenSandwich  : {0}".format(round(ChickenSandwich.get_real_attr("PrimalSoln"), 2)))
                print(" - Fries            : {0}".format(round(Fries.get_real_attr("PrimalSoln"), 2)))
                print(" - SausageBiscuit   : {0}".format(round(SausageBiscuit.get_real_attr("PrimalSoln"), 2)))
                print(" - LowfatMilk       : {0}".format(round(LowfatMilk.get_real_attr("PrimalSoln"), 2)))
                print(" - OrangeJuice      : {0}".format(round(OrangeJuice.get_real_attr("PrimalSoln"), 2)))
            else:
                print("Optimizer terminated with a(n) {0} status (code {1}).".format(status_msg, status_code))

    except MdoError as e:
        print("Received Mindopt exception.")
        print(" - Code          : {}".format(e.code))
        print(" - Reason        : {}".format(e.message))
    except Exception as e:
        print("Received exception.")
        print(" - Reason        : {}".format(e))
    finally:
        pass

Python语言范例4: .mps或.lp文件输入方式

创建py文件和运行

创建一个.py文件如下(文件夹已创建可删除前几句)。(除示例nano指令外,编辑文件可使用vi、vim、nano、emacs等不同编辑器指令,或touch创建文件,也可采用CloudShell右上角的“笔”的编辑图标来选择对应的文档进行新增和修改。)

mkdir python
cd python
mkdir tmp
nano mindopt_example_2_py4.py

然后复制后文的代码拷入,代码右上角有复制按钮。根据提示来修改和保存文件,如ctrl+o保存,然后看到对应名字OK后摁enter即可,如ctrl+x退出,如有修改保存按Y,再看到对应名字OK后摁enter即可退出。

也可采用CloudShell右上角的“笔”的编辑图标来选择对应的文档进行修改。

运行程序可输入以下指令:

python mindopt_example_2_py4.py

注:问题提交远端计算Server后,会需要求解时间,请耐心等待。由于计算资源限制,同一Token同时间只能求解一个问题,请勿同时段提交太多次。如果代码运行失败,可能是mindopt环境变量链接失败,可重新走一遍安装步骤(安装指导)。

python 代码

Tips:  如果想体验运行MindOpt求解器代码,请先在天池-决策优化MindOpt-免费使用上申请授权Token,并替换掉示例代码里的Token。

"""
/**
 *  example_2_py4.py
 *  Description 
 *  -----------
 *
 *  Linear optimization (diet problem).
 * 
 *  The goal is to select foods that satisfy daily nutritional requirements while minimizing the total cost. 
 *  The constraints in this problem limit the number of calories, the volume of good consumed, and the amount of 
 *  vitamins, protein, carbohydrates, calcium, and iron in the diet.
 *
 *  Note
 *  ----
 * 
 *  The model below will be inputted in a row-wise order.
 *
 *  Formulation
 *  -----------
 *
 * Minimize
 * Obj:        1.840000000 Cheeseburger + 2.190000000 HamSandwich + 1.840000000 Hamburger + 1.440000000 FishSandwich +
 *             2.290000000 ChickenSandwich + 0.770000000 Fries + 1.290000000 SausageBiscuit + 0.600000000 LowfatMilk + 
 *             0.720000000 OrangeJuice
 * Subject To
 * Cal:        510 Cheeseburger + 370 HamSandwich + 500 Hamburger + 370 FishSandwich +
 *             400 ChickenSandwich + 220 Fries + 345 SausageBiscuit + 110 LowfatMilk + 80 OrangeJuice >= 2000
 * Carbo:      34 Cheeseburger + 35 HamSandwich + 42 Hamburger + 38 FishSandwich + 42 ChickenSandwich + 
 *             26 Fries + 27 SausageBiscuit + 12 LowfatMilk + 20 OrangeJuice <= 375
 * Carbo_low:  34 Cheeseburger + 35 HamSandwich + 42 Hamburger + 38 FishSandwich + 42 ChickenSandwich + 
 *             26 Fries + 27 SausageBiscuit + 12 LowfatMilk + 20 OrangeJuice >= 350
 * Protein:    28 Cheeseburger + 24 HamSandwich + 25 Hamburger + 14 FishSandwich + 31 ChickenSandwich + 
 *             3 Fries + 15 SausageBiscuit + 9 LowfatMilk + OrangeJuice >= 55
 * VitA:       15 Cheeseburger + 15 HamSandwich + 6 Hamburger + 2 FishSandwich + 8 ChickenSandwich + 
 *             4 SausageBiscuit + 10 LowfatMilk + 2 OrangeJuice >= 100
 * VitC:       6 Cheeseburger + 10 HamSandwich + 2 Hamburger + 15 ChickenSandwich + 
 *             15 Fries + 4 LowfatMilk + 120 OrangeJuice >= 100
 * Calc:       30 Cheeseburger + 20 HamSandwich + 25 Hamburger + 15 FishSandwich + 
 *             15 ChickenSandwich + 20 SausageBiscuit + 30 LowfatMilk + 2 OrangeJuice >= 100
 * Iron:       20 Cheeseburger + 20 HamSandwich + 20 Hamburger + 10 FishSandwich + 
 *             8 ChickenSandwich + 2 Fries + 15 SausageBiscuit + 2 OrangeJuice >= 100
 * Volume:     4 Cheeseburger + 7.500000000 HamSandwich + 3.500000000 Hamburger + 5 FishSandwich + 
 *             7.300000000 ChickenSandwich + 2.600000000 Fries + 4.100000000 SausageBiscuit + 8 LowfatMilk + 12 OrangeJuice <= 75
 * Bounds
 * End
 */
"""
from mindoptpy import *


if __name__ == "__main__":

    MDO_INFINITY = MdoModel.get_infinity()
    token = "xxxxxxxxxtokenxxxxxxxx"
    server = "mindopt.tianchi.aliyun.com"
    desc = "tianchi example2 MdoRemotLdDiet PY4"
    filepath = "./tmp/"

    input_file = "~/mindopt-open-examples/data/example2_mps_file_model.mps"

    # Step 1. Create a model and change the parameters.
    model = MdoModel()

    try:
        # Step 2. Input model.
        model.read_prob(input_file)
        model.set_int_param("NumThreads", 4)
        model.set_real_param("MaxTime", 3600.0)

        # Step 3. Input parameters related to the remote computing server.
        model.set_str_param("Remote/Token", token)
        model.set_str_param("Remote/Desc", desc)
        model.set_str_param("Remote/Server", server)
        model.set_str_param("Remote/File/Path", filepath)

        # Step 4. Upload the serialized model and parameters to server, and then optimize the model.   
        job_id = model.submit_task()
        if job_id == "":
            print("ERROR: Empty job ID.")
            raise MdoError(-1)
        else:
            print("Job was submitted to server successfully.")
            print("User may query the optimization result with the following job ID: {}".format(job_id))

        # Step 5. Check the solution status periodically, and             
        #         download the its upon availability.       
        status = "Submitted"
        while status == 'Submitted' or status == 'Solving': 
            status, model_status, result, has_soln = model.retrieve_task(job_id)

            # Sleep for 10 seconds.
            time.sleep(10)

        model_status_details = model.explain_status(model_status)
        result_details = model.explain_result(result)

        print(" - Job status             : {}".format(status)) 
        print(" - Model status           : {0} ({1})".format(model_status_details, model_status))
        print(" - Optimization status    : {0} ({1})".format(result_details, result))
        print(" - Solution availability  : {0}".format("available" if has_soln else "not available"))

        if has_soln:
            print("\nPopulating solution.")

            model.display_results()
            status_code, status_msg = model.get_status()
            if status_msg == "OPTIMAL":
                print("Optimizer terminated with an OPTIMAL status (code {0}).".format(status_code))
                input_file_names= input_file.rsplit("/")
                input_file_name=input_file_names[-1]
                input_file_rsplit = input_file_name.rsplit(".")
                output_file = input_file_rsplit[0] + '_' + input_file_rsplit[1] + '.sol'
                print("Save the solution file to '",output_file,"'!")
                model.write_soln(output_file)
            else:
                print("Optimizer terminated with a(n) {0} status (code {1}).".format(status_msg, status_code))

    except MdoError as e:
        print("Received Mindopt exception.")
        print(" - Code          : {}".format(e.code))
        print(" - Reason        : {}".format(e.message))
    except Exception as e:
        print("Received exception.")
        print(" - Reason        : {}".format(e))
    finally:
        pass

Python语言范例5: 指定相关参数以.mps或.lp文件输入方式

创建py文件和运行

创建一个.py文件如下(文件夹已创建可删除前几句)。(除示例nano指令外,编辑文件可使用vi、vim、nano、emacs等不同编辑器指令,或touch创建文件,也可采用CloudShell右上角的“笔”的编辑图标来选择对应的文档进行新增和修改。)

mkdir python
cd python
mkdir tmp
nano mindopt_example_2_py5.py

然后复制后文的代码拷入,代码右上角有复制按钮。根据提示来修改和保存文件,如ctrl+o保存,然后看到对应名字OK后摁enter即可,如ctrl+x退出,如有修改保存按Y,再看到对应名字OK后摁enter即可退出。

也可采用CloudShell右上角的“笔”的编辑图标来选择对应的文档进行修改。

运行程序可输入以下指令, --token="xxxYourTokenxxx" 请更换成在天池-决策优化MindOpt-免费使用上申请的专属授权Token。

python mindopt_example_2_py5.py  --input_file="~/mindopt-open-examples/data/example2_mps_file_model.mps"  --token="xxxYourTokenxxx" 

注:问题提交远端计算Server后,会需要求解时间,请耐心等待。由于计算资源限制,同一Token同时间只能求解一个问题,请勿同时段提交太多次。如果代码运行失败,可能是mindopt环境变量链接失败,可重新走一遍安装步骤(安装指导)。

python 代码

"""
/**
 *  example_2_py5.py
 *  Description 
 *  -----------
 *
 *  Linear optimization (diet problem).
 * 
 *  The goal is to select foods that satisfy daily nutritional requirements while minimizing the total cost. 
 *  The constraints in this problem limit the number of calories, the volume of good consumed, and the amount of 
 *  vitamins, protein, carbohydrates, calcium, and iron in the diet.
 *
 *  Note
 *  ----
 * 
 *  The model below will be inputted in a row-wise order.
 *
 *  Formulation
 *  -----------
 *
 * Minimize
 * Obj:        1.840000000 Cheeseburger + 2.190000000 HamSandwich + 1.840000000 Hamburger + 1.440000000 FishSandwich +
 *             2.290000000 ChickenSandwich + 0.770000000 Fries + 1.290000000 SausageBiscuit + 0.600000000 LowfatMilk + 
 *             0.720000000 OrangeJuice
 * Subject To
 * Cal:        510 Cheeseburger + 370 HamSandwich + 500 Hamburger + 370 FishSandwich +
 *             400 ChickenSandwich + 220 Fries + 345 SausageBiscuit + 110 LowfatMilk + 80 OrangeJuice >= 2000
 * Carbo:      34 Cheeseburger + 35 HamSandwich + 42 Hamburger + 38 FishSandwich + 42 ChickenSandwich + 
 *             26 Fries + 27 SausageBiscuit + 12 LowfatMilk + 20 OrangeJuice <= 375
 * Carbo_low:  34 Cheeseburger + 35 HamSandwich + 42 Hamburger + 38 FishSandwich + 42 ChickenSandwich + 
 *             26 Fries + 27 SausageBiscuit + 12 LowfatMilk + 20 OrangeJuice >= 350
 * Protein:    28 Cheeseburger + 24 HamSandwich + 25 Hamburger + 14 FishSandwich + 31 ChickenSandwich + 
 *             3 Fries + 15 SausageBiscuit + 9 LowfatMilk + OrangeJuice >= 55
 * VitA:       15 Cheeseburger + 15 HamSandwich + 6 Hamburger + 2 FishSandwich + 8 ChickenSandwich + 
 *             4 SausageBiscuit + 10 LowfatMilk + 2 OrangeJuice >= 100
 * VitC:       6 Cheeseburger + 10 HamSandwich + 2 Hamburger + 15 ChickenSandwich + 
 *             15 Fries + 4 LowfatMilk + 120 OrangeJuice >= 100
 * Calc:       30 Cheeseburger + 20 HamSandwich + 25 Hamburger + 15 FishSandwich + 
 *             15 ChickenSandwich + 20 SausageBiscuit + 30 LowfatMilk + 2 OrangeJuice >= 100
 * Iron:       20 Cheeseburger + 20 HamSandwich + 20 Hamburger + 10 FishSandwich + 
 *             8 ChickenSandwich + 2 Fries + 15 SausageBiscuit + 2 OrangeJuice >= 100
 * Volume:     4 Cheeseburger + 7.500000000 HamSandwich + 3.500000000 Hamburger + 5 FishSandwich + 
 *             7.300000000 ChickenSandwich + 2.600000000 Fries + 4.100000000 SausageBiscuit + 8 LowfatMilk + 12 OrangeJuice <= 75
 * Bounds
 * End
 */
"""
from mindoptpy import *
import argparse

def parameter_parsing():
    parser = argparse.ArgumentParser(description='MindOpt IO')

    parser.add_argument('--token', default="xxxxxxxxxtokenxxxxxxxx", type=str, help='Token ID')
    parser.add_argument('--server', default="mindopt.tianchi.aliyun.com", type=str, help='Server address')
    parser.add_argument('--desc', default="tianchi example2 MdoRemotLdDiet PY5", type=str, help='Problem description')
    parser.add_argument('--filepath', default="./tmp/", type=str, help='File path of mdo cache file')
    parser.add_argument('--input_file', default="~/mindopt-open-examples/data/example2_mps_file_model.mps", type=str, help='File path of your input mps or lp file')
    args = parser.parse_args()
    return args


if __name__ == "__main__":

    MDO_INFINITY = MdoModel.get_infinity()

    args = parameter_parsing()
    token = args.token
    server = args.server
    desc = args.desc
    filepath = args.filepath
    input_file = args.input_file

    # Step 1. Create a model and change the parameters.
    model = MdoModel()

    try:
        # Step 2. Input model.
        model.read_prob(input_file)
        model.set_int_param("NumThreads", 4)
        model.set_real_param("MaxTime", 3600.0)

        # Step 3. Input parameters related to the remote computing server.
        model.set_str_param("Remote/Token", token)
        model.set_str_param("Remote/Desc", desc)
        model.set_str_param("Remote/Server", server)
        model.set_str_param("Remote/File/Path", filepath)

        # Step 4. Upload the serialized model and parameters to server, and then optimize the model.   
        job_id = model.submit_task()
        if job_id == "":
            print("ERROR: Empty job ID.")
            raise MdoError(-1)
        else:
            print("Job was submitted to server successfully.")
            print("User may query the optimization result with the following job ID: {}".format(job_id))

        # Step 5. Check the solution status periodically, and             
        #         download the its upon availability.       
        status = "Submitted"
        while status == 'Submitted' or status == 'Solving': 
            status, model_status, result, has_soln = model.retrieve_task(job_id)

            # Sleep for 10 seconds.
            time.sleep(10)

        model_status_details = model.explain_status(model_status)
        result_details = model.explain_result(result)

        print(" - Job status             : {}".format(status)) 
        print(" - Model status           : {0} ({1})".format(model_status_details, model_status))
        print(" - Optimization status    : {0} ({1})".format(result_details, result))
        print(" - Solution availability  : {0}".format("available" if has_soln else "not available"))

        if has_soln:
            print("\nPopulating solution.")

            model.display_results()
            status_code, status_msg = model.get_status()
            if status_msg == "OPTIMAL":
                print("Optimizer terminated with an OPTIMAL status (code {0}).".format(status_code))
                input_file_names= input_file.rsplit("/")
                input_file_name=input_file_names[-1]
                input_file_rsplit = input_file_name.rsplit(".")
                output_file = input_file_rsplit[0] + '_' + input_file_rsplit[1] + '.sol'
                print("Save the solution file to '",output_file,"'!")
                model.write_soln(output_file)
            else:
                print("Optimizer terminated with a(n) {0} status (code {1}).".format(status_msg, status_code))

    except MdoError as e:
        print("Received Mindopt exception.")
        print(" - Code          : {}".format(e.code))
        print(" - Reason        : {}".format(e.message))
    except Exception as e:
        print("Received exception.")
        print(" - Reason        : {}".format(e))
    finally:
        pass

求解结果

以下为C语言范例1的运行结果.此范例中,我们采用了单纯型法(simplex method)内点法(interior point method)两种方法作并发求解问题。

求解结果的每日饮食餐费为:$14.86元,包含了4.39份起司汉堡,6.15份薯条,以及3.42份低脂牛乳。

MindOpt Version 0.12.0 (Built: 20201229)
Copyright (c) 2020 Alibaba Cloud.

Returned job ID: 4a56f6f5fca1de64105d1f85e591ac2f.
Job was submitted to server successfully.
User may query the optimization result with the following job ID: 4a56f6f5fca1de64105d1f85e591ac2f
Reader started. File  : ./tmp/m4a56f6f5fca1de64105d1f85e591ac2f.mdo
Reader terminated. Time : 0.001s
Reader started. File  : ./tmp/p4a56f6f5fca1de64105d1f85e591ac2f.mdo
Reader terminated. Time : 0.000s
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100     7  100     7    0     0     13      0 --:--:-- --:--:-- --:--:--    13
100   168  100   168    0     0    646      0 --:--:-- --:--:-- --:--:--   646
100   538  100   538    0     0   2061      0 --:--:-- --:--:-- --:--:--  2061
Reader started. File  : ./tmp/s4a56f6f5fca1de64105d1f85e591ac2f.mdo
Reader terminated. Time : 0.000s

Populating optimization results.
 - Job status             : Finished
 - Model status           : OPTIMAL (1)
 - Optimization status    : Nothing wrong. (0)
 - Solution availability  : available

Populating solution.
Optimizer summary.
 - Optimizer used     : Simplex method
 - Optimizer status   : OPTIMAL
 - Total time         : 0.013s

Solution summary.       Primal solution               Dual solution
 - Objective          : 1.4855737705e+01              1.4855737705e+01 
 - Norm               : 6.15e+00                      2.77e-02
 - Var. viol.         : 5.68e-14                      0.00e+00
 - Cons. viol.        : 5.68e-14                      1.94e-16
Optimizer terminated with an OPTIMAL status.
Daily cost          : $14.86
 - Cheeseburger     : 4.39
 - Fries            : 6.15
 - LowfatMilk       : 3.42

同时,通过 model.write_soln("./diet_soln.sol") 语句(以Python为例),文件夹中生成了 diet_soln.sol 文件,里面标了变量的求解值、和目标值。如Python语言范例5,运行完会存储一份.sol文件。 image.png