6.3. Modeling and optimization in PuLP

PuLP is a third-party open-source modeling language developed based on Python. It supports modeling and analysis for linear programming, mixed-integer programming, and nonlinear programming problems, and it calls other commercial or open-source solvers to solve the problems.

At present, MindOpt allows you to build a linear programming model by using PuLP on Windows, Linux, or OSX and call MindOpt to solve problems. For more information about PuLP, see the official document.

This topic describes how to use PuLP API to build a model for the optimization problem in Examples of linear programming problems and call MindOpt to solve the problem.

6.3.1. Install PuLP

To use PuLP, you need to install MindOpt first. For more information about how to install and configure MindOpt, see Installation. After installing MindOpt, install PuLP in the following two ways:

  1. Use the pip command

pip install pulp
  1. Use the git command

pip install -U git+https://github.com/coin-or/pulp

For more information about how to install PuLP, visit the official website of PuLP.

6.3.2. Call the PuLP API

The PuLP API document (mindopt_pulp.py) of MindOpt defines the API required for PuLP to call MindOpt. This API document is inherited from the LpSolver category of PuLP and the implementation code is included in the installation package.

<MDOHOME>\<VERSION>\<PLATFORM>\lib\pulp\mindopt_pulp.py

Move this API document to the current directory and load it in the code of Python.

25from mindopt_pulp import MINDOPT

Call the PuLP API to build a model for the optimization problem in Examples of linear programming problems. For more information about the PuLP API, see the official document.

29    # A new LP problem
30    prob = LpProblem("lo_ex1", LpMinimize)
31
32    # Variables
33    # 0 <= x0 <= 10
34    x0 = LpVariable("x0", 0, 10)
35    # 0 <= x1
36    x1 = LpVariable("x1", 0)
37    # 0 <= x2
38    x2 = LpVariable("x2", 0)
39    # 0 <= x3
40    x3 = LpVariable("x3", 0)
41    # Use None for +/- Infinity, i.e. x <= 0 -> LpVariable("x", None, 0)
42
43    # Objective
44    prob += x0 + 1 * x1 + 1 * x2 + 1 * x3, "obj"
45    # (the name at the end is facultative)
46
47    # Constraints
48    """
49    c1 : 1 x0 + 1 x1 + 2 x2 + 3 x3 >= 1
50    c2 : 1 x0 - 1 x2 + 6 x3 = 1
51    """
52    prob += x0 + x1 + 2 * x2 + 3 * x3 >= 1, "c1"
53    prob += x0 - x2 + 6 * x3 == 1, "c2"
54    # (the names at the end are facultative)
55
56    # Write the problem as an MPS file
57    prob.writeMPS("lo_ex1.mps")

Specify the solver to MindOpt and set the related parameters. For more information about parameters, see Optional input parameters.

61    options = {
62            "Method": -1,
63            "NumThreads": 0,
64            "Presolve": 1,
65            "Dualization": -1,
66            "SPX/MaxIterations": 2147483647,
67            "SPX/ColumnGeneration": -1,
68            "IPM/MaxIterations": 400,
69            "MaxTime": 1.7976931348623158e+308,
70            "SPX/PrimalTolerance": 1.E-6,
71            "SPX/DualTolerance": 1.E-6,
72            "IPM/PrimalTolerance": 1.E-8,
73            "IPM/DualTolerance": 1.E-8,
74            "IPM/GapTolerance": 1.E-8}

Call the solve() function of PuLP and obtain related results.

75    prob.solve(MINDOPT(options=options))

6.3.3. Modeling example: mdo_pulp_lo_ex1

The linked file mdo_pulp_lo_ex1.py provides complete code.

 1"""
 2/**
 3 *  Description
 4 *  -----------
 5 *
 6 *  Linear optimization (row-wise input).
 7 *
 8 *  Formulation
 9 *  -----------
10 *
11 *  Minimize
12 *    obj: 1 x0 + 1 x1 + 1 x2 + 1 x3
13 *  Subject To
14 *   c1 : 1 x0 + 1 x1 + 2 x2 + 3 x3 >= 1
15 *   c2 : 1 x0 - 1 x2 + 6 x3 = 1
16 *  Bounds
17 *    0 <= x0 <= 10
18 *    0 <= x1
19 *    0 <= x2
20 *    0 <= x3
21 *  End
22 */
23"""
24from pulp import LpProblem, LpMinimize, LpVariable, LpStatus, value
25from mindopt_pulp import MINDOPT
26
27if __name__ == "__main__":
28
29    # A new LP problem
30    prob = LpProblem("lo_ex1", LpMinimize)
31
32    # Variables
33    # 0 <= x0 <= 10
34    x0 = LpVariable("x0", 0, 10)
35    # 0 <= x1
36    x1 = LpVariable("x1", 0)
37    # 0 <= x2
38    x2 = LpVariable("x2", 0)
39    # 0 <= x3
40    x3 = LpVariable("x3", 0)
41    # Use None for +/- Infinity, i.e. x <= 0 -> LpVariable("x", None, 0)
42
43    # Objective
44    prob += x0 + 1 * x1 + 1 * x2 + 1 * x3, "obj"
45    # (the name at the end is facultative)
46
47    # Constraints
48    """
49    c1 : 1 x0 + 1 x1 + 2 x2 + 3 x3 >= 1
50    c2 : 1 x0 - 1 x2 + 6 x3 = 1
51    """
52    prob += x0 + x1 + 2 * x2 + 3 * x3 >= 1, "c1"
53    prob += x0 - x2 + 6 * x3 == 1, "c2"
54    # (the names at the end are facultative)
55
56    # Write the problem as an MPS file
57    prob.writeMPS("lo_ex1.mps")
58
59    # Solve the problem using the MINDOPT solver
60    # prob.solve(MINDOPT())  # use default options
61    options = {
62            "Method": -1,
63            "NumThreads": 0,
64            "Presolve": 1,
65            "Dualization": -1,
66            "SPX/MaxIterations": 2147483647,
67            "SPX/ColumnGeneration": -1,
68            "IPM/MaxIterations": 400,
69            "MaxTime": 1.7976931348623158e+308,
70            "SPX/PrimalTolerance": 1.E-6,
71            "SPX/DualTolerance": 1.E-6,
72            "IPM/PrimalTolerance": 1.E-8,
73            "IPM/DualTolerance": 1.E-8,
74            "IPM/GapTolerance": 1.E-8}
75    prob.solve(MINDOPT(options=options))
76
77    # Print the status of the solved LP
78    print("Status:", LpStatus[prob.status])
79
80    # Print the value of the variables at the optimum
81    for v in prob.variables():
82        print(v.name, "=", v.varValue)
83
84    # Print the value of the objective
85    print("objective=", value(prob.objective))