@@ -60,10 +60,10 @@ function case_generator(lbd, ubd, n, m)
6060 return all_lvbs, all_uvbs
6161end
6262
63- # Now, given a problem, I want to create the right objects to calculate
64- # relaxations , create the optimization problems, and pass them to PDLP
63+
64+ # Given a problem , create the optimization problems and pass them to PDLP
6565# and other comparison solvers (GLPK, Gurobi, HiGHS)
66- function run_example (example:: LoadedProblem , n_LPs:: Int , n_cuts:: Int ; run_GLPK:: Bool = true , run_Gurobi:: Bool = true , run_HiGHS:: Bool = true , run_2xGPU:: Bool = false )
66+ function run_example (example:: LoadedProblem , n_LPs:: Int , n_cuts:: Int ; run_BatchPDLP :: Bool = true , run_GLPK:: Vector{ Bool} = fill ( true , 3 ), run_Gurobi:: Vector{ Bool} = fill ( true , 4 ), run_HiGHS:: Vector{ Bool} = fill ( true , 4 ) , run_2xGPU:: Bool = false )
6767 # #############################################################################
6868 # ######## Step 1) Get Bounds
6969 # #############################################################################
@@ -165,7 +165,7 @@ function run_example(example::LoadedProblem, n_LPs::Int, n_cuts::Int; run_GLPK::
165165
166166 # Feed in data to the PDLPData struct
167167 PDLP_data = PDLPData (n_LPs, example. nvars+ 1 , 1 + n_cuts* cut_height, sparsity= sparsity, iteration_limit= 1000000 )
168-
168+
169169 # Since the PDLP_GPU struct already has an allocated field for PDLP data, we
170170 # only need to update that field with the new LP to solve. The main PDLP
171171 # algorithm already resets all fields except for the original LP, so to prepare
@@ -237,14 +237,15 @@ function run_example(example::LoadedProblem, n_LPs::Int, n_cuts::Int; run_GLPK::
237237 PDLP_lowres_objectives = CUDA. zeros (Float64, n_LPs, 2 )
238238
239239 # Solve the problems once for compilation
240- try
241- PDLP (PDLP_data, solutions= PDLP_solutions, objectives= PDLP_objectives, return_both_obj= true )
242- catch
243- nothing
240+ if run_BatchPDLP
241+ try
242+ PDLP (PDLP_data, solutions= PDLP_solutions, objectives= PDLP_objectives, return_both_obj= true )
243+ catch
244+ nothing
245+ end
244246 end
245247
246248 # Solve the problem once at higher tolerances (default is 1E-8 for abs,rel,primal/dual infeas)
247- println (" Starting BatchPDLP" )
248249 GC. gc ()
249250 GC. enable (false ) # Disable garbage collection temporarily to not impact results
250251
@@ -255,19 +256,22 @@ function run_example(example::LoadedProblem, n_LPs::Int, n_cuts::Int; run_GLPK::
255256
256257 # Solve for the first time, but only do (at least) 95% of problems
257258 # (then reset and run all the problems as normal)
258- iterations = Array (PDLP_data. iterations)
259- stop_here = 0
260- for i in sort (unique (iterations))
261- if count (iterations .<= i) >= 0.95 * n_LPs
262- stop_here = i
263- break
259+ if run_BatchPDLP
260+ println (" Starting BatchPDLP" )
261+ iterations = Array (PDLP_data. iterations)
262+ stop_here = 0
263+ for i in sort (unique (iterations))
264+ if count (iterations .<= i) >= 0.95 * n_LPs
265+ stop_here = i
266+ break
267+ end
268+ end
269+ PDLP_data. parameters. iteration_limit = Int32 (stop_here)
270+ try
271+ PDLP_95pct_solving_time[1 ] = @elapsed PDLP (PDLP_data, solutions= PDLP_solutions, objectives= PDLP_objectives, return_both_obj= true )
272+ catch
273+ PDLP_95pct_solving_time[1 ] = NaN
264274 end
265- end
266- PDLP_data. parameters. iteration_limit = Int32 (stop_here)
267- try
268- PDLP_95pct_solving_time[1 ] = @elapsed PDLP (PDLP_data, solutions= PDLP_solutions, objectives= PDLP_objectives, return_both_obj= true )
269- catch
270- PDLP_95pct_solving_time[1 ] = NaN
271275 end
272276
273277 # Save objectives and termination status
@@ -281,10 +285,12 @@ function run_example(example::LoadedProblem, n_LPs::Int, n_cuts::Int; run_GLPK::
281285 PDLP_data. parameters. iteration_limit = Int32 (1000000 )
282286
283287 # Run PDLP with an iteration limit of 1E6 and tolerances of 1E-8
284- try
285- PDLP_solving_time[1 ] = @elapsed PDLP (PDLP_data, solutions= PDLP_solutions, objectives= PDLP_objectives, return_both_obj= true )
286- catch
287- PDLP_solving_time[1 ] = NaN
288+ if run_BatchPDLP
289+ try
290+ PDLP_solving_time[1 ] = @elapsed PDLP (PDLP_data, solutions= PDLP_solutions, objectives= PDLP_objectives, return_both_obj= true )
291+ catch
292+ PDLP_solving_time[1 ] = NaN
293+ end
288294 end
289295
290296 # Save objectives and termination statuses as CPU arrays
@@ -300,10 +306,12 @@ function run_example(example::LoadedProblem, n_LPs::Int, n_cuts::Int; run_GLPK::
300306 PDLP_data. parameters. termination_criteria. eps_dual_infeasible = 1E-8
301307
302308 # Solve again with lower tolerances
303- try
304- PDLP_lowres_solving_time[1 ] = @elapsed PDLP (PDLP_data, solutions= PDLP_lowres_solutions, objectives= PDLP_lowres_objectives, return_both_obj= true )
305- catch
306- PDLP_lowres_solving_time[1 ] = NaN
309+ if run_BatchPDLP
310+ try
311+ PDLP_lowres_solving_time[1 ] = @elapsed PDLP (PDLP_data, solutions= PDLP_lowres_solutions, objectives= PDLP_lowres_objectives, return_both_obj= true )
312+ catch
313+ PDLP_lowres_solving_time[1 ] = NaN
314+ end
307315 end
308316
309317 # Initialize 2xGPU fields
@@ -477,17 +485,19 @@ function run_example(example::LoadedProblem, n_LPs::Int, n_cuts::Int; run_GLPK::
477485 GC. gc ()
478486
479487 # Print out some PDLP solve times
480- println (" BatchPDLP Solve Times:" )
481- println (" ============================================================" )
482- println (" All problems (high-res): | $(round .(PDLP_solving_time[1 ], digits= 6 )) " )
483- println (" All problems (low-res): | $(round .(PDLP_lowres_solving_time[1 ], digits= 6 )) " )
484- println (" >95% of problems (high-res): | $(round .(PDLP_95pct_solving_time[1 ], digits= 6 )) " )
485- println (" ===========================================================" )
486- if run_2xGPU
487- println (" All problems (high-res) (2xGPU): | $(round .(PDLP_2xGPU_solving_time[1 ], digits= 6 )) " )
488- println (" All problems (low-res) (2xGPU): | $(round .(PDLP_lowres_2xGPU_solving_time[1 ], digits= 6 )) " )
489- println (" >95% of problems (high-res) (2xGPU): | $(round .(PDLP_95pct_2xGPU_solving_time[1 ], digits= 6 )) " )
488+ if run_BatchPDLP
489+ println (" BatchPDLP Solve Times:" )
490+ println (" ============================================================" )
491+ println (" All problems (high-res): | $(round .(PDLP_solving_time[1 ], digits= 6 )) " )
492+ println (" All problems (low-res): | $(round .(PDLP_lowres_solving_time[1 ], digits= 6 )) " )
493+ println (" >95% of problems (high-res): | $(round .(PDLP_95pct_solving_time[1 ], digits= 6 )) " )
490494 println (" ===========================================================" )
495+ if run_2xGPU
496+ println (" All problems (high-res) (2xGPU): | $(round .(PDLP_2xGPU_solving_time[1 ], digits= 6 )) " )
497+ println (" All problems (low-res) (2xGPU): | $(round .(PDLP_lowres_2xGPU_solving_time[1 ], digits= 6 )) " )
498+ println (" >95% of problems (high-res) (2xGPU): | $(round .(PDLP_95pct_2xGPU_solving_time[1 ], digits= 6 )) " )
499+ println (" ===========================================================" )
500+ end
491501 end
492502
493503 # Save constraints and the RHS for CPU solvers
@@ -613,17 +623,17 @@ function run_example(example::LoadedProblem, n_LPs::Int, n_cuts::Int; run_GLPK::
613623
614624 # Compile solvers
615625 for i in eachindex (solver_list)
616- if ! run_GLPK && i <= 3
617- solving_times[:,i] . = NaN
618- primal_objectives[i,:] . = NaN
619- dual_objectives[i,:] . = NaN
620- continue
621- elseif ~ run_Gurobi && (i >= 4 && i <= 8 )
622- solving_times[:,i] . = NaN
623- primal_objectives[i,:] . = NaN
624- dual_objectives[i,:] . = NaN
625- continue
626- elseif ~ run_HiGHS && (i >= 9 && i <= 12 )
626+ if (i == 1 && ! (run_GLPK[ 1 ])) ||
627+ (i == 2 && ! (run_GLPK[ 2 ])) ||
628+ (i == 3 && ! (run_GLPK[ 3 ])) ||
629+ (i == 4 && ! (run_Gurobi[ 1 ])) ||
630+ (i == 5 && ! (run_Gurobi[ 2 ])) ||
631+ (i == 6 && ! (run_Gurobi[ 3 ])) ||
632+ (i == 7 && ! (run_Gurobi[ 4 ])) ||
633+ (i == 8 && ! (run_HiGHS[ 1 ])) ||
634+ (i == 9 && ! (run_HiGHS[ 2 ])) ||
635+ (i == 10 && ! (run_HiGHS[ 3 ])) ||
636+ (i == 11 && ! (run_HiGHS[ 4 ]) )
627637 solving_times[:,i] .= NaN
628638 primal_objectives[i,:] .= NaN
629639 dual_objectives[i,:] .= NaN
@@ -655,22 +665,31 @@ function run_example(example::LoadedProblem, n_LPs::Int, n_cuts::Int; run_GLPK::
655665 end
656666
657667 # Now solve all the LPs
668+ first = [findfirst (run_GLPK), findfirst (run_Gurobi), findfirst (run_HiGHS)]
669+ last = [findlast (run_GLPK), findlast (run_Gurobi), findlast (run_HiGHS)]
658670 for solver = eachindex (solver_list)
659- if ! run_GLPK && solver <= 3
660- continue
661- elseif ~ run_Gurobi && (solver >= 4 && solver <= 7 )
662- continue
663- elseif ~ run_HiGHS && (solver >= 8 && solver <= 11 )
664- continue
665- end
666- current_solver = solver_list[solver]
667- if solver== 1
671+ if ! isnothing (first[1 ]) && solver== first[1 ]
668672 println (" Starting GLPK" )
669- elseif solver== 4
673+ elseif ! isnothing (first[ 2 ]) && solver== 3 + first[ 2 ]
670674 println (" Starting Gurobi" )
671- elseif solver== 8
675+ elseif ! isnothing (first[ 3 ]) && solver== 7 + first[ 3 ]
672676 println (" Starting HiGHS" )
673677 end
678+
679+ if (solver== 1 && ! (run_GLPK[1 ])) ||
680+ (solver== 2 && ! (run_GLPK[2 ])) ||
681+ (solver== 3 && ! (run_GLPK[3 ])) ||
682+ (solver== 4 && ! (run_Gurobi[1 ])) ||
683+ (solver== 5 && ! (run_Gurobi[2 ])) ||
684+ (solver== 6 && ! (run_Gurobi[3 ])) ||
685+ (solver== 7 && ! (run_Gurobi[4 ])) ||
686+ (solver== 8 && ! (run_HiGHS[1 ])) ||
687+ (solver== 9 && ! (run_HiGHS[2 ])) ||
688+ (solver== 10 && ! (run_HiGHS[3 ])) ||
689+ (solver== 11 && ! (run_HiGHS[4 ]))
690+ continue
691+ end
692+ current_solver = solver_list[solver]
674693 for i = 1 : n_LPs
675694 try
676695 # Empty the solver of previous run information
@@ -727,22 +746,22 @@ function run_example(example::LoadedProblem, n_LPs::Int, n_cuts::Int; run_GLPK::
727746 dual_objectives[i, solver] = NaN
728747 end
729748 end
730- if solver== 3
749+ if ! isnothing (last[ 1 ]) && solver== last[ 1 ]
731750 println (" GLPK Solve Times:" )
732751 println (" ============================================================" )
733752 println (" Primal Simplex: | $(round (sum (solving_times[:,1 ]), digits= 6 )) " )
734753 println (" Dual Simplex: | $(round (sum (solving_times[:,2 ]), digits= 6 )) " )
735754 println (" Interior Point: | $(round (sum (solving_times[:,3 ]), digits= 6 )) " )
736755 println (" ===========================================================" )
737- elseif solver== 7
756+ elseif ! isnothing (last[ 2 ]) && solver== 3 + last[ 2 ]
738757 println (" Gurobi Solve Times:" )
739758 println (" ============================================================" )
740759 println (" Primal Simplex: | $(round (sum (solving_times[:,4 ]), digits= 6 )) " )
741760 println (" Dual Simplex: | $(round (sum (solving_times[:,5 ]), digits= 6 )) " )
742761 println (" Interior Point: | $(round (sum (solving_times[:,6 ]), digits= 6 )) " )
743762 println (" PDLP: | $(round (sum (solving_times[:,7 ]), digits= 6 )) " )
744763 println (" ===========================================================" )
745- elseif solver== 11
764+ elseif ! isnothing (last[ 3 ]) && solver== 7 + last[ 3 ]
746765 println (" HiGHS Solve Times:" )
747766 println (" ============================================================" )
748767 println (" Primal Simplex: | $(round (sum (solving_times[:,8 ]), digits= 6 )) " )
@@ -860,7 +879,17 @@ for i = 1:size(included, 1)
860879
861880 # Load and run the problem
862881 ex = LoadedProblem (eval (Symbol (included[i,1 ])))
863- data = run_example (ex, 10000 , 3 , run_2xGPU= true )
882+ if i== 33
883+ data = run_example (ex, 10000 , 3 , run_2xGPU= true , run_GLPK= [false , true , true ], run_HiGHS= [true , true , false , true ]) # least, GLPK Primal Simplex crashes VSCode, HiGHS IPM takes >1hr
884+ elseif i== 59
885+ data = run_example (ex, 10000 , 3 , run_2xGPU= true , run_GLPK= [false , true , true ]) # ex7_3_2, GLPK Primal Simplex crashes VSCode
886+ elseif i== 71
887+ data = run_example (ex, 10000 , 3 , run_2xGPU= true , run_HiGHS= [true , true , false , true ]) # mathopt3, HiGHS IPM takes >overnight
888+ elseif i== 102
889+ data = run_example (ex, 10000 , 3 , run_2xGPU= true , run_GLPK= [true , true , false ]) # maxmin, GLPK IPM crashes Julia
890+ else
891+ data = run_example (ex, 10000 , 3 , run_2xGPU= true )
892+ end
864893
865894 # Write data to a CSV
866895 open (" ./benchmarking_results/rundata_$(included[i,1 ]) .csv" , " w" ) do io
0 commit comments