From 1df919838c1f1ac4d47d7a8aeaa748efc8eb9222 Mon Sep 17 00:00:00 2001 From: Alexis Montoison Date: Thu, 29 Aug 2024 18:44:23 -0400 Subject: [PATCH 1/2] [documentation] Add a section about classification of SIF files --- docs/make.jl | 4 +- docs/src/classification.md | 4 ++ docs/src/model.md | 2 - docs/src/reference.md | 2 - docs/src/tutorial.md | 1 + src/CUTEst.jl | 4 +- src/classification.jl | 138 +++++++++++++++++++++++++++---------- src/create_class.jl | 60 ---------------- test/test_select.jl | 56 +++++++-------- 9 files changed, 142 insertions(+), 129 deletions(-) create mode 100644 docs/src/classification.md create mode 100644 docs/src/tutorial.md delete mode 100644 src/create_class.jl diff --git a/docs/make.jl b/docs/make.jl index c9142359..76d54bdc 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -13,8 +13,10 @@ makedocs( sitename = "CUTEst.jl", pages = [ "Home" => "index.md", - "Overview of CUTEst.jl and CUTEstModel" => "model.md", + "Overview of CUTEst.jl" => "tutorial.md", + "CUTEstModel" => "model.md", "Managing SIF files" => "sifdecoder.md", + "Classification of SIF problems" => "classification.md", "Using CUTEst core functions" => "core.md", "Reference" => "reference.md", ], diff --git a/docs/src/classification.md b/docs/src/classification.md new file mode 100644 index 00000000..a7f6e9f0 --- /dev/null +++ b/docs/src/classification.md @@ -0,0 +1,4 @@ +```@docs +CUTEst.select_sif_problems +CUTEst.build_classification +``` diff --git a/docs/src/model.md b/docs/src/model.md index d6ce21c1..6f82b311 100644 --- a/docs/src/model.md +++ b/docs/src/model.md @@ -4,5 +4,3 @@ The main goal of `CUTEst.jl` is to create a `CUTEstModel`, which rely on the ```@docs CUTEstModel ``` - -You can check an [Introduction to CUTEst.jl](https://jso.dev/tutorials/introduction-to-cutest/) on our [site](https://jso.dev/). diff --git a/docs/src/reference.md b/docs/src/reference.md index be6901e0..c9990d96 100644 --- a/docs/src/reference.md +++ b/docs/src/reference.md @@ -6,8 +6,6 @@ ``` ```@docs -CUTEst.create_class -CUTEst.select CUTEst.cons_coord CUTEst.cons_coord! CUTEst.consjac diff --git a/docs/src/tutorial.md b/docs/src/tutorial.md new file mode 100644 index 00000000..31244fd8 --- /dev/null +++ b/docs/src/tutorial.md @@ -0,0 +1 @@ +You can check an [Introduction to CUTEst.jl](https://jso.dev/tutorials/introduction-to-cutest/) on our [site](https://jso.dev/). diff --git a/src/CUTEst.jl b/src/CUTEst.jl index 338172af..ecf5fe0c 100644 --- a/src/CUTEst.jl +++ b/src/CUTEst.jl @@ -7,13 +7,15 @@ using Pkg.Artifacts using Libdl using Quadmath using NLPModels +using JSON import Libdl.dlsym import REPL.TerminalMenus import Base.format_bytes import Printf.@sprintf +import DataStructures: OrderedDict -export CUTEstModel, sifdecoder, build_libsif, set_mastsif, clear_libsif, manage_libsif, list_sif_problems +export CUTEstModel, sifdecoder, build_libsif, set_mastsif, clear_libsif, manage_libsif, list_sif_problems, select_sif_problems const cutest_false = Ref{Bool}(false) const cutest_true = Ref{Bool}(true) diff --git a/src/classification.jl b/src/classification.jl index ef5d260d..329a5b22 100644 --- a/src/classification.jl +++ b/src/classification.jl @@ -27,10 +27,8 @@ const classdb_contype = Dict( const origins = ["academic", "modelling", "real"] const classdb_origin = Dict("A" => origins[1], "M" => origins[2], "R" => origins[3]) -include("create_class.jl") - """ - select(;min_var=1, max_var=Inf, min_con=0, max_con=Inf, + select_sif_problems(;min_var=1, max_var=Inf, min_con=0, max_con=Inf, objtype=*, contype=*, only_free_var=false, only_bnd_var=false, only_linear_con=false, only_nonlinear_con=false, @@ -68,39 +66,48 @@ It can be a number, a symbol, a string, or an array of those. 6, :quadratic or "quadratic" means the constraints are quadratic; 7, :other or "other" means the constraints are more general. -- `custom_filter` is a function to be applied to the problem data, which is a - dict with the following fields: - - "objtype" - String one of the above objective function types - "contype" - String one of the above constraint types - "regular" - Bool whether the problem is regular or not - "derivative_order" - Int order of the highest derivative available - "origin" - String origin of the problem: "academic", "modelling" or "real" - "has_interval_var" - Bool whether it has interval variables - "variables" - Dict with the following fields - "can_choose" - Bool whether you can change the number of variables via parameters - "number" - Int the number of variables (if `can_choose`, the default) - "fixed" - Int the number of fixed variables - "free" - Int the number of free variables - "bounded_below" - Int the number of variables bounded only from below - "bounded_above" - Int the number of variables bounded only from above - "bounded_both" - Int the number of variables bounded from below and above - "constraints" - Dict with the following fields - "can_choose" - Bool whether you can change the number of constraints via parameters - "number" - Int the number of constraints (if `can_choose`, the default) - "equality" - Int the number of equality constraints - "ineq_below" - Int the number of inequalities of the form c(x) ≧ cl - "ineq_above" - Int the number of inequalities of the form c(x) ≦ cu - "ineq_both" - Int the number of inequalities of the form cl ≦ c(x) ≦ cu - "linear" - Int the number of linear constraints - "nonlinear" - Int the number of nonlinear constraints - -For instance, if you'd like to choose only problems with fixed number of - variables, you can pass - - custom_filter=x->x["variables"]["can_choose"]==false +- `custom_filter`: A function to apply additional filtering to the problem data. This data is provided as a dictionary with the following fields: + + - `"objtype"`: String representing the objective function type. It can be one of the following: + - `"none"`, `"constant"`, `"linear"`, `"quadratic"`, `"sum_of_squares"`, `"other"` + + - `"contype"`: String representing the constraint type. It can be one of the following: + - `"unc"`, `"fixed_vars"`, `"bounds"`, `"network"`, `"linear"`, `"quadratic"`, `"other"` + + - `"regular"`: Boolean indicating whether the problem is regular or not. + + - `"derivative_order"`: Integer representing the order of the highest derivative available. + + - `"origin"`: String indicating the origin of the problem. Possible values are `"academic"`, `"modelling"`, or `"real"`. + + - `"has_interval_var"`: Boolean indicating whether the problem includes interval variables. + + - `"variables"`: Dictionary with fields related to variables: + - `"can_choose"`: Boolean indicating whether you can change the number of variables via parameters. + - `"number"`: Integer representing the number of variables (default if `"can_choose"` is true). + - `"fixed"`: Integer representing the number of fixed variables. + - `"free"`: Integer representing the number of free variables. + - `"bounded_below"`: Integer representing the number of variables bounded only from below. + - `"bounded_above"`: Integer representing the number of variables bounded only from above. + - `"bounded_both"`: Integer representing the number of variables bounded from both below and above. + + - `"constraints"`: Dictionary with fields related to constraints: + - `"can_choose"`: Boolean indicating whether you can change the number of constraints via parameters. + - `"number"`: Integer representing the number of constraints (default if `"can_choose"` is true). + - `"equality"`: Integer representing the number of equality constraints. + - `"ineq_below"`: Integer representing the number of inequalities of the form `c(x) ≥ cl`. + - `"ineq_above"`: Integer representing the number of inequalities of the form `c(x) ≤ cu`. + - `"ineq_both"`: Integer representing the number of inequalities of the form `cl ≤ c(x) ≤ cu`. + - `"linear"`: Integer representing the number of linear constraints. + - `"nonlinear"`: Integer representing the number of nonlinear constraints. + +For instance, if you'd like to choose only problems with fixed number of variables, you can pass + +```julia +custom_filter = x -> x["variables"]["can_choose"] == false +``` """ -function select(; +function select_sif_problems(; min_var = 1, max_var = Inf, min_con = 0, @@ -164,3 +171,64 @@ canonicalize_ftype(reqtype::AbstractVector{T}, allowedtypes) where {T <: Integer allowedtypes[reqtype] canonicalize_ftype(reqtype::AbstractVector{Symbol}, allowedtypes) = map(string, reqtype) canonicalize_ftype(reqtype, allowedtypes) = reqtype + +# Keep an unexported function `select` to not break the tutorial +select(; kwargs...) = select_sif_problems(; kwargs...) + +""" + build_classification() + +Creates the file `classf.json`, running each problem in `CLASSF.DB` and extracting the necessary information. +It should be left alone, unless you think it is not updated. +If you do, please open an issue. +""" +function build_classification() + classdb = open(readlines, joinpath(ENV["MASTSIF"], "CLASSF.DB")) + problems = OrderedDict() + nlp = 0 + for line in classdb + sline = split(line) + p = String(sline[1]) + cl = split(sline[2], "") + + print("Problem $p... ") + try + nlp = CUTEstModel(p) + problems[p] = Dict( + :objtype => classdb_objtype[cl[1]], + :contype => classdb_contype[cl[2]], + :regular => cl[3] == "R", + :derivative_order => Int(cl[4][1] - '0'), + :origin => classdb_origin[cl[6]], + :has_internal_var => cl[7] == "Y", + :variables => Dict( + :can_choose => sline[3][1] == "V", + :number => nlp.meta.nvar, + :fixed => length(nlp.meta.ifix), + :free => length(nlp.meta.ifree), + :bounded_below => length(nlp.meta.ilow), + :bounded_above => length(nlp.meta.iupp), + :bounded_both => length(nlp.meta.irng), + ), + :constraints => Dict( + :can_choose => sline[4][1] == "V", + :number => nlp.meta.ncon, + :equality => length(nlp.meta.jfix), + :ineq_below => length(nlp.meta.jlow), + :ineq_above => length(nlp.meta.jupp), + :ineq_both => length(nlp.meta.jrng), + :linear => nlp.meta.nlin, + :nonlinear => nlp.meta.nnln, + ), + ) + println("done") + catch ex + println("errored: $ex") + finally + finalize(nlp) + end + end + open(joinpath(dirname(@__FILE__), "classf.json"), "w") do jsonfile + JSON.print(jsonfile, problems, 2) + end +end diff --git a/src/create_class.jl b/src/create_class.jl deleted file mode 100644 index 93f9308f..00000000 --- a/src/create_class.jl +++ /dev/null @@ -1,60 +0,0 @@ -import DataStructures: OrderedDict -using JSON - -"""`create_class()` - -Creates the file `classf.json`, running each problem in `\$MASTSIF/CLASSF.DB` and -extracting the necessary information. It should be left alone, unless you think -it is not updated. If you do, please open an issue at -[https://github.com/JuliaSmoothOptimizers/CUTEst.jl](https://github.com/JuliaSmoothOptimizers/CUTEst.jl) -""" -function create_class() - classdb = open(readlines, joinpath(ENV["MASTSIF"], "CLASSF.DB")) - problems = OrderedDict() - nlp = 0 - for line in classdb - sline = split(line) - p = String(sline[1]) - cl = split(sline[2], "") - - print("Problem $p... ") - try - nlp = CUTEstModel(p) - problems[p] = Dict( - :objtype => classdb_objtype[cl[1]], - :contype => classdb_contype[cl[2]], - :regular => cl[3] == "R", - :derivative_order => Int(cl[4][1] - '0'), - :origin => classdb_origin[cl[6]], - :has_internal_var => cl[7] == "Y", - :variables => Dict( - :can_choose => sline[3][1] == "V", - :number => nlp.meta.nvar, - :fixed => length(nlp.meta.ifix), - :free => length(nlp.meta.ifree), - :bounded_below => length(nlp.meta.ilow), - :bounded_above => length(nlp.meta.iupp), - :bounded_both => length(nlp.meta.irng), - ), - :constraints => Dict( - :can_choose => sline[4][1] == "V", - :number => nlp.meta.ncon, - :equality => length(nlp.meta.jfix), - :ineq_below => length(nlp.meta.jlow), - :ineq_above => length(nlp.meta.jupp), - :ineq_both => length(nlp.meta.jrng), - :linear => nlp.meta.nlin, - :nonlinear => nlp.meta.nnln, - ), - ) - println("done") - catch ex - println("errored: $ex") - finally - finalize(nlp) - end - end - open(joinpath(dirname(@__FILE__), "classf.json"), "w") do jsonfile - JSON.print(jsonfile, problems, 2) - end -end diff --git a/test/test_select.jl b/test/test_select.jl index 2fa310db..bba686c8 100644 --- a/test/test_select.jl +++ b/test/test_select.jl @@ -23,49 +23,49 @@ ENV["MASTSIF"] = mastsif_backup @testset "CUTEst selection tool" begin problems = filter(x -> occursin(r"SIF$", x), readdir(mastsif)) np = length(problems) - @test np == length(CUTEst.select()) + @test np == (select_sif_problems() |> length) @testset "Variables" begin - selection = CUTEst.select(max_var = 10) + selection = select_sif_problems(max_var = 10) n = length(selection) @test small_problem in selection @test !(large_problem in selection) - selection = CUTEst.select(min_var = 11) + selection = select_sif_problems(min_var = 11) @test !(small_problem in selection) @test large_problem in selection @test np == n + length(selection) - selection = CUTEst.select(only_free_var = true) + selection = select_sif_problems(only_free_var = true) @test free_problem in selection @test !(bnd_problem in selection) - selection = CUTEst.select(only_bnd_var = true) + selection = select_sif_problems(only_bnd_var = true) @test !(free_problem in selection) @test bnd_problem in selection end @testset "Constraints" begin - selection = CUTEst.select(max_con = 0) + selection = select_sif_problems(max_con = 0) n = length(selection) @test unc_problem in selection @test !(con_problem in selection) @test !(equ_problem in selection) @test !(ineq_problem in selection) - selection = CUTEst.select(min_con = 1) + selection = select_sif_problems(min_con = 1) @test !(unc_problem in selection) @test con_problem in selection @test equ_problem in selection @test ineq_problem in selection @test np == n + length(selection) - selection = CUTEst.select(only_equ_con = true) + selection = select_sif_problems(only_equ_con = true) @test equ_problem in selection @test !(ineq_problem in selection) - selection = CUTEst.select(only_ineq_con = true) + selection = select_sif_problems(only_ineq_con = true) @test !(equ_problem in selection) @test ineq_problem in selection - selection = CUTEst.select(only_linear_con = true) + selection = select_sif_problems(only_linear_con = true) @test lin_problem in selection @test !(nln_problem in selection) - selection = CUTEst.select(only_nonlinear_con = true) + selection = select_sif_problems(only_nonlinear_con = true) @test !(lin_problem in selection) @test nln_problem in selection end @@ -74,21 +74,21 @@ ENV["MASTSIF"] = mastsif_backup n = length(CUTEst.objtypes) npi = 0 for i = 1:n - selection = CUTEst.select(objtype = i) + selection = select_sif_problems(objtype = i) npi += length(selection) @test objtypes_problems[i] in selection for j in setdiff(1:n, i) @test !(objtypes_problems[j] in selection) end - selection_alt = CUTEst.select(objtype = CUTEst.objtypes[i]) + selection_alt = select_sif_problems(objtype = CUTEst.objtypes[i]) @test sort(selection_alt) == sort(selection) - selection_alt = CUTEst.select(objtype = Symbol(CUTEst.objtypes[i])) + selection_alt = select_sif_problems(objtype = Symbol(CUTEst.objtypes[i])) @test sort(selection_alt) == sort(selection) end @test npi == np for i = 1:(n - 1) for subset in combinations(1:n, i) - selection = CUTEst.select(objtype = subset) + selection = select_sif_problems(objtype = subset) for j in subset @test objtypes_problems[j] in selection end @@ -103,21 +103,21 @@ ENV["MASTSIF"] = mastsif_backup n = length(CUTEst.contypes) npi = 0 for i = 1:n - selection = CUTEst.select(contype = i) + selection = select_sif_problems(contype = i) npi += length(selection) @test contypes_problems[i] in selection for j in setdiff(1:n, i) @test !(contypes_problems[j] in selection) end - selection_alt = CUTEst.select(contype = CUTEst.contypes[i]) + selection_alt = select_sif_problems(contype = CUTEst.contypes[i]) @test sort(selection_alt) == sort(selection) - selection_alt = CUTEst.select(contype = Symbol(CUTEst.contypes[i])) + selection_alt = select_sif_problems(contype = Symbol(CUTEst.contypes[i])) @test sort(selection_alt) == sort(selection) end @test npi == np for i = 1:(n - 1) for subset in combinations(1:n, i) - selection = CUTEst.select(contype = subset) + selection = select_sif_problems(contype = subset) for j in subset @test contypes_problems[j] in selection end @@ -130,22 +130,22 @@ ENV["MASTSIF"] = mastsif_backup #= @testset "Consistency" begin - set1 = CUTEst.select(contype=["unc"]) - set2 = CUTEst.select(max_con=0, only_free_var=true) + set1 = select_sif_problems(contype=["unc"]) + set2 = select_sif_problems(max_con=0, only_free_var=true) @test sort(set1) == sort(set2) - set1 = CUTEst.select(contype=["fixed_vars"]) - set2 = CUTEst.select(max_con=0, custom_filter=x ->( + set1 = select_sif_problems(contype=["fixed_vars"]) + set2 = select_sif_problems(max_con=0, custom_filter=x ->( x["variables"]["fixed"] > 0) && (x["variables"]["fixed"] + x["variables"]["free"] == x["variables"]["number"])) @test sort(set1) == sort(set2) - set1 = CUTEst.select(contype=["unc", "fixed_vars", "bounds"]) - set2 = CUTEst.select(max_con=0) + set1 = select_sif_problems(contype=["unc", "fixed_vars", "bounds"]) + set2 = select_sif_problems(max_con=0) @test sort(set1) == sort(set2) - set1 = CUTEst.select(contype=["linear"]) - set2 = CUTEst.select(min_con=1, only_linear_con=true) + set1 = select_sif_problems(contype=["linear"]) + set2 = select_sif_problems(min_con=1, only_linear_con=true) println("Mastsif says L, but decoding gives otherwise") println(setdiff(set1, set2)) println("Decoding gives linear, but Mastsif disagrees") @@ -155,7 +155,7 @@ ENV["MASTSIF"] = mastsif_backup =# @testset "Canonicalization" begin - set1 = CUTEst.select(objtype = 1:4) + set1 = select_sif_problems(objtype = 1:4) @test !(isempty(set1)) end end From 373583ac2307ee3a5c58496c83e35ca23d5676ae Mon Sep 17 00:00:00 2001 From: Alexis Montoison Date: Thu, 29 Aug 2024 19:36:15 -0400 Subject: [PATCH 2/2] Add a function select_sif_problems --- README.md | 8 +++ src/classification.jl | 143 ++++++++++++++++++++---------------------- 2 files changed, 76 insertions(+), 75 deletions(-) diff --git a/README.md b/README.md index bb4403c7..d3f86108 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,14 @@ using CUTEst available_problems = list_sif_problems() ``` +If you want to retrieve only problems with specific properties, you can use the function `select_sif_problems`: + +```julia +using CUTEst + +filtered_problems = select_sif_problems(; min_var=10, max_var=100, only_linear_con=true) +``` + ## Tutorial You can check an [Introduction to CUTEst.jl](https://jso.dev/tutorials/introduction-to-cutest/) on our [site](https://jso.dev/). diff --git a/src/classification.jl b/src/classification.jl index 329a5b22..fcadef81 100644 --- a/src/classification.jl +++ b/src/classification.jl @@ -28,83 +28,76 @@ const origins = ["academic", "modelling", "real"] const classdb_origin = Dict("A" => origins[1], "M" => origins[2], "R" => origins[3]) """ - select_sif_problems(;min_var=1, max_var=Inf, min_con=0, max_con=Inf, - objtype=*, contype=*, - only_free_var=false, only_bnd_var=false, - only_linear_con=false, only_nonlinear_con=false, - only_equ_con=false, only_ineq_con=false, - custom_filter=*) + select_sif_problems(; min_var=1, max_var=Inf, min_con=0, max_con=Inf, + objtype=*, contype=*, only_free_var=false, + only_bnd_var=false, only_linear_con=false, + only_nonlinear_con=false, only_equ_con=false, + only_ineq_con=false, custom_filter=*) -Returns a subset of the CUTEst problems using the classification file -`classf.json`. This file is export together with the package, so if you have an -old CUTEst installation, it can lead to inconsistencies. +Returns a subset of the CUTEst problems using the classification file `classf.json`. -- `min_var` and `max_var` set the number of variables in the problem; -- `min_con` and `max_con` set the number of constraints in the problem -(e.g., use `max_con=0` for unconstrained or `min_con=1` for constrained) -- `only_*` flags are self-explaining. Note that they appear in conflicting -pairs. Both can be false, but only one can be true. -- `objtype` is the classification of the objective function according to the -[MASTSIF classification file](https://www.cuter.rl.ac.uk/Problems/classification.shtml). -It can be a number, a symbol, a string, or an array of those. - - 1, :none or "none" means there is no objective function; - 2, :constant or "constant" means the objective function is a constant; - 3, :linear or "linear" means the objective function is a linear functional; - 4, :quadratic or "quadratic" means the objective function is quadratic; - 5, :sum_of_squares or "sum_of_squares" means the objective function is a sum of squares - 6, :other or "other" means the objective function is none of the above. - -- `contype` is the classification of the constraints according to the same - MASTSIF classification file. - - 1, :unc or "unc" means there are no constraints at all; - 2, :fixed_vars or "fixed_vars" means the only constraints are fixed variables; - 3, :bounds or "bounds" means the only constraints are bounded variables; - 4, :network or "network" means the constraints represent the adjacency matrix of a (linear) network; - 5, :linear or "linear" means the constraints are linear; - 6, :quadratic or "quadratic" means the constraints are quadratic; - 7, :other or "other" means the constraints are more general. +## Keyword arguments -- `custom_filter`: A function to apply additional filtering to the problem data. This data is provided as a dictionary with the following fields: +- `min_var` and `max_var` set the number of variables in the problem; - - `"objtype"`: String representing the objective function type. It can be one of the following: - - `"none"`, `"constant"`, `"linear"`, `"quadratic"`, `"sum_of_squares"`, `"other"` +- `min_con` and `max_con` set the number of constraints in the problem (use `max_con=0` for unconstrained or `min_con=1` for constrained); - - `"contype"`: String representing the constraint type. It can be one of the following: - - `"unc"`, `"fixed_vars"`, `"bounds"`, `"network"`, `"linear"`, `"quadratic"`, `"other"` +- `only_*` flags are self-explaining. Note that they appear in conflicting pairs. Both can be false, but only one can be true. - - `"regular"`: Boolean indicating whether the problem is regular or not. +- `objtype` is the classification of the objective function according to the [MASTSIF classification](https://www.cuter.rl.ac.uk/Problems/classification.shtml). It can be a number, a symbol, a string, or an array of those. + - 1, :none or "none" means there is no objective function; + - 2, :constant or "constant" means the objective function is a constant; + - 3, :linear or "linear" means the objective function is a linear functional; + - 4, :quadratic or "quadratic" means the objective function is quadratic; + - 5, :sum_of_squares or "sum_of_squares" means the objective function is a sum of squares; + - 6, :other or "other" means the objective function is none of the above. - - `"derivative_order"`: Integer representing the order of the highest derivative available. +- `contype` is the classification of the constraints according to the same MASTSIF classification file. + - 1, :unc or "unc" means there are no constraints at all; + - 2, :fixed_vars or "fixed_vars" means the only constraints are fixed variables; + - 3, :bounds or "bounds" means the only constraints are bounded variables; + - 4, :network or "network" means the constraints represent the adjacency matrix of a (linear) network; + - 5, :linear or "linear" means the constraints are linear; + - 6, :quadratic or "quadratic" means the constraints are quadratic; + - 7, :other or "other" means the constraints are more general. - - `"origin"`: String indicating the origin of the problem. Possible values are `"academic"`, `"modelling"`, or `"real"`. - - - `"has_interval_var"`: Boolean indicating whether the problem includes interval variables. +- `custom_filter`: A function to apply additional filtering to the problem data. This data is provided as a dictionary with the following fields: + - `"objtype"`: String representing the objective function type. It can be one of the following: + - `"none"`, `"constant"`, `"linear"`, `"quadratic"`, `"sum_of_squares"`, `"other"` - - `"variables"`: Dictionary with fields related to variables: - - `"can_choose"`: Boolean indicating whether you can change the number of variables via parameters. - - `"number"`: Integer representing the number of variables (default if `"can_choose"` is true). - - `"fixed"`: Integer representing the number of fixed variables. - - `"free"`: Integer representing the number of free variables. - - `"bounded_below"`: Integer representing the number of variables bounded only from below. - - `"bounded_above"`: Integer representing the number of variables bounded only from above. - - `"bounded_both"`: Integer representing the number of variables bounded from both below and above. + - `"contype"`: String representing the constraint type. It can be one of the following: + - `"unc"`, `"fixed_vars"`, `"bounds"`, `"network"`, `"linear"`, `"quadratic"`, `"other"` - - `"constraints"`: Dictionary with fields related to constraints: - - `"can_choose"`: Boolean indicating whether you can change the number of constraints via parameters. - - `"number"`: Integer representing the number of constraints (default if `"can_choose"` is true). - - `"equality"`: Integer representing the number of equality constraints. - - `"ineq_below"`: Integer representing the number of inequalities of the form `c(x) ≥ cl`. - - `"ineq_above"`: Integer representing the number of inequalities of the form `c(x) ≤ cu`. - - `"ineq_both"`: Integer representing the number of inequalities of the form `cl ≤ c(x) ≤ cu`. - - `"linear"`: Integer representing the number of linear constraints. - - `"nonlinear"`: Integer representing the number of nonlinear constraints. + - `"regular"`: Boolean indicating whether the problem is regular or not. + - `"derivative_order"`: Integer representing the order of the highest derivative available. -For instance, if you'd like to choose only problems with fixed number of variables, you can pass + - `"origin"`: String indicating the origin of the problem. Possible values are `"academic"`, `"modelling"`, or `"real"`. + + - `"has_interval_var"`: Boolean indicating whether the problem includes interval variables. + + - `"variables"`: Dictionary with fields related to variables: + - `"can_choose"`: Boolean indicating whether you can change the number of variables via parameters. + - `"number"`: Integer representing the number of variables (default if `"can_choose"` is true). + - `"fixed"`: Integer representing the number of fixed variables. + - `"free"`: Integer representing the number of free variables. + - `"bounded_below"`: Integer representing the number of variables bounded only from below. + - `"bounded_above"`: Integer representing the number of variables bounded only from above. + - `"bounded_both"`: Integer representing the number of variables bounded from both below and above. + + - `"constraints"`: Dictionary with fields related to constraints: + - `"can_choose"`: Boolean indicating whether you can change the number of constraints via parameters. + - `"number"`: Integer representing the number of constraints (default if `"can_choose"` is true). + - `"equality"`: Integer representing the number of equality constraints. + - `"ineq_below"`: Integer representing the number of inequalities of the form `c(x) ≥ cl`. + - `"ineq_above"`: Integer representing the number of inequalities of the form `c(x) ≤ cu`. + - `"ineq_both"`: Integer representing the number of inequalities of the form `cl ≤ c(x) ≤ cu`. + - `"linear"`: Integer representing the number of linear constraints. + - `"nonlinear"`: Integer representing the number of nonlinear constraints. ```julia -custom_filter = x -> x["variables"]["can_choose"] == false +filtered_problems1 = select_sif_problems(; min_var=10, max_var=100, only_linear_con=true) +filtered_problems2 = select_sif_problems(; max_con=0) +filtered_problems3 = select_sif_problems(; min_con=1) ``` """ function select_sif_problems(; @@ -114,12 +107,12 @@ function select_sif_problems(; max_con = Inf, objtype = objtypes, contype = contypes, - only_free_var = false, - only_bnd_var = false, - only_linear_con = false, - only_nonlinear_con = false, - only_equ_con = false, - only_ineq_con = false, + only_free_var::Bool = false, + only_bnd_var::Bool = false, + only_linear_con::Bool = false, + only_nonlinear_con::Bool = false, + only_equ_con::Bool = false, + only_ineq_con::Bool = false, custom_filter::Function = x -> true, ) # Checks for conflicting option @@ -137,9 +130,9 @@ function select_sif_problems(; error("contypes $contype not supported") end - data = JSON.parsefile(joinpath(dirname(@__FILE__), "classf.json")) + data = JSON.parsefile(joinpath(@__DIR__, "classf.json")) problems = keys(data) - selection = Vector{String}() + selection = String[] for p in problems pv = data[p]["variables"] pc = data[p]["constraints"] @@ -164,6 +157,9 @@ function select_sif_problems(; return selection end +# Keep an unexported function `select` to not break the tutorial +select(; kwargs...) = select_sif_problems(; kwargs...) + canonicalize_ftype(reqtype::Integer, allowedtypes) = [allowedtypes[reqtype]] canonicalize_ftype(reqtype::Symbol, allowedtypes) = [string(reqtype)] canonicalize_ftype(reqtype::AbstractString, allowedtypes) = [reqtype] @@ -172,9 +168,6 @@ canonicalize_ftype(reqtype::AbstractVector{T}, allowedtypes) where {T <: Integer canonicalize_ftype(reqtype::AbstractVector{Symbol}, allowedtypes) = map(string, reqtype) canonicalize_ftype(reqtype, allowedtypes) = reqtype -# Keep an unexported function `select` to not break the tutorial -select(; kwargs...) = select_sif_problems(; kwargs...) - """ build_classification()