@@ -12,40 +12,36 @@ optimization routines. The wrapper
1212to the problem collection, which we can leverage to test the optimizers made available by
1313Optimization.jl.
1414
15- This benchmark uses the following packages:
16-
1715
1816```julia; eval = true; @setup
1917using Pkg; Pkg.activate("."); Pkg.instantiate()
20- ```
21-
22- ```julia; eval = true
2318using Optimization
2419using OptimizationNLPModels
2520using CUTEst
2621using OptimizationOptimJL
22+ using OptimizationOptimisers
23+ using OptimizationOptimJL: LBFGS, ConjugateGradient, NelderMead, SimulatedAnnealing, ParticleSwarm
2724using Ipopt
2825using OptimizationMOI
2926using OptimizationMOI: MOI as MOI
3027using DataFrames
3128using Plots
3229using StatsPlots
3330using StatsBase: countmap
34- using OptimizationOptimJL: LBFGS, ConjugateGradient, NelderMead, SimulatedAnnealing, ParticleSwarm
3531
3632optimizers = [
37- ("LBFGS", LBFGS()),
38- ("ConjugateGradient", ConjugateGradient()),
39- ("NelderMead", NelderMead()),
40- ("SimulatedAnnealing", SimulatedAnnealing()),
41- ("ParticleSwarm", ParticleSwarm()),
33+ ("Ipopt", MOI.OptimizerWithAttributes(Ipopt.Optimizer,
34+ "max_iter" => 5000,
35+ "tol" => 1e-6,
36+ "print_level" => 5)),
4237]
4338
4439function get_stats(sol, optimizer_name)
45- if hasfield(typeof(sol), :stats) && hasfield(typeof(sol.stats), :time)
46- solve_time = sol.stats.time
47- else
48- solve_time = NaN
40+ # Robustly get solve_time, even if stats or time is missing
41+ solve_time = try
42+ hasfield(typeof(sol), :stats) && hasfield(typeof(sol.stats), :time) ? getfield(sol.stats, :time) : NaN
43+ catch
44+ NaN
4945 end
5046 return (length(sol.u), solve_time, optimizer_name, Symbol(sol.retcode))
5147end
@@ -135,15 +131,22 @@ problems on this section.
135131
136132```julia
137133@info "before"
138- eq_bou_problems = CUTEst.select_sif_problems(min_con=1, only_equ_con=true, only_free_var=false)
139- @info "after1 - testing $(length(eq_bou_problems)) equality-constrained problems"
140134
141- # Limit to first 50 problems for 100GB memory systems
142- eq_bou_problems = eq_bou_problems[1:min(50, length(eq_bou_problems))]
143- @info "Limited to $(length(eq_bou_problems)) problems for comprehensive testing"
135+ # Select a moderate subset of equality-constrained bounded problems for a realistic mix
136+ eq_bou_problems = CUTEst.select_sif_problems(min_con=1, only_equ_con=true, only_free_var=false)
137+ eq_bou_problems = eq_bou_problems[1:min(30, length(eq_bou_problems))]
138+ # Skip HIER13, BLOWEYA, LUKVLE8, READING2, NINENEW, READING6, DITTERT, CVXQP2, and MSS1 if present
139+ eq_bou_problems = filter(p -> !(lowercase(p) in ["hier13", "bloweya", "lukvle8", "patternne", "reading2", "ninenew", "reading6", "dittert", "cvxqp2", "mss1"]), eq_bou_problems)
140+ @info "Testing $(length(eq_bou_problems)) equality-constrained bounded problems (subset)"
144141
145142# Analysis
146- eq_bou_results = run_benchmarks(eq_bou_problems, optimizers)
143+ eq_bou_results = run_benchmarks(eq_bou_problems, optimizers; chunk_size=3)
144+
145+ total_attempts = nrow(eq_bou_results)
146+ successful_codes = [:Success, :MaxIters, :MaxTime, :FirstOrderOptimal]
147+ successful_results = filter(row -> row.retcode in successful_codes, eq_bou_results)
148+ successful_attempts = nrow(successful_results)
149+ success_rate = total_attempts > 0 ? round(successful_attempts / total_attempts * 100, digits=1) : 0
147150
148151# Calculate and display success rates
149152successful_codes = [:Success, :MaxIters, :MaxTime, :FirstOrderOptimal]
@@ -152,56 +155,94 @@ total_attempts = nrow(eq_bou_results)
152155successful_attempts = nrow(successful_results)
153156success_rate = total_attempts > 0 ? round(successful_attempts / total_attempts * 100, digits=1) : 0
154157
155- @info "SUCCESS RATE ANALYSIS:"
156- @info "Total attempts: $(total_attempts)"
157- @info "Successful attempts: $(successful_attempts)"
158- @info "Success rate: $(success_rate)%"
159-
160- @info "after2"
158+ println("Full results table for equality-constrained bounded problems:")
159+ display(eq_bou_results)
160+
161+ println("SUCCESS RATE ANALYSIS (Equality Constrained, Bounded):")
162+ println("Total attempts: ", total_attempts)
163+ println("Successful attempts: ", successful_attempts)
164+ println("Success rate: ", success_rate, "%")
165+ println("Return code distribution:")
166+ if total_attempts > 0
167+ for (code, count) in sort(collect(pairs(countmap(eq_bou_results.retcode))), by=x->x[2], rev=true)
168+ println(" ", code, ": ", count, " occurrences")
169+ end
170+ else
171+ println(" No results to analyze")
172+ end
161173
162- @df eq_bou_results scatter(:n_vars, :secs,
174+ if nrow(eq_bou_results) > 0
175+ @df eq_bou_results scatter(:n_vars, :secs,
163176 group = :solver,
164177 xlabel = "n. variables",
165178 ylabel = "secs.",
166179 title = "Time to solution by optimizer and number of vars",
167180 )
168- @info "after3"
181+ println("Plotted equality-constrained bounded results.")
182+ else
183+ println("No equality-constrained bounded results to plot. DataFrame is empty.")
184+ println("Attempted problems:")
185+ println(eq_bou_problems)
186+ end
169187```
170188
171189Next, we examine the same relationship for inequality-constrained problems.
172190
173191```julia
174192@info "after4"
175- neq_bou_problems = CUTEst.select_sif_problems(min_con=1, only_ineq_con=true, only_free_var=false)
176- @info "after5 - testing $(length(neq_bou_problems)) inequality-constrained problems"
177193
178- # Limit to first 50 problems for 100GB memory systems
179- neq_bou_problems = neq_bou_problems[1:min(50, length(neq_bou_problems))]
180- @info "Limited to $(length(neq_bou_problems)) problems for comprehensive testing"
194+ # Select a moderate subset of inequality-constrained bounded problems for a realistic mix
195+ neq_bou_problems = CUTEst.select_sif_problems(min_con=1, only_ineq_con=true, only_free_var=false)
196+ neq_bou_problems = neq_bou_problems[1:min(30, length(neq_bou_problems))]
197+ # Skip HIER13, BLOWEYA, CHARDIS1, LUKVLE8, READING2, CVPXQ2, and MSS1 if present (in case they appear in this list too)
198+ neq_bou_problems = filter(p -> !(lowercase(p) in ("chardis1", "hs67", "hs101", "haifal", "himmelp2", "hanging", "synthes1", "lukvli13", "liswet9", "hs85", "lukvli7", "expfita", "s268")), neq_bou_problems)
199+ @info "Testing $(length(neq_bou_problems)) inequality-constrained bounded problems (subset)"
181200
182201# Analysis
183- neq_bou_results = run_benchmarks(neq_bou_problems, optimizers)
202+ neq_bou_results = run_benchmarks(neq_bou_problems, optimizers; chunk_size=3 )
184203
185- # Calculate and display success rates
204+ total_attempts = nrow(neq_bou_results)
186205successful_codes = [:Success, :MaxIters, :MaxTime, :FirstOrderOptimal]
187206successful_results = filter(row -> row.retcode in successful_codes, neq_bou_results)
188- total_attempts = nrow(neq_bou_results)
189207successful_attempts = nrow(successful_results)
190208success_rate = total_attempts > 0 ? round(successful_attempts / total_attempts * 100, digits=1) : 0
191209
192- @info "INEQUALITY CONSTRAINED SUCCESS RATE: $(success_rate)% ($(successful_attempts)/$(total_attempts))"
210+ # Calculate and display success rates
211+ successful_codes = [:Success, :MaxIters, :MaxTime, :FirstOrderOptimal]
212+ successful_results = filter(row -> row.retcode in successful_codes, neq_bou_results)
213+ total_attempts = nrow(neq_bou_results)
214+ successful_attempts = nrow(successful_results)
215+ success_rate = total_attempts > 0 ? round(successful_attempts / total_attempts * 100, digits=1) : 0
193216
194- @info "after6"
217+ println("Full results table for inequality-constrained bounded problems:")
218+ display(neq_bou_results)
219+
220+ println("SUCCESS RATE ANALYSIS (Inequality Constrained, Bounded):")
221+ println("Total attempts: ", total_attempts)
222+ println("Successful attempts: ", successful_attempts)
223+ println("Success rate: ", success_rate, "%")
224+ println("Return code distribution:")
225+ if total_attempts > 0
226+ for (code, count) in sort(collect(pairs(countmap(neq_bou_results.retcode))), by=x->x[2], rev=true)
227+ println(" ", code, ": ", count, " occurrences")
228+ end
229+ else
230+ println(" No results to analyze")
231+ end
195232
196- @df neq_bou_results scatter(:n_vars, :secs,
233+ if nrow(neq_bou_results) > 0
234+ @df neq_bou_results scatter(:n_vars, :secs,
197235 group = :solver,
198236 xlabel = "n. variables",
199237 ylabel = "secs.",
200238 title = "Time to solution by optimizer and number of vars",
201239 )
240+ println("Plotted inequality-constrained bounded results.")
241+ else
242+ println("No inequality-constrained bounded results to plot. DataFrame is empty.")
243+ println("Attempted problems:")
244+ println(neq_bou_problems)
245+ end
202246```
203247
204- ```julia, echo = false
205- using SciMLBenchmarks
206- SciMLBenchmarks.bench_footer(WEAVE_ARGS[:folder],WEAVE_ARGS[:file])
207- ```
248+
0 commit comments