22#
33from collections import defaultdict
44from operator import itemgetter
5- import highspy , random , time , math
5+ import highspy
6+ import random
7+ import time
8+ import math
9+ import numpy as np
610
711# Relative gap for column generation
812CG_GAP_REL = 1e-4
2226#
2327def solveGreedyModel ():
2428 bins = defaultdict (float )
25- solution = defaultdict (list )
29+ solution = defaultdict (list [ int ] )
2630
2731 for item , w in sorted (enumerate (ItemWeights ), reverse = True , key = itemgetter (1 )):
2832 index = next ((i for i , W in bins .items () if W + w <= BinCapacity ), len (bins ))
@@ -56,17 +60,17 @@ def solveCompactModel():
5660 x = {(i ,j ): i * B + j for i in range (NumberItems ) for j in range (B ) }
5761 y = [len (x ) + j for j in range (B )]
5862
59- m .addVars (len (x ), [0 ]* len (x ), [1 ]* len (x )); # x_{ij} \in {0,1}, \forall i,j
60- m .addVars (len (y ), [0 ]* len (y ), [1 ]* len (y )); # y_{j} \in {0,1}, \forall j
63+ m .addVars (len (x ), [0.0 ]* len (x ), [1.0 ]* len (x )) # x_{ij} \in {0,1}, \forall i,j
64+ m .addVars (len (y ), [0.0 ]* len (y ), [1.0 ]* len (y )) # y_{j} \in {0,1}, \forall j
6165 m .changeColsIntegrality (
6266 len (x )+ len (y ),
6367 list (range (len (x )+ len (y ))),
64- [highspy .HighsVarType .kInteger ]* (len (x )+ len (y ))
68+ np . array ( [highspy .HighsVarType .kInteger ]* (len (x )+ len (y ) ))
6569 )
6670
6771 # min sum_{j} y_{j}
6872 m .changeObjectiveSense (highspy .ObjSense .kMinimize )
69- m .changeColsCost (len (y ), y , [1 ]* len (y ))
73+ m .changeColsCost (len (y ), y , [1.0 ]* len (y ))
7074
7175 # \sum_{j} x_{ij} == 1, \foreach i
7276 # 1 <= \sum_{j} x_{ij} <= 1
@@ -76,7 +80,7 @@ def solveCompactModel():
7680 1 , # rhs
7781 B , # Number of non-zero variables
7882 [x [i ,j ] for j in range (B )], # Indexes of variable
79- [1 ] * B # Coefficients of variables
83+ [1.0 ] * B # Coefficients of variables
8084 )
8185
8286 # sum_{i} w_{i} * x_{ij} <= c * y_{j}, \foreach j
@@ -116,17 +120,17 @@ def createMasterProblem(columns: list):
116120 m .setOptionValue ('output_flag' , False )
117121 m .setOptionValue ('random_seed' , SEED )
118122
119- m .addVars (len (columns ), [0 ]* len (columns ), [1 ]* len (columns ))
123+ m .addVars (len (columns ), [0.0 ]* len (columns ), [1.0 ]* len (columns ))
120124
121125 # min \sum_{k} \lambda_{k}
122126 m .changeObjectiveSense (highspy .ObjSense .kMinimize )
123- m .changeColsCost (len (columns ), list (range (len (columns ))), [1 ]* len (columns ))
127+ m .changeColsCost (len (columns ), list (range (len (columns ))), [1.0 ]* len (columns ))
124128
125129 # \sum_{k \in K_i} \lambda_{k} == 1, \foreach i
126130 # 1 <= \sum_{k \in K_i} \lambda_{k} <= 1
127131 for i in range (NumberItems ):
128132 K_i = [k for k , column in enumerate (columns ) if i in column ]
129- m .addRow (1 , 1 , len (K_i ), K_i , [1 ]* len (K_i ))
133+ m .addRow (1 , 1 , len (K_i ), K_i , [1.0 ]* len (K_i ))
130134
131135 m .run ()
132136
@@ -150,8 +154,8 @@ def solveSubproblemExact(duals):
150154 m .setOptionValue ('output_flag' , False )
151155 m .setOptionValue ('random_seed' , SEED )
152156
153- m .addVars (NumberItems , [0 ]* NumberItems , [1 ]* NumberItems )
154- m .changeColsIntegrality (NumberItems , list (range (NumberItems )), [highspy .HighsVarType .kInteger ]* NumberItems )
157+ m .addVars (NumberItems , [0.0 ]* NumberItems , [1.0 ]* NumberItems )
158+ m .changeColsIntegrality (NumberItems , list (range (NumberItems )), np . array ( [highspy .HighsVarType .kInteger ]* NumberItems ) )
155159
156160 # max \sum_{i} \mu_{i} * z_{i}
157161 # where \mu_{i} is the dual variable for the i-th row of the master problem
@@ -179,7 +183,7 @@ def solveSubproblemExact(duals):
179183# Solve the knapsack subproblem with greedy heuristic
180184def solveSubproblemNotExact (duals ):
181185 total_weight = 0
182- new_column = []
186+ new_column : list [ int ] = []
183187
184188 for i in sorted (range (NumberItems ), key = lambda i : - duals [i ]/ ItemWeights [i ]):
185189 if duals [i ] >= 0 and ItemWeights [i ] + total_weight <= BinCapacity :
@@ -192,8 +196,9 @@ def solveSubproblemNotExact(duals):
192196#
193197# Generate columns for the master problem
194198#
195- def generateColumns (columns : list , m , msg = True , solve_exact = False , start_time = 0 ):
199+ def generateColumns (columns : list [ list [ int ]] , m , msg = True , solve_exact = False , start_time = 0. 0 ):
196200 best_gap = math .inf
201+ row_format = ""
197202
198203 iter = 0
199204 while True :
@@ -261,7 +266,7 @@ class Node:
261266 assigned_columns : list [int ]
262267
263268 value : float
264- final_columns : list [int ]
269+ final_columns : list [list [ int ] ]
265270 final_columns_vals : list [float ]
266271 final_fractional_columns : list [int ]
267272
@@ -320,7 +325,7 @@ def solveNode(node: Node, columns: list[list[int]], m):
320325# Specifically, the code "up-branches" columns with fractional value in the RMP solution, i.e., forces specific columns
321326# to be selected in RMP. The subproblems don't need to explicitly enforce this constraint (unlike other branching strategies).
322327#
323- def branchAndPrice (m , vals , columns , start_time = 0 ):
328+ def branchAndPrice (m , vals , columns : list [ list [ int ]] , start_time = 0. 0 ):
324329 header = ["NodesExpl" , "TreeSize" , "CurrCols" , "FracCols" , "UB" , "Time" ]
325330 row_format = "{:>12}" * (len (header ))
326331 print (row_format .format (* header ))
0 commit comments