7.4. PuLP

Pulp is a third-party open source modeling language developed based on Python. It supports modeling and analysis of problems such as linear programming, mixed integer programming, and nonlinear programming, and calls other commercial or open source solvers to solve them.

Currently, MindOpt can solve linear programming models built with Pulp on Windows/Linux/OSX platforms. For more details about Pulp, please refer to Pulp official documentation.

In this section, we describe how to use the PuLP API to formulate the optimization problem in Example of Linear Programming and call MindOpt to solve it.

7.4.1. Install PuLP

Users must first install MindOpt. For installation and configuration of MindOpt, please refer to Software Installation. After MindOpt is installed, users can install PuLP in the following two ways:

  1. Use pip command to install:

pip install pulp
  1. Use git command to install:

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

For the detailed installation method of PuLP, please refer to PuLP official website or PyPi.

7.4.2. PuLP Interface

MindOpt defines the necessary interfaces for PuLP to call MindOpt in the PuLP interface file (mindopt_pulp.py). This interface inherits from PuLP’s LpSolver class. Implementation details can be found in the interface file within the installation package:

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

When users want to use it, they first need to move this interface file to the current working directory and load the MINDOPT class defined in this module in the Python code:

25from mindopt_pulp import MINDOPT

Next, we call the PuLP API to set up the optimization problem in Example of Linear Programming. For detailed information about the PuLP API, please refer to the PuLP official documentation.

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")

Before solving, we specify using the MindOpt solver and set the relevant parameters for solving (for solver parameters, please refer to 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}

Finally, we call PuLP’s solve() function to solve and obtain the relevant results:

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

7.4.3. Modeling Example: mdo_pulp_lo_ex1

The complete code is provided in the file link mdo_pulp_lo_ex1.py:

 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))