混合整数問題をモデル化するためのモジュール pulp を商用パッケージGurobiと同じ文法で記述するためのラッパーモジュール

インポート

GRB(定数)クラス

class GRB[source]

GRB()

区分的線形関数

gray[source]

gray(i)

convex_comb_agg_log[source]

convex_comb_agg_log(model, var_list=[])

add piecewise relation with a logarithmic number of binary variables

using the convex combination formulation -- non-disaggregated. Parameters:

- model: a model where to include the SOS type 2
- vars : list of variables that declare the SOS type 2

mult_selection[source]

mult_selection(model, x, a, b)

mult_selection -- add piecewise relation with multiple selection formulation Parameters:

- model: a model where to include the piecewise linear relation
- a[k]: x-coordinate of the k-th point in the piecewise linear relation
- b[k]: y-coordinate of the k-th point in the piecewise linear relation

Returns the model with the piecewise linear relation on added variables x, f, and z.

multidict関数

multidict関数は,辞書を引数として入力すると, 第1の返値としてキーのリスト,2番目以降の返値として辞書を返す.

multidict[source]

multidict(dic)

I,d = multidict({1:80, 2:270, 3:250 , 4:160, 5:180})
J,M,N = multidict({1:[500,600], 2:[800,500], 3:[500,100]})
print(I,d)
print(J,M,N)
[1, 2, 3, 4, 5] {1: 80, 2: 270, 3: 250, 4: 160, 5: 180}
[1, 2, 3] {1: 500, 2: 800, 3: 500} {1: 600, 2: 500, 3: 100}

tuplelistクラス

tuplelistは,名前の通りタプル(組)を要素としたリストである.

tuplelistには,引数によって指定した条件を満たす要素を取り出すselectメソッドが 準備されている.

class tuplelist[source]

tuplelist(iterable=()) :: list

Tuplelist class for mypulp.py It works like Gurobi's tuplelist

cost = {(1,1):4,  (1,2):6, (1,3):9,
        (2,1):5,  (2,2):4, (2,3):7,
        (3,1):6,  (3,2):3, (3,3):4,
        (4,1):8,  (4,2):5, (4,3):3,
        (5,1):10, (5,2):8, (5,3):4
        } 
arcs = tuplelist([(i,j) for (i,j) in cost])
print( arcs.select(2,"*") )
[(2, 1), (2, 2), (2, 3)]

線形表現クラス

class LinExpr[source]

LinExpr(coeff=[], var=[]) :: LpAffineExpression

Linear Expresstion Class

変数クラス

class Variable[source]

Variable(name='', lowBound=0.0, upBound=1e+100, cat='Continuous') :: LpVariable

Variable Class

CBC options

Coin Branch and Cutを用いて最適化する際に,以下のオプションを付加することができる.

class pulp.apis.PULP_CBC_CMD(mip=True, msg=True, timeLimit=None, fracGap=None, maxSeconds=None, gapRel=None, gapAbs=None, presolve=None, cuts=None, strong=None, options=None, warmStart=False, keepFiles=False, path=None, threads=None, logPath=None, mip_start=False)
Bases: pulp.apis.coin_api.COIN_CMD

This solver uses a precompiled version of cbc provided with the package

Parameters

  • mip (bool) – if False, assume LP even if integer variables

  • msg (bool) – if False, no log is shown

  • timeLimit (float) – maximum time for solver (in seconds)

  • gapRel (float) – relative gap tolerance for the solver to stop (in fraction)

  • gapAbs (float) – absolute gap tolerance for the solver to stop

  • threads (int) – sets the maximum number of threads

  • options (list) – list of additional options to pass to solver

  • warmStart (bool) – if True, the solver will use the current value of variables as a start

  • keepFiles (bool) – if True, files are saved in the current directory and not deleted after solving

  • path (str) – path to the solver binary

  • logPath (str) – path to the log file

  • presolve (bool) – if True, adds presolve on

  • cuts (bool) – if True, adds gomory on knapsack on probing on

  • strong (bool) – if True, adds strong

モデルクラスの最適化メソッド optimize の引数 solverで, PULP_CBC_CMDのインスタンスを渡す.

optimize(self, solver=PULP_CBC_CMD(timeLimit=max_cpu, presolve=True))

モデルクラス

class Model[source]

Model(name='') :: LpProblem

Model Class

例題

TEST=True
if TEST:
    model = Model("lo1")

    J, v = multidict({1: 16, 2: 19, 3: 23, 4: 28})

    # x1 = model.addVar(vtype="C", name="x1")
    # x2 = model.addVar(vtype="I", name="x2")
    # x3 = model.addVar(lb=0, ub=30, vtype="B", name="x3")

    x1 = model.addVar(vtype=GRB.CONTINUOUS, name="x1")
    # x1 = model.addVar(vtype="N", lb=10.5, ub=50,name="x1")
    x2 = model.addVar(vtype="C", name="x2")
    x3 = model.addVar(lb=0, ub=30, vtype="C", name="x3")

    model.update()
    model.addSOS(2, [x1, x2, x3])
    L1 = LinExpr([2, 1, 1], [x1, x2, x3])
    # L1=LinExpr()
    # L1.addTerms(2,x1)
    # L1.addTerms(1,x2)
    # L1.addTerms(1,x3)

    # model.addConstr(lhs=L1,sense="<=",rhs=60,name="C0")
    # model.addConstr(x1 + 2*x2 + x3 <= 60, name="C1")

    c1 = model.addConstr(lhs=L1, sense="<=", rhs=60)
    model.addConstr(x1 + 2 * x2 + x3 <= 60)

    model.setObjective(15 * x1 + 18 * x2 + 30 * x3, GRB.MAXIMIZE)

    model.write("mypulp1.mps")
    model.write("mypulp1.lp")
    
    #SCIPを使用する場合
    solver = pulp.SCIP(timeLimit=10)
    model.optimize(solver=solver)
    
    #model.optimize()

    if model.Status == GRB.Status.OPTIMAL:
        model.write("answer.sol")
        print("Opt. Value=", model.ObjVal)
        # for v in model.getVars():
        #    print(v.VarName,v.X,v.RC)
        for v in model.getVars():
            print(v.VarName, v.X)
        for c in model.getConstrs():
            print(c.ConstrName, c.Pi)
    # m=Model()
    # x=m.addVar( name="x", vtype="I" , lb=1)
    # y=m.addVar( name="y", vtype="I" , lb=1)
    # z=m.addVar( name="z", vtype="I" , lb=1)
    # m.update()
    # m.addConstr(2*x+ y ==11)
    # m.addConstr(y+ 3*z ==14)
    # # m.setObjective(0,GRB.MINIMIZE)
    # m.optimize()
    # print(x.X,y.X,z.X)
Opt. Value= 30.0
x1 0.0
x2 0.0
x3 1.0
x_1 1.0
c_1 None
c_2 None
c_3 None
c_4 None
c_5 None
if TEST:
    m=Model()

    x = [0,2,3,1]
    y = [1,0,3,3]

    n=len(x)

    X=m.addVar(ub=3.0, name="X")
    Y=m.addVar(ub=3.0, name ="Y")

    Z=m.addVar(name ="Z")

    a,b={},{}
    for i in range(n):
        a[i] =m.addVar(name="a({0})".format(i))
        b[i] =m.addVar(name="b({0})".format(i))
        m.update()

    for i in range(n):
        m.addConstr( a[i] >= x[i] -X )
        m.addConstr( a[i] >= X-x[i] )
        m.addConstr( b[i] >= y[i] -Y )
        m.addConstr( b[i] >= Y-y[i] )

        m.addConstr(Z>=a[i]+b[i])

    m.setObjective(Z, GRB.MINIMIZE)
    # m.setObjective( quicksum( 1*a[i] for i in range(n))
    #                + quicksum( 1*b[i] for i in range(n)), GRB.MINIMIZE )


    m.optimize()

    print(X.X,Y.X)
    print(m.ObjVal)
    for i in range(n):
        print(a[i].X,b[i].X)
Welcome to the CBC MILP Solver 
Version: 2.10.3 
Build Date: Dec 15 2019 

command line - /Users/mikiokubo/Library/Caches/pypoetry/virtualenvs/scmopt-KVX_UVCf-py3.8/lib/python3.8/site-packages/pulp/apis/../solverdir/cbc/osx/64/cbc /var/folders/69/5y96sdc94jxf6khgc8mlmxrr0000gn/T/a9600581b8304017ab19ab021b6e0065-pulp.mps branch printingOptions all solution /var/folders/69/5y96sdc94jxf6khgc8mlmxrr0000gn/T/a9600581b8304017ab19ab021b6e0065-pulp.sol (default strategy 1)
At line 2 NAME          MODEL
At line 3 ROWS
At line 25 COLUMNS
At line 71 RHS
At line 92 BOUNDS
At line 104 ENDATA
Problem MODEL has 20 rows, 11 columns and 44 elements
Coin0008I MODEL read with 0 errors
Presolve 10 (-10) rows, 6 (-5) columns and 26 (-18) elements
0  Obj 0 Primal inf 12.999995 (5)
6  Obj 2.5
Optimal - objective value 2.5
After Postsolve, objective 2.5, infeasibilities - dual 0 (0), primal 0 (0)
Optimal objective 2.5 - 6 iterations time 0.002, Presolve 0.00
Option for printingOptions changed from normal to all
Total time (CPU seconds):       0.00   (Wallclock seconds):       0.01

1.5 2.0
2.5
1.5 1.0
0.5 2.0
1.5 1.0
1.5 1.0
if TEST:
    model = Model("lo1")

    x = model.addVar(name='tonkoke')
    y = model.addVar(name='kokenton')
    z = model.addVar(name='mix')

    model.setObjective(15*x + 18*y + 30*z, GRB.MAXIMIZE)
    model.addConstr(2*x +   y + z <= 60, name='pork')
    model.addConstr(  x + 2*y + z <= 60, name='chicken')
    model.addConstr(            z <= 30, name='beef')

    model.optimize()
    print( model.ObjVal )
    for i in model.getVars():
        print(i.VarName, i.X)
Welcome to the CBC MILP Solver 
Version: 2.10.3 
Build Date: Dec 15 2019 

command line - /Users/mikiokubo/Library/Caches/pypoetry/virtualenvs/scmopt-KVX_UVCf-py3.8/lib/python3.8/site-packages/pulp/apis/../solverdir/cbc/osx/64/cbc /var/folders/69/5y96sdc94jxf6khgc8mlmxrr0000gn/T/3175126010324092b3a9adfcf59ef2f7-pulp.mps max branch printingOptions all solution /var/folders/69/5y96sdc94jxf6khgc8mlmxrr0000gn/T/3175126010324092b3a9adfcf59ef2f7-pulp.sol (default strategy 1)
At line 2 NAME          MODEL
At line 3 ROWS
At line 8 COLUMNS
At line 19 RHS
At line 23 BOUNDS
At line 27 ENDATA
Problem MODEL has 3 rows, 3 columns and 7 elements
Coin0008I MODEL read with 0 errors
Presolve 2 (-1) rows, 3 (0) columns and 6 (-1) elements
0  Obj -0 Dual inf 62.999997 (3)
2  Obj 1230
Optimal - objective value 1230
After Postsolve, objective 1230, infeasibilities - dual 0 (0), primal 0 (0)
Optimal objective 1230 - 2 iterations time 0.002, Presolve 0.00
Option for printingOptions changed from normal to all
Total time (CPU seconds):       0.00   (Wallclock seconds):       0.00

1230.0
kokenton 10.0
mix 30.0
tonkoke 10.0