From 8cb7e7454bcef7a6f7299e45656a8d6878b63bc0 Mon Sep 17 00:00:00 2001 From: Jongeun Kim <39563389+jongeunkim@users.noreply.github.com> Date: Mon, 15 Aug 2022 08:13:41 -0700 Subject: [PATCH 01/18] Add a linking constraint feature --- src/Alpine.jl | 2 ++ src/linking.jl | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/multi.jl | 5 ++++ src/solver.jl | 7 +++++- 4 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 src/linking.jl diff --git a/src/Alpine.jl b/src/Alpine.jl index 3aa5d0f3..030c1ae1 100644 --- a/src/Alpine.jl +++ b/src/Alpine.jl @@ -6,6 +6,7 @@ using JuMP import LinearAlgebra: dot, Diagonal import Statistics +import Combinatorics const _ALPINE_VERSION = "v0.4.1" const ALPINE_DEBUG = false @@ -29,6 +30,7 @@ include("presolve.jl") include("amp.jl") include("embedding.jl") include("heuristics.jl") +include("linking.jl") # Convexification include("multi.jl") diff --git a/src/linking.jl b/src/linking.jl new file mode 100644 index 00000000..ef680ac9 --- /dev/null +++ b/src/linking.jl @@ -0,0 +1,68 @@ +function add_linking_constraints(m::Optimizer, λ::Dict) + """ + Add linking constraints between λ[i], λ[j] variables. + + Reference information: + Jongeun Kim, Jean-Philippe P. Richard, Mohit Tawarmalani, Piecewise Polyhedral Relaxations of Multilinear Optimization, + http://www.optimization-online.org/DB_HTML/2022/07/8974.html + + For example, suppose we have λ[i], λ[j], and λ[k] where i=(1,2,3), j=(1,2,4), and k=(1,2,5). + λ[i] contains all multipliers for the extreme points in the space of (x1,x2,x3). + λ[j] contains all multipliers for the extreme points in the space of (x1,x2,x4). + λ[k] contains all multipliers for the extreme points in the space of (x1,x2,x5). + + Using λ[i], λ[j], or λ[k], we can express multilinear function x1*x2. + We define a linking variable μ(1,2) that represents the value of x1*x2. + Linking constraints are + μ(1,2) == convex combination expression for x1*x2 using λ[i], + μ(1,2) == convex combination expression for x1*x2 using λ[j], and + μ(1,2) == convex combination expression for x1*x2 using λ[k]. + + Then, these constraints link between λ[i], λ[j], and λ[k] variables. + """ + + # (Step 0) Define informational paramters used in the report in the end of the function. + t_begin = time() + num_added_constraints = 0 + + # (Step 1) Define link_info::Dict + # - key: linking variable indices + # - value: the subset of key(λ) where each element is a superset of the linking variable indices + maxdeg = maximum([length(k) for k in keys(λ)]) # Compute maximum degree of multilinear terms + if maxdeg <= 2 + # @info "no linking constraint is added because the maximum degree of multilinear term is $(maxdeg)." + return + end + all_vars_idx = sort(collect(union(collect(keys(λ))...))) # Collect all variable indices used in multilinear terms + link_info = Dict(link_var_idx=>filter(r->issubset(link_var_idx, r), keys(λ)) + for deg in 2:maxdeg-1 for link_var_idx in Combinatorics.combinations(all_vars_idx, deg)) + filter!(r -> length(r.second) >= 2, link_info) + if isempty(link_info) + # @info "no linking constraint is added because there is no multilinear terms that shaer more than two variables." + return + end + + # (Step 2) Add linking (decision) variables to the mip model + link_vars = @variable(m.model_mip, [collect(keys(link_info))]) + + # (Step 3) Add linking constraints to the mip model + for (link_var_idx, list_multi_idx) in link_info, (i, multi_idx) in enumerate(list_multi_idx) + # Define `linkidx2multiidx` to know where `link_var_idx` and `list_multi_idx` have the same value. + # `linkidx2multiidx` satisfies that link_var_idx[i] = list_multi_idx[linkidx2multiidx[i]] for all i. + # By the definition of `link_info`, it always holds that issubset(link_var_idx, list_multi_idx). + linkidx2multiidx = [findfirst(multi_idx .== i) for i in link_var_idx] + + # We define the RHS of linking constraints (convex combination expression for prod(x[link_var_idx]) using λ[multi_idx]) + expr = 0 + for idx in Iterators.product([1:d for d in λ[multi_idx][:dim]]...) + var = λ[multi_idx][:vars][λ[multi_idx][:indices][idx...]] + func_value = prod(m.discretization[i][idx[j]] for (i,j) in zip(link_var_idx, linkidx2multiidx)) + expr += func_value * var + end + + @constraint(m.model_mip, link_vars[link_var_idx] == expr) + num_added_constraints += 1 + end + + # @info "$num_added_constraints linking constraints are added in $(time() - t_begin) seconds." +end \ No newline at end of file diff --git a/src/multi.jl b/src/multi.jl index 7bd73195..ff598888 100644 --- a/src/multi.jl +++ b/src/multi.jl @@ -30,6 +30,11 @@ function amp_post_convhull(m::Optimizer; kwargs...) end end + # Add linking constraints + if m.options.linking_constraints + Alp.add_linking_constraints(m, λ) + end + # Experimental code for Warm starting Alp.get_option(m, :convhull_warmstart) && !isempty(m.best_bound_sol) && Alp.amp_warmstart_α(m, α) diff --git a/src/solver.jl b/src/solver.jl index eb97ce0e..2a2c3463 100644 --- a/src/solver.jl +++ b/src/solver.jl @@ -67,6 +67,8 @@ mutable struct OptimizerOptions int_enable :: Bool # Convert integer problem into binary problem int_cumulative_disc :: Bool # Cumulatively involve integer variables for discretization + # Linking constraint feature + linking_constraints :: Bool end function get_default_options() @@ -127,6 +129,8 @@ function get_default_options() int_enable = false int_cumulative_disc = true + linking_constraints = false + return OptimizerOptions(log_level, time_limit, max_iter, @@ -171,6 +175,7 @@ function get_default_options() presolve_bt_mip_time_limit, presolve_bp, int_enable, - int_cumulative_disc) + int_cumulative_disc, + linking_constraints) end \ No newline at end of file From 7cb2ba1174f19baafff4776283452f4dddce9529 Mon Sep 17 00:00:00 2001 From: Jongeun Kim <39563389+jongeunkim@users.noreply.github.com> Date: Mon, 15 Aug 2022 08:20:13 -0700 Subject: [PATCH 02/18] An example to test the linking constraint feature. --- examples/run_examples_linking.jl | 57 ++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 examples/run_examples_linking.jl diff --git a/examples/run_examples_linking.jl b/examples/run_examples_linking.jl new file mode 100644 index 00000000..2e34ec3c --- /dev/null +++ b/examples/run_examples_linking.jl @@ -0,0 +1,57 @@ +# - Necessary - # +using Alpine +using JuMP +using Gurobi +using Ipopt +using Juniper +using Logging + +# Install library package. To install, at your Julia command prompt, +# Pkg.add(path="https://github.com/lanl-ansi/MINLPLib.jl.git") +# Reference: https://github.com/lanl-ansi/MINLPLib.jl +import MINLPLib + +# Choose underlying solvers for Alpine +ipopt = get_ipopt() +gurobi = get_gurobi() +juniper = get_juniper(gurobi, ipopt) + +#= Global solver + Hints: + => Try different integer values (>=4) for `disc_ratio` to potentially observe + better Alpine run times (can be instance specific). + => Choose `presolve_bt` to `false` if you prefer the bound tightening (OBBT) presolve to be turned off. + => If you prefer to use Alpine for only OBBT presolve, without any paritioning applied to the + nonlinear terms, include option "apply_partitioning" below and set it to false. +=# + +function run(use_linking_constraints, time_limit, instance_name) + alpine = JuMP.optimizer_with_attributes(Alpine.Optimizer, + "minlp_solver" => juniper, + "nlp_solver" => ipopt, + "mip_solver" => gurobi, + "presolve_bt" => true, + "disc_ratio" => 10, + "time_limit" => time_limit, + "linking_constraints" => use_linking_constraints) + m = MINLPLib.fetch_model(instance_name) + JuMP.set_optimizer(m, alpine) + + t_begin = time() + JuMP.optimize!(m) + objval = JuMP.objective_value(m) + soltime = time() - t_begin + + return objval, soltime +end + +# Linking constraints are only added when there are multilinear terms whose degree is at least 3. +# Choose instances in `mult3`` or `mult4`` libraries to see the improvement. +const instance_name = "mult3/m_10_3_10_100_1" +const time_limit = 60 + +objval_nolink, soltime_nolink = run(false, time_limit, instance_name) +objval_link, soltime_link = run(true, time_limit, instance_name) + +@info "Solution Time:\t link = $soltime_link, nolink = $soltime_nolink" +@info "Objective Value:\t link = $objval_link, nolink = $objval_nolink" From d4b0406bcbaef163280b8bb9b4505ed5bc7557b4 Mon Sep 17 00:00:00 2001 From: harshangrjn Date: Mon, 15 Aug 2022 10:41:28 -0600 Subject: [PATCH 03/18] Combinatorics dependency added --- CHANGELOG.md | 4 ++++ Project.toml | 2 ++ 2 files changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 19f90fdb..e2ab1e60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Alpine.jl Change Log +## Staged +- New feature: Linking constraints for multilinear terms with uniform and adaptive partitions (speed up in run times for multilinear termed problems) +- Added dependency on Combinatorics package for linking constraints + ## v0.4.1 - Added MOI attribute for tightened bounds post-OBBT (@blegat) diff --git a/Project.toml b/Project.toml index 2277a3b8..34976852 100644 --- a/Project.toml +++ b/Project.toml @@ -5,6 +5,7 @@ repo = "https://github.com/lanl-ansi/Alpine.jl.git" version = "0.4.1" [deps] +Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa" JuMP = "4076af6c-e467-56ae-b986-b466b2749572" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" MathOptInterface = "b8f27783-ece8-5eb3-8dc8-9495eed66fee" @@ -18,6 +19,7 @@ Juniper = "0.8, 0.9" MathOptInterface = "0.10, 1" Pavito = "0.3.4, 0.3.5" julia = "1" +Combinatorics = "1" [extras] Cbc = "9961bab8-2fa3-5c5a-9d89-47fab24efd76" From b7fff0ccddb4c33a1bfc21b0780ac5c809d893d2 Mon Sep 17 00:00:00 2001 From: harshangrjn Date: Tue, 23 Aug 2022 14:41:42 -0600 Subject: [PATCH 04/18] julia formatter added --- .JuliaFormatter.toml | 8 ++++++++ .github/workflows/format_check.yml | 31 ++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 .JuliaFormatter.toml create mode 100644 .github/workflows/format_check.yml diff --git a/.JuliaFormatter.toml b/.JuliaFormatter.toml new file mode 100644 index 00000000..8f4c4870 --- /dev/null +++ b/.JuliaFormatter.toml @@ -0,0 +1,8 @@ +# Configuration file for JuliaFormatter.jl + # For more information, see: https://domluna.github.io/JuliaFormatter.jl/stable/config/ + + always_for_in = true + always_use_return = true + margin = 80 + remove_extra_newlines = true + short_to_long_function_def = true \ No newline at end of file diff --git a/.github/workflows/format_check.yml b/.github/workflows/format_check.yml new file mode 100644 index 00000000..8509ce45 --- /dev/null +++ b/.github/workflows/format_check.yml @@ -0,0 +1,31 @@ +name: format-check + on: + push: + branches: + - master + - release-* + pull_request: + types: [opened, synchronize, reopened] + jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: julia-actions/setup-julia@latest + with: + version: '1' + - uses: actions/checkout@v1 + - name: Format check + shell: julia --color=yes {0} + run: | + using Pkg + Pkg.add(PackageSpec(name="JuliaFormatter", version="1")) + using JuliaFormatter + format("src/MOI_wrapper", verbose=true) + format("test", verbose=true) + out = String(read(Cmd(`git diff`))) + if isempty(out) + exit(0) + end + @error "Some files have not been formatted !!!" + write(stdout, out) + exit(1) \ No newline at end of file From 9de55afa0d92b01f4fabad35b8c6c19de4436a9f Mon Sep 17 00:00:00 2001 From: harshangrjn Date: Tue, 23 Aug 2022 15:16:42 -0600 Subject: [PATCH 05/18] julia formatter for PR #207 --- .JuliaFormatter.toml | 2 +- docs/make.jl | 24 +- examples/JuMP_models.jl | 2 +- examples/MINLPs/blend.jl | 1255 +++++++++----- examples/MINLPs/brainpc3.jl | 40 +- examples/MINLPs/castro.jl | 675 +++++--- examples/MINLPs/circle.jl | 72 +- examples/MINLPs/convex.jl | 119 +- examples/MINLPs/discretemulti.jl | 246 ++- examples/MINLPs/div.jl | 45 +- examples/MINLPs/exprstest.jl | 374 ++-- examples/MINLPs/integer.jl | 443 +++-- examples/MINLPs/linearlift.jl | 43 +- examples/MINLPs/multi.jl | 325 ++-- examples/MINLPs/nlp.jl | 136 +- examples/MINLPs/rosenbrock.jl | 11 +- examples/MINLPs/sincos.jl | 42 +- examples/Project.toml | 1 - examples/optimizers.jl | 53 +- examples/run_examples.jl | 22 +- examples/run_examples_linking.jl | 42 +- src/MOI_wrapper/MOI_function2expr.jl | 13 +- src/MOI_wrapper/MOI_wrapper.jl | 374 ++-- src/algorithm.jl | 886 +++++----- src/amp.jl | 277 ++- src/bounds.jl | 179 +- src/const.jl | 13 +- src/embedding.jl | 231 ++- src/heuristics.jl | 52 +- src/linking.jl | 27 +- src/log.jl | 408 +++-- src/multi.jl | 444 +++-- src/nlexpr.jl | 1206 +++++++------ src/operators.jl | 495 ++++-- src/presolve.jl | 230 ++- src/solver.jl | 309 ++-- src/tmc.jl | 356 ++-- src/utility.jl | 879 +++++----- test/runtests.jl | 24 +- test/test_algorithm.jl | 945 +++++----- test/test_expression.jl | 2410 +++++++++++++++++--------- test/test_solver.jl | 343 ++-- test/test_utility.jl | 185 +- 43 files changed, 8682 insertions(+), 5576 deletions(-) diff --git a/.JuliaFormatter.toml b/.JuliaFormatter.toml index 8f4c4870..693fd7c1 100644 --- a/.JuliaFormatter.toml +++ b/.JuliaFormatter.toml @@ -3,6 +3,6 @@ always_for_in = true always_use_return = true - margin = 80 + margin = 90 remove_extra_newlines = true short_to_long_function_def = true \ No newline at end of file diff --git a/docs/make.jl b/docs/make.jl index b873577e..68db0481 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -5,17 +5,25 @@ using DocumenterTools: Themes for w in ("light", "dark") header = read(joinpath(@__DIR__, "src/assets/themes/style.scss"), String) theme = read(joinpath(@__DIR__, "src/assets/themes/$(w)defs.scss"), String) - write(joinpath(@__DIR__, "src/assets/themes/$(w).scss"), header*"\n"*theme) + write(joinpath(@__DIR__, "src/assets/themes/$(w).scss"), header * "\n" * theme) end -Themes.compile(joinpath(@__DIR__, "src/assets/themes/light.scss"), joinpath(@__DIR__, "src/assets/themes/documenter-light.css")) -Themes.compile(joinpath(@__DIR__, "src/assets/themes/dark.scss"), joinpath(@__DIR__, "src/assets/themes/documenter-dark.css")) +Themes.compile( + joinpath(@__DIR__, "src/assets/themes/light.scss"), + joinpath(@__DIR__, "src/assets/themes/documenter-light.css"), +) +Themes.compile( + joinpath(@__DIR__, "src/assets/themes/dark.scss"), + joinpath(@__DIR__, "src/assets/themes/documenter-dark.css"), +) makedocs( sitename = "Alpine", authors = "Harsha Nagarajan, Site Wang, Kaarthik Sundar and contributors", - format = Documenter.HTML(mathengine = Documenter.MathJax(), - prettyurls = get(ENV, "CI", nothing) == "true"), + format = Documenter.HTML( + mathengine = Documenter.MathJax(), + prettyurls = get(ENV, "CI", nothing) == "true", + ), strict = true, pages = [ "Introduction" => "index.md", @@ -26,8 +34,4 @@ makedocs( ], ) -deploydocs( - repo = "github.com/lanl-ansi/Alpine.jl.git", - push_preview = true -) - +deploydocs(repo = "github.com/lanl-ansi/Alpine.jl.git", push_preview = true) diff --git a/examples/JuMP_models.jl b/examples/JuMP_models.jl index daaafb80..bfda0155 100644 --- a/examples/JuMP_models.jl +++ b/examples/JuMP_models.jl @@ -11,4 +11,4 @@ include("MINLPs/linearlift.jl") include("MINLPs/multi.jl") include("MINLPs/rosenbrock.jl") # include("MINLPs/sincos.jl") -# include("MINLPs/integer.jl") \ No newline at end of file +# include("MINLPs/integer.jl") diff --git a/examples/MINLPs/blend.jl b/examples/MINLPs/blend.jl index b9ce949f..e05fcfdb 100644 --- a/examples/MINLPs/blend.jl +++ b/examples/MINLPs/blend.jl @@ -1,494 +1,825 @@ -function blend029(;solver = nothing) - +function blend029(; solver = nothing) m = Model(solver) @variable(m, x[1:102]) - for i=67:102 - set_binary(x[i]) + for i in 67:102 + set_binary(x[i]) end - for i=1:48 - set_lower_bound(x[i], 0) - set_upper_bound(x[i], 1) + for i in 1:48 + set_lower_bound(x[i], 0) + set_upper_bound(x[i], 1) end - for i=49:66 - set_lower_bound(x[i], 0) - set_upper_bound(x[i], 2) + for i in 49:66 + set_lower_bound(x[i], 0) + set_upper_bound(x[i], 2) end - @objective(m, Max, - 1.74*x[1] - 1.74*x[2] - 1.74*x[3] - 1.45*x[4] - 1.45*x[5] - 1.45*x[6] + 7.38*x[7] + 7.38*x[8] + 7.38*x[9] + 5.6*x[10] + 5.6*x[11] + 5.6*x[12] - 1.7*x[13] - 1.7*x[14] - 1.7*x[15] - 1.18*x[16] - 1.18*x[17] - 1.18*x[18] + 7.21*x[19] + 7.21*x[20] + 7.21*x[21] + 5.45*x[22] + 5.45*x[23] + 5.45*x[24] - 0.3*x[25] - 0.3*x[26] - 0.3*x[27] + 7.71*x[28] + 7.71*x[29] + 7.71*x[30] + 6.28*x[31] + 6.28*x[32] + 6.28*x[33] + 7.74*x[34] + 7.74*x[35] + 7.74*x[36] - 0.84*x[67] - 0.84*x[68] - 0.84*x[69] - 0.05*x[70] - 0.05*x[71] - 0.05*x[72] - 0.94*x[73] - 0.94*x[74] - 0.94*x[75] - 0.81*x[76] - 0.81*x[77] - 0.81*x[78] - 0.79*x[79] - 0.79*x[80] - 0.79*x[81] - 0.05*x[82] - 0.05*x[83] - 0.05*x[84] - 0.65*x[85] - 0.65*x[86] - 0.65*x[87] - 0.97*x[88] - 0.97*x[89] - 0.97*x[90] - 0.57*x[91] - 0.57*x[92] - 0.57*x[93] - 0.26*x[94] - 0.26*x[95] - 0.26*x[96] - 0.45*x[97] - 0.45*x[98] - 0.45*x[99] - 0.1*x[100] - 0.1*x[101] - 0.1*x[102]) + @objective( + m, + Max, + -1.74 * x[1] - 1.74 * x[2] - 1.74 * x[3] - 1.45 * x[4] - 1.45 * x[5] - + 1.45 * x[6] + + 7.38 * x[7] + + 7.38 * x[8] + + 7.38 * x[9] + + 5.6 * x[10] + + 5.6 * x[11] + + 5.6 * x[12] - 1.7 * x[13] - 1.7 * x[14] - 1.7 * x[15] - 1.18 * x[16] - + 1.18 * x[17] - 1.18 * x[18] + + 7.21 * x[19] + + 7.21 * x[20] + + 7.21 * x[21] + + 5.45 * x[22] + + 5.45 * x[23] + + 5.45 * x[24] - 0.3 * x[25] - 0.3 * x[26] - 0.3 * x[27] + + 7.71 * x[28] + + 7.71 * x[29] + + 7.71 * x[30] + + 6.28 * x[31] + + 6.28 * x[32] + + 6.28 * x[33] + + 7.74 * x[34] + + 7.74 * x[35] + + 7.74 * x[36] - 0.84 * x[67] - 0.84 * x[68] - 0.84 * x[69] - 0.05 * x[70] - + 0.05 * x[71] - 0.05 * x[72] - 0.94 * x[73] - 0.94 * x[74] - 0.94 * x[75] - + 0.81 * x[76] - 0.81 * x[77] - 0.81 * x[78] - 0.79 * x[79] - 0.79 * x[80] - + 0.79 * x[81] - 0.05 * x[82] - 0.05 * x[83] - 0.05 * x[84] - 0.65 * x[85] - + 0.65 * x[86] - 0.65 * x[87] - 0.97 * x[88] - 0.97 * x[89] - 0.97 * x[90] - + 0.57 * x[91] - 0.57 * x[92] - 0.57 * x[93] - 0.26 * x[94] - 0.26 * x[95] - + 0.26 * x[96] - 0.45 * x[97] - 0.45 * x[98] - 0.45 * x[99] - 0.1 * x[100] - + 0.1 * x[101] - 0.1 * x[102] + ) - @NLconstraint(m, x[37]*x[55]-0.6*x[1]-0.2*x[13]+0.2*x[25]+0.2*x[28]+0.2*x[31] ==0.04) #= e8: =# - @NLconstraint(m, x[40]*x[58]-0.6*x[4]-0.2*x[16]-0.2*x[25]+0.7*x[34] ==0.07) #= e9: =# - @NLconstraint(m, x[43]*x[55]-0.4*x[1]-0.4*x[13]+0.5*x[25]+0.5*x[28]+0.5*x[31] ==0.1) #= e10: =# - @NLconstraint(m, x[46]*x[58]-0.4*x[4]-0.4*x[16]-0.5*x[25]+0.6*x[34] ==0.06) #= e11: =# - @NLconstraint(m, x[38]*x[56]-(x[37]*x[55]-(x[37]*x[26]+x[37]*x[29]+x[37]*x[32]))-0.6*x[2]-0.2*x[14] ==0) #= e24: =# - @NLconstraint(m, x[39]*x[57]-(x[38]*x[56]-(x[38]*x[27]+x[38]*x[30]+x[38]*x[33]))-0.6*x[3]-0.2*x[15] ==0) #= e25: =# - @NLconstraint(m, x[41]*x[59]-(x[40]*x[58]+x[37]*x[26]-x[40]*x[35])-0.6*x[5]-0.2*x[17] ==0) #= e26: =# - @NLconstraint(m, x[42]*x[60]-(x[41]*x[59]+x[38]*x[27]-x[41]*x[36])-0.6*x[6]-0.2*x[18] ==0) #= e27: =# - @NLconstraint(m, x[44]*x[56]-(x[43]*x[55]-(x[43]*x[26]+x[43]*x[29]+x[43]*x[32]))-0.4*x[2]-0.4*x[14] ==0) #= e28: =# - @NLconstraint(m, x[45]*x[57]-(x[44]*x[56]-(x[44]*x[27]+x[44]*x[30]+x[44]*x[33]))-0.4*x[3]-0.4*x[15] ==0) #= e29: =# - @NLconstraint(m, x[47]*x[59]-(x[46]*x[58]+x[43]*x[26]-x[46]*x[35])-0.4*x[5]-0.4*x[17] ==0) #= e30: =# - @NLconstraint(m, x[48]*x[60]-(x[47]*x[59]+x[44]*x[27]-x[47]*x[36])-0.4*x[6]-0.4*x[18] ==0) #= e31: =# + @NLconstraint( + m, + x[37] * x[55] - 0.6 * x[1] - 0.2 * x[13] + + 0.2 * x[25] + + 0.2 * x[28] + + 0.2 * x[31] == 0.04 + ) #= e8: =# + @NLconstraint( + m, + x[40] * x[58] - 0.6 * x[4] - 0.2 * x[16] - 0.2 * x[25] + 0.7 * x[34] == 0.07 + ) #= e9: =# + @NLconstraint( + m, + x[43] * x[55] - 0.4 * x[1] - 0.4 * x[13] + + 0.5 * x[25] + + 0.5 * x[28] + + 0.5 * x[31] == 0.1 + ) #= e10: =# + @NLconstraint( + m, + x[46] * x[58] - 0.4 * x[4] - 0.4 * x[16] - 0.5 * x[25] + 0.6 * x[34] == 0.06 + ) #= e11: =# + @NLconstraint( + m, + x[38] * x[56] - + (x[37] * x[55] - (x[37] * x[26] + x[37] * x[29] + x[37] * x[32])) - 0.6 * x[2] - + 0.2 * x[14] == 0 + ) #= e24: =# + @NLconstraint( + m, + x[39] * x[57] - + (x[38] * x[56] - (x[38] * x[27] + x[38] * x[30] + x[38] * x[33])) - 0.6 * x[3] - + 0.2 * x[15] == 0 + ) #= e25: =# + @NLconstraint( + m, + x[41] * x[59] - (x[40] * x[58] + x[37] * x[26] - x[40] * x[35]) - 0.6 * x[5] - + 0.2 * x[17] == 0 + ) #= e26: =# + @NLconstraint( + m, + x[42] * x[60] - (x[41] * x[59] + x[38] * x[27] - x[41] * x[36]) - 0.6 * x[6] - + 0.2 * x[18] == 0 + ) #= e27: =# + @NLconstraint( + m, + x[44] * x[56] - + (x[43] * x[55] - (x[43] * x[26] + x[43] * x[29] + x[43] * x[32])) - 0.4 * x[2] - + 0.4 * x[14] == 0 + ) #= e28: =# + @NLconstraint( + m, + x[45] * x[57] - + (x[44] * x[56] - (x[44] * x[27] + x[44] * x[30] + x[44] * x[33])) - 0.4 * x[3] - + 0.4 * x[15] == 0 + ) #= e29: =# + @NLconstraint( + m, + x[47] * x[59] - (x[46] * x[58] + x[43] * x[26] - x[46] * x[35]) - 0.4 * x[5] - + 0.4 * x[17] == 0 + ) #= e30: =# + @NLconstraint( + m, + x[48] * x[60] - (x[47] * x[59] + x[44] * x[27] - x[47] * x[36]) - 0.4 * x[6] - + 0.4 * x[18] == 0 + ) #= e31: =# - @constraint(m, x[1]+x[4]+x[7]+x[10]+x[49] ==1) #= e2: =# - @constraint(m, x[13]+x[16]+x[19]+x[22]+x[52] ==1.1) #= e3: =# - @constraint(m, -x[1]-x[13]+x[25]+x[28]+x[31]+x[55] ==0.2) #= e4: =# - @constraint(m, -x[4]-x[16]-x[25]+x[34]+x[58] ==0.1) #= e5: =# - @constraint(m, -x[7]-x[19]-x[28]-x[34]+x[61] ==1.55) #= e6: =# - @constraint(m, -x[10]-x[22]-x[31]+x[64] ==0.49) #= e7: =# - @constraint(m, x[2]+x[5]+x[8]+x[11]-x[49]+x[50] ==1) #= e12: =# - @constraint(m, x[3]+x[6]+x[9]+x[12]-x[50]+x[51] ==0) #= e13: =# - @constraint(m, x[14]+x[17]+x[20]+x[23]-x[52]+x[53] ==0.1) #= e14: =# - @constraint(m, x[15]+x[18]+x[21]+x[24]-x[53]+x[54] ==0.9) #= e15: =# - @constraint(m, -x[2]-x[14]+x[26]+x[29]+x[32]-x[55]+x[56] ==0) #= e16: =# - @constraint(m, -x[3]-x[15]+x[27]+x[30]+x[33]-x[56]+x[57] ==0) #= e17: =# - @constraint(m, -x[5]-x[17]-x[26]+x[35]-x[58]+x[59] ==0) #= e18: =# - @constraint(m, -x[6]-x[18]-x[27]+x[36]-x[59]+x[60] ==0) #= e19: =# - @constraint(m, -x[8]-x[20]-x[29]-x[35]-x[61]+x[62] ==-0.81) #= e20: =# - @constraint(m, -x[9]-x[21]-x[30]-x[36]-x[62]+x[63] ==-0.88) #= e21: =# - @constraint(m, -x[11]-x[23]-x[32]-x[64]+x[65] ==-0.14) #= e22: =# - @constraint(m, -x[12]-x[24]-x[33]-x[65]+x[66] ==-0.1) #= e23: =# - @constraint(m, x[1]-x[67]<=0) #= e32: =# - @constraint(m, x[2]-x[68]<=0) #= e33: =# - @constraint(m, x[3]-x[69]<=0) #= e34: =# - @constraint(m, x[4]-x[70]<=0) #= e35: =# - @constraint(m, x[5]-x[71]<=0) #= e36: =# - @constraint(m, x[6]-x[72]<=0) #= e37: =# - @constraint(m, x[7]-x[73]<=0) #= e38: =# - @constraint(m, x[8]-x[74]<=0) #= e39: =# - @constraint(m, x[9]-x[75]<=0) #= e40: =# - @constraint(m, x[10]-x[76]<=0) #= e41: =# - @constraint(m, x[11]-x[77]<=0) #= e42: =# - @constraint(m, x[12]-x[78]<=0) #= e43: =# - @constraint(m, x[13]-x[79]<=0) #= e44: =# - @constraint(m, x[14]-x[80]<=0) #= e45: =# - @constraint(m, x[15]-x[81]<=0) #= e46: =# - @constraint(m, x[16]-x[82]<=0) #= e47: =# - @constraint(m, x[17]-x[83]<=0) #= e48: =# - @constraint(m, x[18]-x[84]<=0) #= e49: =# - @constraint(m, x[19]-x[85]<=0) #= e50: =# - @constraint(m, x[20]-x[86]<=0) #= e51: =# - @constraint(m, x[21]-x[87]<=0) #= e52: =# - @constraint(m, x[22]-x[88]<=0) #= e53: =# - @constraint(m, x[23]-x[89]<=0) #= e54: =# - @constraint(m, x[24]-x[90]<=0) #= e55: =# - @constraint(m, x[25]-x[91]<=0) #= e56: =# - @constraint(m, x[26]-x[92]<=0) #= e57: =# - @constraint(m, x[27]-x[93]<=0) #= e58: =# - @constraint(m, x[28]-x[94]<=0) #= e59: =# - @constraint(m, x[29]-x[95]<=0) #= e60: =# - @constraint(m, x[30]-x[96]<=0) #= e61: =# - @constraint(m, x[31]-x[97]<=0) #= e62: =# - @constraint(m, x[32]-x[98]<=0) #= e63: =# - @constraint(m, x[33]-x[99]<=0) #= e64: =# - @constraint(m, x[34]-x[100]<=0) #= e65: =# - @constraint(m, x[35]-x[101]<=0) #= e66: =# - @constraint(m, x[36]-x[102]<=0) #= e67: =# - @constraint(m, x[1]>=0) #= e68: =# - @constraint(m, x[2]>=0) #= e69: =# - @constraint(m, x[3]>=0) #= e70: =# - @constraint(m, x[4]>=0) #= e71: =# - @constraint(m, x[5]>=0) #= e72: =# - @constraint(m, x[6]>=0) #= e73: =# - @constraint(m, x[7]>=0) #= e74: =# - @constraint(m, x[8]>=0) #= e75: =# - @constraint(m, x[9]>=0) #= e76: =# - @constraint(m, x[10]>=0) #= e77: =# - @constraint(m, x[11]>=0) #= e78: =# - @constraint(m, x[12]>=0) #= e79: =# - @constraint(m, x[13]>=0) #= e80: =# - @constraint(m, x[14]>=0) #= e81: =# - @constraint(m, x[15]>=0) #= e82: =# - @constraint(m, x[16]>=0) #= e83: =# - @constraint(m, x[17]>=0) #= e84: =# - @constraint(m, x[18]>=0) #= e85: =# - @constraint(m, x[19]>=0) #= e86: =# - @constraint(m, x[20]>=0) #= e87: =# - @constraint(m, x[21]>=0) #= e88: =# - @constraint(m, x[22]>=0) #= e89: =# - @constraint(m, x[23]>=0) #= e90: =# - @constraint(m, x[24]>=0) #= e91: =# - @constraint(m, x[25]>=0) #= e92: =# - @constraint(m, x[26]>=0) #= e93: =# - @constraint(m, x[27]>=0) #= e94: =# - @constraint(m, x[28]>=0) #= e95: =# - @constraint(m, x[29]>=0) #= e96: =# - @constraint(m, x[30]>=0) #= e97: =# - @constraint(m, x[31]>=0) #= e98: =# - @constraint(m, x[32]>=0) #= e99: =# - @constraint(m, x[33]>=0) #= e100: =# - @constraint(m, x[34]>=0) #= e101: =# - @constraint(m, x[35]>=0) #= e102: =# - @constraint(m, x[36]>=0) #= e103: =# - @constraint(m, x[73]<=1.5) #= e104: =# - @constraint(m, x[74]<=1.5) #= e105: =# - @constraint(m, x[75]<=1.5) #= e106: =# - @constraint(m, x[76]<=0.6) #= e107: =# - @constraint(m, x[77]<=0.6) #= e108: =# - @constraint(m, x[78]<=0.6) #= e109: =# - @constraint(m, x[85]<=1.1) #= e110: =# - @constraint(m, x[86]<=1.1) #= e111: =# - @constraint(m, x[87]<=1.1) #= e112: =# - @constraint(m, x[88]<=0.2) #= e113: =# - @constraint(m, x[89]<=0.2) #= e114: =# - @constraint(m, x[90]<=0.2) #= e115: =# - @constraint(m, x[73]<=1) #= e116: =# - @constraint(m, x[74]<=1) #= e117: =# - @constraint(m, x[75]<=1) #= e118: =# - @constraint(m, x[76]<=0.8) #= e119: =# - @constraint(m, x[77]<=0.8) #= e120: =# - @constraint(m, x[78]<=0.8) #= e121: =# - @constraint(m, x[85]<=1) #= e122: =# - @constraint(m, x[86]<=1) #= e123: =# - @constraint(m, x[87]<=1) #= e124: =# - @constraint(m, x[88]<=0.8) #= e125: =# - @constraint(m, x[89]<=0.8) #= e126: =# - @constraint(m, x[90]<=0.8) #= e127: =# - @constraint(m, -x[73]>=-1.3) #= e128: =# - @constraint(m, -x[74]>=-1.3) #= e129: =# - @constraint(m, -x[75]>=-1.3) #= e130: =# - @constraint(m, -x[76]>=-1.4) #= e131: =# - @constraint(m, -x[77]>=-1.4) #= e132: =# - @constraint(m, -x[78]>=-1.4) #= e133: =# - @constraint(m, -x[85]>=-1.7) #= e134: =# - @constraint(m, -x[86]>=-1.7) #= e135: =# - @constraint(m, -x[87]>=-1.7) #= e136: =# - @constraint(m, -x[88]>=-1.8) #= e137: =# - @constraint(m, -x[89]>=-1.8) #= e138: =# - @constraint(m, -x[90]>=-1.8) #= e139: =# - @constraint(m, -x[73]>=-1) #= e140: =# - @constraint(m, -x[74]>=-1) #= e141: =# - @constraint(m, -x[75]>=-1) #= e142: =# - @constraint(m, -x[76]>=-1.4) #= e143: =# - @constraint(m, -x[77]>=-1.4) #= e144: =# - @constraint(m, -x[78]>=-1.4) #= e145: =# - @constraint(m, -x[85]>=-1) #= e146: =# - @constraint(m, -x[86]>=-1) #= e147: =# - @constraint(m, -x[87]>=-1) #= e148: =# - @constraint(m, -x[88]>=-1.4) #= e149: =# - @constraint(m, -x[89]>=-1.4) #= e150: =# - @constraint(m, -x[90]>=-1.4) #= e151: =# - @constraint(m, -x[37]+x[95]<=0.9) #= e152: =# - @constraint(m, -x[38]+x[96]<=0.9) #= e153: =# - @constraint(m, -x[37]+x[98]<=0) #= e154: =# - @constraint(m, -x[38]+x[99]<=0) #= e155: =# - @constraint(m, -x[40]+x[101]<=0.9) #= e156: =# - @constraint(m, -x[41]+x[102]<=0.9) #= e157: =# - @constraint(m, -x[43]+x[95]<=0.6) #= e158: =# - @constraint(m, -x[44]+x[96]<=0.6) #= e159: =# - @constraint(m, -x[43]+x[98]<=0.4) #= e160: =# - @constraint(m, -x[44]+x[99]<=0.4) #= e161: =# - @constraint(m, -x[46]+x[101]<=0.6) #= e162: =# - @constraint(m, -x[47]+x[102]<=0.6) #= e163: =# - @constraint(m, -x[37]-x[95]>=-1.9) #= e164: =# - @constraint(m, -x[38]-x[96]>=-1.9) #= e165: =# - @constraint(m, -x[37]-x[98]>=-2) #= e166: =# - @constraint(m, -x[38]-x[99]>=-2) #= e167: =# - @constraint(m, -x[40]-x[101]>=-1.9) #= e168: =# - @constraint(m, -x[41]-x[102]>=-1.9) #= e169: =# - @constraint(m, -x[43]-x[95]>=-1.4) #= e170: =# - @constraint(m, -x[44]-x[96]>=-1.4) #= e171: =# - @constraint(m, -x[43]-x[98]>=-1.8) #= e172: =# - @constraint(m, -x[44]-x[99]>=-1.8) #= e173: =# - @constraint(m, -x[46]-x[101]>=-1.4) #= e174: =# - @constraint(m, -x[47]-x[102]>=-1.4) #= e175: =# - @constraint(m, x[94]<=1.1) #= e176: =# - @constraint(m, x[97]<=0.2) #= e177: =# - @constraint(m, x[100]<=1.6) #= e178: =# - @constraint(m, x[94]<=1.1) #= e179: =# - @constraint(m, x[97]<=0.9) #= e180: =# - @constraint(m, x[100]<=1.2) #= e181: =# - @constraint(m, -x[94]>=-1.7) #= e182: =# - @constraint(m, -x[97]>=-1.8) #= e183: =# - @constraint(m, -x[100]>=-1.2) #= e184: =# - @constraint(m, -x[94]>=-0.9) #= e185: =# - @constraint(m, -x[97]>=-1.3) #= e186: =# - @constraint(m, -x[100]>=-0.8) #= e187: =# - @constraint(m, x[67]+x[91]<=1) #= e188: =# - @constraint(m, x[68]+x[92]<=1) #= e189: =# - @constraint(m, x[69]+x[93]<=1) #= e190: =# - @constraint(m, x[67]+x[94]<=1) #= e191: =# - @constraint(m, x[68]+x[95]<=1) #= e192: =# - @constraint(m, x[69]+x[96]<=1) #= e193: =# - @constraint(m, x[67]+x[97]<=1) #= e194: =# - @constraint(m, x[68]+x[98]<=1) #= e195: =# - @constraint(m, x[69]+x[99]<=1) #= e196: =# - @constraint(m, x[79]+x[91]<=1) #= e197: =# - @constraint(m, x[80]+x[92]<=1) #= e198: =# - @constraint(m, x[81]+x[93]<=1) #= e199: =# - @constraint(m, x[79]+x[94]<=1) #= e200: =# - @constraint(m, x[80]+x[95]<=1) #= e201: =# - @constraint(m, x[81]+x[96]<=1) #= e202: =# - @constraint(m, x[79]+x[97]<=1) #= e203: =# - @constraint(m, x[80]+x[98]<=1) #= e204: =# - @constraint(m, x[81]+x[99]<=1) #= e205: =# - @constraint(m, x[70]+x[100]<=1) #= e206: =# - @constraint(m, x[71]+x[101]<=1) #= e207: =# - @constraint(m, x[72]+x[102]<=1) #= e208: =# - @constraint(m, x[82]+x[100]<=1) #= e209: =# - @constraint(m, x[83]+x[101]<=1) #= e210: =# - @constraint(m, x[84]+x[102]<=1) #= e211: =# - @constraint(m, x[91]+x[100]<=1) #= e212: =# - @constraint(m, x[92]+x[101]<=1) #= e213: =# - @constraint(m, x[93]+x[102]<=1) #= e214: =# + @constraint(m, x[1] + x[4] + x[7] + x[10] + x[49] == 1) #= e2: =# + @constraint(m, x[13] + x[16] + x[19] + x[22] + x[52] == 1.1) #= e3: =# + @constraint(m, -x[1] - x[13] + x[25] + x[28] + x[31] + x[55] == 0.2) #= e4: =# + @constraint(m, -x[4] - x[16] - x[25] + x[34] + x[58] == 0.1) #= e5: =# + @constraint(m, -x[7] - x[19] - x[28] - x[34] + x[61] == 1.55) #= e6: =# + @constraint(m, -x[10] - x[22] - x[31] + x[64] == 0.49) #= e7: =# + @constraint(m, x[2] + x[5] + x[8] + x[11] - x[49] + x[50] == 1) #= e12: =# + @constraint(m, x[3] + x[6] + x[9] + x[12] - x[50] + x[51] == 0) #= e13: =# + @constraint(m, x[14] + x[17] + x[20] + x[23] - x[52] + x[53] == 0.1) #= e14: =# + @constraint(m, x[15] + x[18] + x[21] + x[24] - x[53] + x[54] == 0.9) #= e15: =# + @constraint(m, -x[2] - x[14] + x[26] + x[29] + x[32] - x[55] + x[56] == 0) #= e16: =# + @constraint(m, -x[3] - x[15] + x[27] + x[30] + x[33] - x[56] + x[57] == 0) #= e17: =# + @constraint(m, -x[5] - x[17] - x[26] + x[35] - x[58] + x[59] == 0) #= e18: =# + @constraint(m, -x[6] - x[18] - x[27] + x[36] - x[59] + x[60] == 0) #= e19: =# + @constraint(m, -x[8] - x[20] - x[29] - x[35] - x[61] + x[62] == -0.81) #= e20: =# + @constraint(m, -x[9] - x[21] - x[30] - x[36] - x[62] + x[63] == -0.88) #= e21: =# + @constraint(m, -x[11] - x[23] - x[32] - x[64] + x[65] == -0.14) #= e22: =# + @constraint(m, -x[12] - x[24] - x[33] - x[65] + x[66] == -0.1) #= e23: =# + @constraint(m, x[1] - x[67] <= 0) #= e32: =# + @constraint(m, x[2] - x[68] <= 0) #= e33: =# + @constraint(m, x[3] - x[69] <= 0) #= e34: =# + @constraint(m, x[4] - x[70] <= 0) #= e35: =# + @constraint(m, x[5] - x[71] <= 0) #= e36: =# + @constraint(m, x[6] - x[72] <= 0) #= e37: =# + @constraint(m, x[7] - x[73] <= 0) #= e38: =# + @constraint(m, x[8] - x[74] <= 0) #= e39: =# + @constraint(m, x[9] - x[75] <= 0) #= e40: =# + @constraint(m, x[10] - x[76] <= 0) #= e41: =# + @constraint(m, x[11] - x[77] <= 0) #= e42: =# + @constraint(m, x[12] - x[78] <= 0) #= e43: =# + @constraint(m, x[13] - x[79] <= 0) #= e44: =# + @constraint(m, x[14] - x[80] <= 0) #= e45: =# + @constraint(m, x[15] - x[81] <= 0) #= e46: =# + @constraint(m, x[16] - x[82] <= 0) #= e47: =# + @constraint(m, x[17] - x[83] <= 0) #= e48: =# + @constraint(m, x[18] - x[84] <= 0) #= e49: =# + @constraint(m, x[19] - x[85] <= 0) #= e50: =# + @constraint(m, x[20] - x[86] <= 0) #= e51: =# + @constraint(m, x[21] - x[87] <= 0) #= e52: =# + @constraint(m, x[22] - x[88] <= 0) #= e53: =# + @constraint(m, x[23] - x[89] <= 0) #= e54: =# + @constraint(m, x[24] - x[90] <= 0) #= e55: =# + @constraint(m, x[25] - x[91] <= 0) #= e56: =# + @constraint(m, x[26] - x[92] <= 0) #= e57: =# + @constraint(m, x[27] - x[93] <= 0) #= e58: =# + @constraint(m, x[28] - x[94] <= 0) #= e59: =# + @constraint(m, x[29] - x[95] <= 0) #= e60: =# + @constraint(m, x[30] - x[96] <= 0) #= e61: =# + @constraint(m, x[31] - x[97] <= 0) #= e62: =# + @constraint(m, x[32] - x[98] <= 0) #= e63: =# + @constraint(m, x[33] - x[99] <= 0) #= e64: =# + @constraint(m, x[34] - x[100] <= 0) #= e65: =# + @constraint(m, x[35] - x[101] <= 0) #= e66: =# + @constraint(m, x[36] - x[102] <= 0) #= e67: =# + @constraint(m, x[1] >= 0) #= e68: =# + @constraint(m, x[2] >= 0) #= e69: =# + @constraint(m, x[3] >= 0) #= e70: =# + @constraint(m, x[4] >= 0) #= e71: =# + @constraint(m, x[5] >= 0) #= e72: =# + @constraint(m, x[6] >= 0) #= e73: =# + @constraint(m, x[7] >= 0) #= e74: =# + @constraint(m, x[8] >= 0) #= e75: =# + @constraint(m, x[9] >= 0) #= e76: =# + @constraint(m, x[10] >= 0) #= e77: =# + @constraint(m, x[11] >= 0) #= e78: =# + @constraint(m, x[12] >= 0) #= e79: =# + @constraint(m, x[13] >= 0) #= e80: =# + @constraint(m, x[14] >= 0) #= e81: =# + @constraint(m, x[15] >= 0) #= e82: =# + @constraint(m, x[16] >= 0) #= e83: =# + @constraint(m, x[17] >= 0) #= e84: =# + @constraint(m, x[18] >= 0) #= e85: =# + @constraint(m, x[19] >= 0) #= e86: =# + @constraint(m, x[20] >= 0) #= e87: =# + @constraint(m, x[21] >= 0) #= e88: =# + @constraint(m, x[22] >= 0) #= e89: =# + @constraint(m, x[23] >= 0) #= e90: =# + @constraint(m, x[24] >= 0) #= e91: =# + @constraint(m, x[25] >= 0) #= e92: =# + @constraint(m, x[26] >= 0) #= e93: =# + @constraint(m, x[27] >= 0) #= e94: =# + @constraint(m, x[28] >= 0) #= e95: =# + @constraint(m, x[29] >= 0) #= e96: =# + @constraint(m, x[30] >= 0) #= e97: =# + @constraint(m, x[31] >= 0) #= e98: =# + @constraint(m, x[32] >= 0) #= e99: =# + @constraint(m, x[33] >= 0) #= e100: =# + @constraint(m, x[34] >= 0) #= e101: =# + @constraint(m, x[35] >= 0) #= e102: =# + @constraint(m, x[36] >= 0) #= e103: =# + @constraint(m, x[73] <= 1.5) #= e104: =# + @constraint(m, x[74] <= 1.5) #= e105: =# + @constraint(m, x[75] <= 1.5) #= e106: =# + @constraint(m, x[76] <= 0.6) #= e107: =# + @constraint(m, x[77] <= 0.6) #= e108: =# + @constraint(m, x[78] <= 0.6) #= e109: =# + @constraint(m, x[85] <= 1.1) #= e110: =# + @constraint(m, x[86] <= 1.1) #= e111: =# + @constraint(m, x[87] <= 1.1) #= e112: =# + @constraint(m, x[88] <= 0.2) #= e113: =# + @constraint(m, x[89] <= 0.2) #= e114: =# + @constraint(m, x[90] <= 0.2) #= e115: =# + @constraint(m, x[73] <= 1) #= e116: =# + @constraint(m, x[74] <= 1) #= e117: =# + @constraint(m, x[75] <= 1) #= e118: =# + @constraint(m, x[76] <= 0.8) #= e119: =# + @constraint(m, x[77] <= 0.8) #= e120: =# + @constraint(m, x[78] <= 0.8) #= e121: =# + @constraint(m, x[85] <= 1) #= e122: =# + @constraint(m, x[86] <= 1) #= e123: =# + @constraint(m, x[87] <= 1) #= e124: =# + @constraint(m, x[88] <= 0.8) #= e125: =# + @constraint(m, x[89] <= 0.8) #= e126: =# + @constraint(m, x[90] <= 0.8) #= e127: =# + @constraint(m, -x[73] >= -1.3) #= e128: =# + @constraint(m, -x[74] >= -1.3) #= e129: =# + @constraint(m, -x[75] >= -1.3) #= e130: =# + @constraint(m, -x[76] >= -1.4) #= e131: =# + @constraint(m, -x[77] >= -1.4) #= e132: =# + @constraint(m, -x[78] >= -1.4) #= e133: =# + @constraint(m, -x[85] >= -1.7) #= e134: =# + @constraint(m, -x[86] >= -1.7) #= e135: =# + @constraint(m, -x[87] >= -1.7) #= e136: =# + @constraint(m, -x[88] >= -1.8) #= e137: =# + @constraint(m, -x[89] >= -1.8) #= e138: =# + @constraint(m, -x[90] >= -1.8) #= e139: =# + @constraint(m, -x[73] >= -1) #= e140: =# + @constraint(m, -x[74] >= -1) #= e141: =# + @constraint(m, -x[75] >= -1) #= e142: =# + @constraint(m, -x[76] >= -1.4) #= e143: =# + @constraint(m, -x[77] >= -1.4) #= e144: =# + @constraint(m, -x[78] >= -1.4) #= e145: =# + @constraint(m, -x[85] >= -1) #= e146: =# + @constraint(m, -x[86] >= -1) #= e147: =# + @constraint(m, -x[87] >= -1) #= e148: =# + @constraint(m, -x[88] >= -1.4) #= e149: =# + @constraint(m, -x[89] >= -1.4) #= e150: =# + @constraint(m, -x[90] >= -1.4) #= e151: =# + @constraint(m, -x[37] + x[95] <= 0.9) #= e152: =# + @constraint(m, -x[38] + x[96] <= 0.9) #= e153: =# + @constraint(m, -x[37] + x[98] <= 0) #= e154: =# + @constraint(m, -x[38] + x[99] <= 0) #= e155: =# + @constraint(m, -x[40] + x[101] <= 0.9) #= e156: =# + @constraint(m, -x[41] + x[102] <= 0.9) #= e157: =# + @constraint(m, -x[43] + x[95] <= 0.6) #= e158: =# + @constraint(m, -x[44] + x[96] <= 0.6) #= e159: =# + @constraint(m, -x[43] + x[98] <= 0.4) #= e160: =# + @constraint(m, -x[44] + x[99] <= 0.4) #= e161: =# + @constraint(m, -x[46] + x[101] <= 0.6) #= e162: =# + @constraint(m, -x[47] + x[102] <= 0.6) #= e163: =# + @constraint(m, -x[37] - x[95] >= -1.9) #= e164: =# + @constraint(m, -x[38] - x[96] >= -1.9) #= e165: =# + @constraint(m, -x[37] - x[98] >= -2) #= e166: =# + @constraint(m, -x[38] - x[99] >= -2) #= e167: =# + @constraint(m, -x[40] - x[101] >= -1.9) #= e168: =# + @constraint(m, -x[41] - x[102] >= -1.9) #= e169: =# + @constraint(m, -x[43] - x[95] >= -1.4) #= e170: =# + @constraint(m, -x[44] - x[96] >= -1.4) #= e171: =# + @constraint(m, -x[43] - x[98] >= -1.8) #= e172: =# + @constraint(m, -x[44] - x[99] >= -1.8) #= e173: =# + @constraint(m, -x[46] - x[101] >= -1.4) #= e174: =# + @constraint(m, -x[47] - x[102] >= -1.4) #= e175: =# + @constraint(m, x[94] <= 1.1) #= e176: =# + @constraint(m, x[97] <= 0.2) #= e177: =# + @constraint(m, x[100] <= 1.6) #= e178: =# + @constraint(m, x[94] <= 1.1) #= e179: =# + @constraint(m, x[97] <= 0.9) #= e180: =# + @constraint(m, x[100] <= 1.2) #= e181: =# + @constraint(m, -x[94] >= -1.7) #= e182: =# + @constraint(m, -x[97] >= -1.8) #= e183: =# + @constraint(m, -x[100] >= -1.2) #= e184: =# + @constraint(m, -x[94] >= -0.9) #= e185: =# + @constraint(m, -x[97] >= -1.3) #= e186: =# + @constraint(m, -x[100] >= -0.8) #= e187: =# + @constraint(m, x[67] + x[91] <= 1) #= e188: =# + @constraint(m, x[68] + x[92] <= 1) #= e189: =# + @constraint(m, x[69] + x[93] <= 1) #= e190: =# + @constraint(m, x[67] + x[94] <= 1) #= e191: =# + @constraint(m, x[68] + x[95] <= 1) #= e192: =# + @constraint(m, x[69] + x[96] <= 1) #= e193: =# + @constraint(m, x[67] + x[97] <= 1) #= e194: =# + @constraint(m, x[68] + x[98] <= 1) #= e195: =# + @constraint(m, x[69] + x[99] <= 1) #= e196: =# + @constraint(m, x[79] + x[91] <= 1) #= e197: =# + @constraint(m, x[80] + x[92] <= 1) #= e198: =# + @constraint(m, x[81] + x[93] <= 1) #= e199: =# + @constraint(m, x[79] + x[94] <= 1) #= e200: =# + @constraint(m, x[80] + x[95] <= 1) #= e201: =# + @constraint(m, x[81] + x[96] <= 1) #= e202: =# + @constraint(m, x[79] + x[97] <= 1) #= e203: =# + @constraint(m, x[80] + x[98] <= 1) #= e204: =# + @constraint(m, x[81] + x[99] <= 1) #= e205: =# + @constraint(m, x[70] + x[100] <= 1) #= e206: =# + @constraint(m, x[71] + x[101] <= 1) #= e207: =# + @constraint(m, x[72] + x[102] <= 1) #= e208: =# + @constraint(m, x[82] + x[100] <= 1) #= e209: =# + @constraint(m, x[83] + x[101] <= 1) #= e210: =# + @constraint(m, x[84] + x[102] <= 1) #= e211: =# + @constraint(m, x[91] + x[100] <= 1) #= e212: =# + @constraint(m, x[92] + x[101] <= 1) #= e213: =# + @constraint(m, x[93] + x[102] <= 1) #= e214: =# return m end -function blend029_gl(;solver = nothing) - +function blend029_gl(; solver = nothing) m = Model(solver) @variable(m, x[1:102]) - for i=67:102 - JuMP.set_binary(x[i]) + for i in 67:102 + JuMP.set_binary(x[i]) end - for i=1:48 - set_lower_bound(x[i], 0) - set_upper_bound(x[i], 1) + for i in 1:48 + set_lower_bound(x[i], 0) + set_upper_bound(x[i], 1) end - for i=49:66 - set_lower_bound(x[i], 0) - set_upper_bound(x[i], 2) + for i in 49:66 + set_lower_bound(x[i], 0) + set_upper_bound(x[i], 2) end - @objective(m, Max, - 1.74*x[1] - 1.74*x[2] - 1.74*x[3] - 1.45*x[4] - 1.45*x[5] - 1.45*x[6] + 7.38*x[7] + 7.38*x[8] + 7.38*x[9] + 5.6*x[10] + 5.6*x[11] + 5.6*x[12] - 1.7*x[13] - 1.7*x[14] - 1.7*x[15] - 1.18*x[16] - 1.18*x[17] - 1.18*x[18] + 7.21*x[19] + 7.21*x[20] + 7.21*x[21] + 5.45*x[22] + 5.45*x[23] + 5.45*x[24] - 0.3*x[25] - 0.3*x[26] - 0.3*x[27] + 7.71*x[28] + 7.71*x[29] + 7.71*x[30] + 6.28*x[31] + 6.28*x[32] + 6.28*x[33] + 7.74*x[34] + 7.74*x[35] + 7.74*x[36] - 0.84*x[67] - 0.84*x[68] - 0.84*x[69] - 0.05*x[70] - 0.05*x[71] - 0.05*x[72] - 0.94*x[73] - 0.94*x[74] - 0.94*x[75] - 0.81*x[76] - 0.81*x[77] - 0.81*x[78] - 0.79*x[79] - 0.79*x[80] - 0.79*x[81] - 0.05*x[82] - 0.05*x[83] - 0.05*x[84] - 0.65*x[85] - 0.65*x[86] - 0.65*x[87] - 0.97*x[88] - 0.97*x[89] - 0.97*x[90] - 0.57*x[91] - 0.57*x[92] - 0.57*x[93] - 0.26*x[94] - 0.26*x[95] - 0.26*x[96] - 0.45*x[97] - 0.45*x[98] - 0.45*x[99] - 0.1*x[100] - 0.1*x[101] - 0.1*x[102]) + @objective( + m, + Max, + -1.74 * x[1] - 1.74 * x[2] - 1.74 * x[3] - 1.45 * x[4] - 1.45 * x[5] - + 1.45 * x[6] + + 7.38 * x[7] + + 7.38 * x[8] + + 7.38 * x[9] + + 5.6 * x[10] + + 5.6 * x[11] + + 5.6 * x[12] - 1.7 * x[13] - 1.7 * x[14] - 1.7 * x[15] - 1.18 * x[16] - + 1.18 * x[17] - 1.18 * x[18] + + 7.21 * x[19] + + 7.21 * x[20] + + 7.21 * x[21] + + 5.45 * x[22] + + 5.45 * x[23] + + 5.45 * x[24] - 0.3 * x[25] - 0.3 * x[26] - 0.3 * x[27] + + 7.71 * x[28] + + 7.71 * x[29] + + 7.71 * x[30] + + 6.28 * x[31] + + 6.28 * x[32] + + 6.28 * x[33] + + 7.74 * x[34] + + 7.74 * x[35] + + 7.74 * x[36] - 0.84 * x[67] - 0.84 * x[68] - 0.84 * x[69] - 0.05 * x[70] - + 0.05 * x[71] - 0.05 * x[72] - 0.94 * x[73] - 0.94 * x[74] - 0.94 * x[75] - + 0.81 * x[76] - 0.81 * x[77] - 0.81 * x[78] - 0.79 * x[79] - 0.79 * x[80] - + 0.79 * x[81] - 0.05 * x[82] - 0.05 * x[83] - 0.05 * x[84] - 0.65 * x[85] - + 0.65 * x[86] - 0.65 * x[87] - 0.97 * x[88] - 0.97 * x[89] - 0.97 * x[90] - + 0.57 * x[91] - 0.57 * x[92] - 0.57 * x[93] - 0.26 * x[94] - 0.26 * x[95] - + 0.26 * x[96] - 0.45 * x[97] - 0.45 * x[98] - 0.45 * x[99] - 0.1 * x[100] - + 0.1 * x[101] - 0.1 * x[102] + ) - @NLconstraint(m, x[37]*x[55]-0.6*x[1]-0.2*x[13]+0.2*x[25]+0.2*x[28]+0.2*x[31] >=0.04) #= e8: =# - @NLconstraint(m, x[40]*x[58]-0.6*x[4]-0.2*x[16]-0.2*x[25]+0.7*x[34] >=0.07) #= e9: =# - @NLconstraint(m, x[43]*x[55]-0.4*x[1]-0.4*x[13]+0.5*x[25]+0.5*x[28]+0.5*x[31] >=0.1) #= e10: =# - @NLconstraint(m, x[46]*x[58]-0.4*x[4]-0.4*x[16]-0.5*x[25]+0.6*x[34] >=0.06) #= e11: =# - @NLconstraint(m, x[38]*x[56]-(x[37]*x[55]-(x[37]*x[26]+x[37]*x[29]+x[37]*x[32]))-0.6*x[2]-0.2*x[14] >=0) #= e24: =# - @NLconstraint(m, x[39]*x[57]-(x[38]*x[56]-(x[38]*x[27]+x[38]*x[30]+x[38]*x[33]))-0.6*x[3]-0.2*x[15] >=0) #= e25: =# - @NLconstraint(m, x[41]*x[59]-(x[40]*x[58]+x[37]*x[26]-x[40]*x[35])-0.6*x[5]-0.2*x[17] >=0) #= e26: =# - @NLconstraint(m, x[42]*x[60]-(x[41]*x[59]+x[38]*x[27]-x[41]*x[36])-0.6*x[6]-0.2*x[18] >=0) #= e27: =# - @NLconstraint(m, x[44]*x[56]-(x[43]*x[55]-(x[43]*x[26]+x[43]*x[29]+x[43]*x[32]))-0.4*x[2]-0.4*x[14] >=0) #= e28: =# - @NLconstraint(m, x[45]*x[57]-(x[44]*x[56]-(x[44]*x[27]+x[44]*x[30]+x[44]*x[33]))-0.4*x[3]-0.4*x[15] >=0) #= e29: =# - @NLconstraint(m, x[47]*x[59]-(x[46]*x[58]+x[43]*x[26]-x[46]*x[35])-0.4*x[5]-0.4*x[17] >=0) #= e30: =# - @NLconstraint(m, x[48]*x[60]-(x[47]*x[59]+x[44]*x[27]-x[47]*x[36])-0.4*x[6]-0.4*x[18] >=0) #= e31: =# + @NLconstraint( + m, + x[37] * x[55] - 0.6 * x[1] - 0.2 * x[13] + + 0.2 * x[25] + + 0.2 * x[28] + + 0.2 * x[31] >= 0.04 + ) #= e8: =# + @NLconstraint( + m, + x[40] * x[58] - 0.6 * x[4] - 0.2 * x[16] - 0.2 * x[25] + 0.7 * x[34] >= 0.07 + ) #= e9: =# + @NLconstraint( + m, + x[43] * x[55] - 0.4 * x[1] - 0.4 * x[13] + + 0.5 * x[25] + + 0.5 * x[28] + + 0.5 * x[31] >= 0.1 + ) #= e10: =# + @NLconstraint( + m, + x[46] * x[58] - 0.4 * x[4] - 0.4 * x[16] - 0.5 * x[25] + 0.6 * x[34] >= 0.06 + ) #= e11: =# + @NLconstraint( + m, + x[38] * x[56] - + (x[37] * x[55] - (x[37] * x[26] + x[37] * x[29] + x[37] * x[32])) - 0.6 * x[2] - + 0.2 * x[14] >= 0 + ) #= e24: =# + @NLconstraint( + m, + x[39] * x[57] - + (x[38] * x[56] - (x[38] * x[27] + x[38] * x[30] + x[38] * x[33])) - 0.6 * x[3] - + 0.2 * x[15] >= 0 + ) #= e25: =# + @NLconstraint( + m, + x[41] * x[59] - (x[40] * x[58] + x[37] * x[26] - x[40] * x[35]) - 0.6 * x[5] - + 0.2 * x[17] >= 0 + ) #= e26: =# + @NLconstraint( + m, + x[42] * x[60] - (x[41] * x[59] + x[38] * x[27] - x[41] * x[36]) - 0.6 * x[6] - + 0.2 * x[18] >= 0 + ) #= e27: =# + @NLconstraint( + m, + x[44] * x[56] - + (x[43] * x[55] - (x[43] * x[26] + x[43] * x[29] + x[43] * x[32])) - 0.4 * x[2] - + 0.4 * x[14] >= 0 + ) #= e28: =# + @NLconstraint( + m, + x[45] * x[57] - + (x[44] * x[56] - (x[44] * x[27] + x[44] * x[30] + x[44] * x[33])) - 0.4 * x[3] - + 0.4 * x[15] >= 0 + ) #= e29: =# + @NLconstraint( + m, + x[47] * x[59] - (x[46] * x[58] + x[43] * x[26] - x[46] * x[35]) - 0.4 * x[5] - + 0.4 * x[17] >= 0 + ) #= e30: =# + @NLconstraint( + m, + x[48] * x[60] - (x[47] * x[59] + x[44] * x[27] - x[47] * x[36]) - 0.4 * x[6] - + 0.4 * x[18] >= 0 + ) #= e31: =# - @NLconstraint(m, x[37]*x[55]-0.6*x[1]-0.2*x[13]+0.2*x[25]+0.2*x[28]+0.2*x[31] <=0.04) #= e8: =# - @NLconstraint(m, x[40]*x[58]-0.6*x[4]-0.2*x[16]-0.2*x[25]+0.7*x[34] <=0.07) #= e9: =# - @NLconstraint(m, x[43]*x[55]-0.4*x[1]-0.4*x[13]+0.5*x[25]+0.5*x[28]+0.5*x[31] <=0.1) #= e10: =# - @NLconstraint(m, x[46]*x[58]-0.4*x[4]-0.4*x[16]-0.5*x[25]+0.6*x[34] <=0.06) #= e11: =# - @NLconstraint(m, x[38]*x[56]-(x[37]*x[55]-(x[37]*x[26]+x[37]*x[29]+x[37]*x[32]))-0.6*x[2]-0.2*x[14] <=0) #= e24: =# - @NLconstraint(m, x[39]*x[57]-(x[38]*x[56]-(x[38]*x[27]+x[38]*x[30]+x[38]*x[33]))-0.6*x[3]-0.2*x[15] <=0) #= e25: =# - @NLconstraint(m, x[41]*x[59]-(x[40]*x[58]+x[37]*x[26]-x[40]*x[35])-0.6*x[5]-0.2*x[17] <=0) #= e26: =# - @NLconstraint(m, x[42]*x[60]-(x[41]*x[59]+x[38]*x[27]-x[41]*x[36])-0.6*x[6]-0.2*x[18] <=0) #= e27: =# - @NLconstraint(m, x[44]*x[56]-(x[43]*x[55]-(x[43]*x[26]+x[43]*x[29]+x[43]*x[32]))-0.4*x[2]-0.4*x[14] <=0) #= e28: =# - @NLconstraint(m, x[45]*x[57]-(x[44]*x[56]-(x[44]*x[27]+x[44]*x[30]+x[44]*x[33]))-0.4*x[3]-0.4*x[15] <=0) #= e29: =# - @NLconstraint(m, x[47]*x[59]-(x[46]*x[58]+x[43]*x[26]-x[46]*x[35])-0.4*x[5]-0.4*x[17] <=0) #= e30: =# - @NLconstraint(m, x[48]*x[60]-(x[47]*x[59]+x[44]*x[27]-x[47]*x[36])-0.4*x[6]-0.4*x[18] <=0) #= e31: =# + @NLconstraint( + m, + x[37] * x[55] - 0.6 * x[1] - 0.2 * x[13] + + 0.2 * x[25] + + 0.2 * x[28] + + 0.2 * x[31] <= 0.04 + ) #= e8: =# + @NLconstraint( + m, + x[40] * x[58] - 0.6 * x[4] - 0.2 * x[16] - 0.2 * x[25] + 0.7 * x[34] <= 0.07 + ) #= e9: =# + @NLconstraint( + m, + x[43] * x[55] - 0.4 * x[1] - 0.4 * x[13] + + 0.5 * x[25] + + 0.5 * x[28] + + 0.5 * x[31] <= 0.1 + ) #= e10: =# + @NLconstraint( + m, + x[46] * x[58] - 0.4 * x[4] - 0.4 * x[16] - 0.5 * x[25] + 0.6 * x[34] <= 0.06 + ) #= e11: =# + @NLconstraint( + m, + x[38] * x[56] - + (x[37] * x[55] - (x[37] * x[26] + x[37] * x[29] + x[37] * x[32])) - 0.6 * x[2] - + 0.2 * x[14] <= 0 + ) #= e24: =# + @NLconstraint( + m, + x[39] * x[57] - + (x[38] * x[56] - (x[38] * x[27] + x[38] * x[30] + x[38] * x[33])) - 0.6 * x[3] - + 0.2 * x[15] <= 0 + ) #= e25: =# + @NLconstraint( + m, + x[41] * x[59] - (x[40] * x[58] + x[37] * x[26] - x[40] * x[35]) - 0.6 * x[5] - + 0.2 * x[17] <= 0 + ) #= e26: =# + @NLconstraint( + m, + x[42] * x[60] - (x[41] * x[59] + x[38] * x[27] - x[41] * x[36]) - 0.6 * x[6] - + 0.2 * x[18] <= 0 + ) #= e27: =# + @NLconstraint( + m, + x[44] * x[56] - + (x[43] * x[55] - (x[43] * x[26] + x[43] * x[29] + x[43] * x[32])) - 0.4 * x[2] - + 0.4 * x[14] <= 0 + ) #= e28: =# + @NLconstraint( + m, + x[45] * x[57] - + (x[44] * x[56] - (x[44] * x[27] + x[44] * x[30] + x[44] * x[33])) - 0.4 * x[3] - + 0.4 * x[15] <= 0 + ) #= e29: =# + @NLconstraint( + m, + x[47] * x[59] - (x[46] * x[58] + x[43] * x[26] - x[46] * x[35]) - 0.4 * x[5] - + 0.4 * x[17] <= 0 + ) #= e30: =# + @NLconstraint( + m, + x[48] * x[60] - (x[47] * x[59] + x[44] * x[27] - x[47] * x[36]) - 0.4 * x[6] - + 0.4 * x[18] <= 0 + ) #= e31: =# - warmstarter = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.53351, 0.60649, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.2, 0.2, 0.2, 0.7, 0.7, 0.7, 0.5, 0.5, 0.5, 0.6, 0.6, 0.6, 1.0, 2.0, 1.0, 1.1, 0.66649, 0.96, 0.2, 0.2, 0.2, 0.1, 0.1, 0.1, 1.55, 1.27351, 2.0, 0.49, 0.35, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] + warmstarter = [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.53351, + 0.60649, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.2, + 0.2, + 0.2, + 0.7, + 0.7, + 0.7, + 0.5, + 0.5, + 0.5, + 0.6, + 0.6, + 0.6, + 1.0, + 2.0, + 1.0, + 1.1, + 0.66649, + 0.96, + 0.2, + 0.2, + 0.2, + 0.1, + 0.1, + 0.1, + 1.55, + 1.27351, + 2.0, + 0.49, + 0.35, + 0.25, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + ] for i in 1:102 - set_start_value(x[i], warmstarter[i]) + set_start_value(x[i], warmstarter[i]) end - @constraint(m, x[1]+x[4]+x[7]+x[10]+x[49] ==1) #= e2: =# - @constraint(m, x[13]+x[16]+x[19]+x[22]+x[52] ==1.1) #= e3: =# - @constraint(m, -x[1]-x[13]+x[25]+x[28]+x[31]+x[55] ==0.2) #= e4: =# - @constraint(m, -x[4]-x[16]-x[25]+x[34]+x[58] ==0.1) #= e5: =# - @constraint(m, -x[7]-x[19]-x[28]-x[34]+x[61] ==1.55) #= e6: =# - @constraint(m, -x[10]-x[22]-x[31]+x[64] ==0.49) #= e7: =# - @constraint(m, x[2]+x[5]+x[8]+x[11]-x[49]+x[50] ==1) #= e12: =# - @constraint(m, x[3]+x[6]+x[9]+x[12]-x[50]+x[51] ==0) #= e13: =# - @constraint(m, x[14]+x[17]+x[20]+x[23]-x[52]+x[53] ==0.1) #= e14: =# - @constraint(m, x[15]+x[18]+x[21]+x[24]-x[53]+x[54] ==0.9) #= e15: =# - @constraint(m, -x[2]-x[14]+x[26]+x[29]+x[32]-x[55]+x[56] ==0) #= e16: =# - @constraint(m, -x[3]-x[15]+x[27]+x[30]+x[33]-x[56]+x[57] ==0) #= e17: =# - @constraint(m, -x[5]-x[17]-x[26]+x[35]-x[58]+x[59] ==0) #= e18: =# - @constraint(m, -x[6]-x[18]-x[27]+x[36]-x[59]+x[60] ==0) #= e19: =# - @constraint(m, -x[8]-x[20]-x[29]-x[35]-x[61]+x[62] ==-0.81) #= e20: =# - @constraint(m, -x[9]-x[21]-x[30]-x[36]-x[62]+x[63] ==-0.88) #= e21: =# - @constraint(m, -x[11]-x[23]-x[32]-x[64]+x[65] ==-0.14) #= e22: =# - @constraint(m, -x[12]-x[24]-x[33]-x[65]+x[66] ==-0.1) #= e23: =# - @constraint(m, x[1]-x[67]<=0) #= e32: =# - @constraint(m, x[2]-x[68]<=0) #= e33: =# - @constraint(m, x[3]-x[69]<=0) #= e34: =# - @constraint(m, x[4]-x[70]<=0) #= e35: =# - @constraint(m, x[5]-x[71]<=0) #= e36: =# - @constraint(m, x[6]-x[72]<=0) #= e37: =# - @constraint(m, x[7]-x[73]<=0) #= e38: =# - @constraint(m, x[8]-x[74]<=0) #= e39: =# - @constraint(m, x[9]-x[75]<=0) #= e40: =# - @constraint(m, x[10]-x[76]<=0) #= e41: =# - @constraint(m, x[11]-x[77]<=0) #= e42: =# - @constraint(m, x[12]-x[78]<=0) #= e43: =# - @constraint(m, x[13]-x[79]<=0) #= e44: =# - @constraint(m, x[14]-x[80]<=0) #= e45: =# - @constraint(m, x[15]-x[81]<=0) #= e46: =# - @constraint(m, x[16]-x[82]<=0) #= e47: =# - @constraint(m, x[17]-x[83]<=0) #= e48: =# - @constraint(m, x[18]-x[84]<=0) #= e49: =# - @constraint(m, x[19]-x[85]<=0) #= e50: =# - @constraint(m, x[20]-x[86]<=0) #= e51: =# - @constraint(m, x[21]-x[87]<=0) #= e52: =# - @constraint(m, x[22]-x[88]<=0) #= e53: =# - @constraint(m, x[23]-x[89]<=0) #= e54: =# - @constraint(m, x[24]-x[90]<=0) #= e55: =# - @constraint(m, x[25]-x[91]<=0) #= e56: =# - @constraint(m, x[26]-x[92]<=0) #= e57: =# - @constraint(m, x[27]-x[93]<=0) #= e58: =# - @constraint(m, x[28]-x[94]<=0) #= e59: =# - @constraint(m, x[29]-x[95]<=0) #= e60: =# - @constraint(m, x[30]-x[96]<=0) #= e61: =# - @constraint(m, x[31]-x[97]<=0) #= e62: =# - @constraint(m, x[32]-x[98]<=0) #= e63: =# - @constraint(m, x[33]-x[99]<=0) #= e64: =# - @constraint(m, x[34]-x[100]<=0) #= e65: =# - @constraint(m, x[35]-x[101]<=0) #= e66: =# - @constraint(m, x[36]-x[102]<=0) #= e67: =# - @constraint(m, x[1]>=0) #= e68: =# - @constraint(m, x[2]>=0) #= e69: =# - @constraint(m, x[3]>=0) #= e70: =# - @constraint(m, x[4]>=0) #= e71: =# - @constraint(m, x[5]>=0) #= e72: =# - @constraint(m, x[6]>=0) #= e73: =# - @constraint(m, x[7]>=0) #= e74: =# - @constraint(m, x[8]>=0) #= e75: =# - @constraint(m, x[9]>=0) #= e76: =# - @constraint(m, x[10]>=0) #= e77: =# - @constraint(m, x[11]>=0) #= e78: =# - @constraint(m, x[12]>=0) #= e79: =# - @constraint(m, x[13]>=0) #= e80: =# - @constraint(m, x[14]>=0) #= e81: =# - @constraint(m, x[15]>=0) #= e82: =# - @constraint(m, x[16]>=0) #= e83: =# - @constraint(m, x[17]>=0) #= e84: =# - @constraint(m, x[18]>=0) #= e85: =# - @constraint(m, x[19]>=0) #= e86: =# - @constraint(m, x[20]>=0) #= e87: =# - @constraint(m, x[21]>=0) #= e88: =# - @constraint(m, x[22]>=0) #= e89: =# - @constraint(m, x[23]>=0) #= e90: =# - @constraint(m, x[24]>=0) #= e91: =# - @constraint(m, x[25]>=0) #= e92: =# - @constraint(m, x[26]>=0) #= e93: =# - @constraint(m, x[27]>=0) #= e94: =# - @constraint(m, x[28]>=0) #= e95: =# - @constraint(m, x[29]>=0) #= e96: =# - @constraint(m, x[30]>=0) #= e97: =# - @constraint(m, x[31]>=0) #= e98: =# - @constraint(m, x[32]>=0) #= e99: =# - @constraint(m, x[33]>=0) #= e100: =# - @constraint(m, x[34]>=0) #= e101: =# - @constraint(m, x[35]>=0) #= e102: =# - @constraint(m, x[36]>=0) #= e103: =# - @constraint(m, x[73]<=1.5) #= e104: =# - @constraint(m, x[74]<=1.5) #= e105: =# - @constraint(m, x[75]<=1.5) #= e106: =# - @constraint(m, x[76]<=0.6) #= e107: =# - @constraint(m, x[77]<=0.6) #= e108: =# - @constraint(m, x[78]<=0.6) #= e109: =# - @constraint(m, x[85]<=1.1) #= e110: =# - @constraint(m, x[86]<=1.1) #= e111: =# - @constraint(m, x[87]<=1.1) #= e112: =# - @constraint(m, x[88]<=0.2) #= e113: =# - @constraint(m, x[89]<=0.2) #= e114: =# - @constraint(m, x[90]<=0.2) #= e115: =# - @constraint(m, x[73]<=1) #= e116: =# - @constraint(m, x[74]<=1) #= e117: =# - @constraint(m, x[75]<=1) #= e118: =# - @constraint(m, x[76]<=0.8) #= e119: =# - @constraint(m, x[77]<=0.8) #= e120: =# - @constraint(m, x[78]<=0.8) #= e121: =# - @constraint(m, x[85]<=1) #= e122: =# - @constraint(m, x[86]<=1) #= e123: =# - @constraint(m, x[87]<=1) #= e124: =# - @constraint(m, x[88]<=0.8) #= e125: =# - @constraint(m, x[89]<=0.8) #= e126: =# - @constraint(m, x[90]<=0.8) #= e127: =# - @constraint(m, -x[73]>=-1.3) #= e128: =# - @constraint(m, -x[74]>=-1.3) #= e129: =# - @constraint(m, -x[75]>=-1.3) #= e130: =# - @constraint(m, -x[76]>=-1.4) #= e131: =# - @constraint(m, -x[77]>=-1.4) #= e132: =# - @constraint(m, -x[78]>=-1.4) #= e133: =# - @constraint(m, -x[85]>=-1.7) #= e134: =# - @constraint(m, -x[86]>=-1.7) #= e135: =# - @constraint(m, -x[87]>=-1.7) #= e136: =# - @constraint(m, -x[88]>=-1.8) #= e137: =# - @constraint(m, -x[89]>=-1.8) #= e138: =# - @constraint(m, -x[90]>=-1.8) #= e139: =# - @constraint(m, -x[73]>=-1) #= e140: =# - @constraint(m, -x[74]>=-1) #= e141: =# - @constraint(m, -x[75]>=-1) #= e142: =# - @constraint(m, -x[76]>=-1.4) #= e143: =# - @constraint(m, -x[77]>=-1.4) #= e144: =# - @constraint(m, -x[78]>=-1.4) #= e145: =# - @constraint(m, -x[85]>=-1) #= e146: =# - @constraint(m, -x[86]>=-1) #= e147: =# - @constraint(m, -x[87]>=-1) #= e148: =# - @constraint(m, -x[88]>=-1.4) #= e149: =# - @constraint(m, -x[89]>=-1.4) #= e150: =# - @constraint(m, -x[90]>=-1.4) #= e151: =# - @constraint(m, -x[37]+x[95]<=0.9) #= e152: =# - @constraint(m, -x[38]+x[96]<=0.9) #= e153: =# - @constraint(m, -x[37]+x[98]<=0) #= e154: =# - @constraint(m, -x[38]+x[99]<=0) #= e155: =# - @constraint(m, -x[40]+x[101]<=0.9) #= e156: =# - @constraint(m, -x[41]+x[102]<=0.9) #= e157: =# - @constraint(m, -x[43]+x[95]<=0.6) #= e158: =# - @constraint(m, -x[44]+x[96]<=0.6) #= e159: =# - @constraint(m, -x[43]+x[98]<=0.4) #= e160: =# - @constraint(m, -x[44]+x[99]<=0.4) #= e161: =# - @constraint(m, -x[46]+x[101]<=0.6) #= e162: =# - @constraint(m, -x[47]+x[102]<=0.6) #= e163: =# - @constraint(m, -x[37]-x[95]>=-1.9) #= e164: =# - @constraint(m, -x[38]-x[96]>=-1.9) #= e165: =# - @constraint(m, -x[37]-x[98]>=-2) #= e166: =# - @constraint(m, -x[38]-x[99]>=-2) #= e167: =# - @constraint(m, -x[40]-x[101]>=-1.9) #= e168: =# - @constraint(m, -x[41]-x[102]>=-1.9) #= e169: =# - @constraint(m, -x[43]-x[95]>=-1.4) #= e170: =# - @constraint(m, -x[44]-x[96]>=-1.4) #= e171: =# - @constraint(m, -x[43]-x[98]>=-1.8) #= e172: =# - @constraint(m, -x[44]-x[99]>=-1.8) #= e173: =# - @constraint(m, -x[46]-x[101]>=-1.4) #= e174: =# - @constraint(m, -x[47]-x[102]>=-1.4) #= e175: =# - @constraint(m, x[94]<=1.1) #= e176: =# - @constraint(m, x[97]<=0.2) #= e177: =# - @constraint(m, x[100]<=1.6) #= e178: =# - @constraint(m, x[94]<=1.1) #= e179: =# - @constraint(m, x[97]<=0.9) #= e180: =# - @constraint(m, x[100]<=1.2) #= e181: =# - @constraint(m, -x[94]>=-1.7) #= e182: =# - @constraint(m, -x[97]>=-1.8) #= e183: =# - @constraint(m, -x[100]>=-1.2) #= e184: =# - @constraint(m, -x[94]>=-0.9) #= e185: =# - @constraint(m, -x[97]>=-1.3) #= e186: =# - @constraint(m, -x[100]>=-0.8) #= e187: =# - @constraint(m, x[67]+x[91]<=1) #= e188: =# - @constraint(m, x[68]+x[92]<=1) #= e189: =# - @constraint(m, x[69]+x[93]<=1) #= e190: =# - @constraint(m, x[67]+x[94]<=1) #= e191: =# - @constraint(m, x[68]+x[95]<=1) #= e192: =# - @constraint(m, x[69]+x[96]<=1) #= e193: =# - @constraint(m, x[67]+x[97]<=1) #= e194: =# - @constraint(m, x[68]+x[98]<=1) #= e195: =# - @constraint(m, x[69]+x[99]<=1) #= e196: =# - @constraint(m, x[79]+x[91]<=1) #= e197: =# - @constraint(m, x[80]+x[92]<=1) #= e198: =# - @constraint(m, x[81]+x[93]<=1) #= e199: =# - @constraint(m, x[79]+x[94]<=1) #= e200: =# - @constraint(m, x[80]+x[95]<=1) #= e201: =# - @constraint(m, x[81]+x[96]<=1) #= e202: =# - @constraint(m, x[79]+x[97]<=1) #= e203: =# - @constraint(m, x[80]+x[98]<=1) #= e204: =# - @constraint(m, x[81]+x[99]<=1) #= e205: =# - @constraint(m, x[70]+x[100]<=1) #= e206: =# - @constraint(m, x[71]+x[101]<=1) #= e207: =# - @constraint(m, x[72]+x[102]<=1) #= e208: =# - @constraint(m, x[82]+x[100]<=1) #= e209: =# - @constraint(m, x[83]+x[101]<=1) #= e210: =# - @constraint(m, x[84]+x[102]<=1) #= e211: =# - @constraint(m, x[91]+x[100]<=1) #= e212: =# - @constraint(m, x[92]+x[101]<=1) #= e213: =# - @constraint(m, x[93]+x[102]<=1) #= e214: =# + @constraint(m, x[1] + x[4] + x[7] + x[10] + x[49] == 1) #= e2: =# + @constraint(m, x[13] + x[16] + x[19] + x[22] + x[52] == 1.1) #= e3: =# + @constraint(m, -x[1] - x[13] + x[25] + x[28] + x[31] + x[55] == 0.2) #= e4: =# + @constraint(m, -x[4] - x[16] - x[25] + x[34] + x[58] == 0.1) #= e5: =# + @constraint(m, -x[7] - x[19] - x[28] - x[34] + x[61] == 1.55) #= e6: =# + @constraint(m, -x[10] - x[22] - x[31] + x[64] == 0.49) #= e7: =# + @constraint(m, x[2] + x[5] + x[8] + x[11] - x[49] + x[50] == 1) #= e12: =# + @constraint(m, x[3] + x[6] + x[9] + x[12] - x[50] + x[51] == 0) #= e13: =# + @constraint(m, x[14] + x[17] + x[20] + x[23] - x[52] + x[53] == 0.1) #= e14: =# + @constraint(m, x[15] + x[18] + x[21] + x[24] - x[53] + x[54] == 0.9) #= e15: =# + @constraint(m, -x[2] - x[14] + x[26] + x[29] + x[32] - x[55] + x[56] == 0) #= e16: =# + @constraint(m, -x[3] - x[15] + x[27] + x[30] + x[33] - x[56] + x[57] == 0) #= e17: =# + @constraint(m, -x[5] - x[17] - x[26] + x[35] - x[58] + x[59] == 0) #= e18: =# + @constraint(m, -x[6] - x[18] - x[27] + x[36] - x[59] + x[60] == 0) #= e19: =# + @constraint(m, -x[8] - x[20] - x[29] - x[35] - x[61] + x[62] == -0.81) #= e20: =# + @constraint(m, -x[9] - x[21] - x[30] - x[36] - x[62] + x[63] == -0.88) #= e21: =# + @constraint(m, -x[11] - x[23] - x[32] - x[64] + x[65] == -0.14) #= e22: =# + @constraint(m, -x[12] - x[24] - x[33] - x[65] + x[66] == -0.1) #= e23: =# + @constraint(m, x[1] - x[67] <= 0) #= e32: =# + @constraint(m, x[2] - x[68] <= 0) #= e33: =# + @constraint(m, x[3] - x[69] <= 0) #= e34: =# + @constraint(m, x[4] - x[70] <= 0) #= e35: =# + @constraint(m, x[5] - x[71] <= 0) #= e36: =# + @constraint(m, x[6] - x[72] <= 0) #= e37: =# + @constraint(m, x[7] - x[73] <= 0) #= e38: =# + @constraint(m, x[8] - x[74] <= 0) #= e39: =# + @constraint(m, x[9] - x[75] <= 0) #= e40: =# + @constraint(m, x[10] - x[76] <= 0) #= e41: =# + @constraint(m, x[11] - x[77] <= 0) #= e42: =# + @constraint(m, x[12] - x[78] <= 0) #= e43: =# + @constraint(m, x[13] - x[79] <= 0) #= e44: =# + @constraint(m, x[14] - x[80] <= 0) #= e45: =# + @constraint(m, x[15] - x[81] <= 0) #= e46: =# + @constraint(m, x[16] - x[82] <= 0) #= e47: =# + @constraint(m, x[17] - x[83] <= 0) #= e48: =# + @constraint(m, x[18] - x[84] <= 0) #= e49: =# + @constraint(m, x[19] - x[85] <= 0) #= e50: =# + @constraint(m, x[20] - x[86] <= 0) #= e51: =# + @constraint(m, x[21] - x[87] <= 0) #= e52: =# + @constraint(m, x[22] - x[88] <= 0) #= e53: =# + @constraint(m, x[23] - x[89] <= 0) #= e54: =# + @constraint(m, x[24] - x[90] <= 0) #= e55: =# + @constraint(m, x[25] - x[91] <= 0) #= e56: =# + @constraint(m, x[26] - x[92] <= 0) #= e57: =# + @constraint(m, x[27] - x[93] <= 0) #= e58: =# + @constraint(m, x[28] - x[94] <= 0) #= e59: =# + @constraint(m, x[29] - x[95] <= 0) #= e60: =# + @constraint(m, x[30] - x[96] <= 0) #= e61: =# + @constraint(m, x[31] - x[97] <= 0) #= e62: =# + @constraint(m, x[32] - x[98] <= 0) #= e63: =# + @constraint(m, x[33] - x[99] <= 0) #= e64: =# + @constraint(m, x[34] - x[100] <= 0) #= e65: =# + @constraint(m, x[35] - x[101] <= 0) #= e66: =# + @constraint(m, x[36] - x[102] <= 0) #= e67: =# + @constraint(m, x[1] >= 0) #= e68: =# + @constraint(m, x[2] >= 0) #= e69: =# + @constraint(m, x[3] >= 0) #= e70: =# + @constraint(m, x[4] >= 0) #= e71: =# + @constraint(m, x[5] >= 0) #= e72: =# + @constraint(m, x[6] >= 0) #= e73: =# + @constraint(m, x[7] >= 0) #= e74: =# + @constraint(m, x[8] >= 0) #= e75: =# + @constraint(m, x[9] >= 0) #= e76: =# + @constraint(m, x[10] >= 0) #= e77: =# + @constraint(m, x[11] >= 0) #= e78: =# + @constraint(m, x[12] >= 0) #= e79: =# + @constraint(m, x[13] >= 0) #= e80: =# + @constraint(m, x[14] >= 0) #= e81: =# + @constraint(m, x[15] >= 0) #= e82: =# + @constraint(m, x[16] >= 0) #= e83: =# + @constraint(m, x[17] >= 0) #= e84: =# + @constraint(m, x[18] >= 0) #= e85: =# + @constraint(m, x[19] >= 0) #= e86: =# + @constraint(m, x[20] >= 0) #= e87: =# + @constraint(m, x[21] >= 0) #= e88: =# + @constraint(m, x[22] >= 0) #= e89: =# + @constraint(m, x[23] >= 0) #= e90: =# + @constraint(m, x[24] >= 0) #= e91: =# + @constraint(m, x[25] >= 0) #= e92: =# + @constraint(m, x[26] >= 0) #= e93: =# + @constraint(m, x[27] >= 0) #= e94: =# + @constraint(m, x[28] >= 0) #= e95: =# + @constraint(m, x[29] >= 0) #= e96: =# + @constraint(m, x[30] >= 0) #= e97: =# + @constraint(m, x[31] >= 0) #= e98: =# + @constraint(m, x[32] >= 0) #= e99: =# + @constraint(m, x[33] >= 0) #= e100: =# + @constraint(m, x[34] >= 0) #= e101: =# + @constraint(m, x[35] >= 0) #= e102: =# + @constraint(m, x[36] >= 0) #= e103: =# + @constraint(m, x[73] <= 1.5) #= e104: =# + @constraint(m, x[74] <= 1.5) #= e105: =# + @constraint(m, x[75] <= 1.5) #= e106: =# + @constraint(m, x[76] <= 0.6) #= e107: =# + @constraint(m, x[77] <= 0.6) #= e108: =# + @constraint(m, x[78] <= 0.6) #= e109: =# + @constraint(m, x[85] <= 1.1) #= e110: =# + @constraint(m, x[86] <= 1.1) #= e111: =# + @constraint(m, x[87] <= 1.1) #= e112: =# + @constraint(m, x[88] <= 0.2) #= e113: =# + @constraint(m, x[89] <= 0.2) #= e114: =# + @constraint(m, x[90] <= 0.2) #= e115: =# + @constraint(m, x[73] <= 1) #= e116: =# + @constraint(m, x[74] <= 1) #= e117: =# + @constraint(m, x[75] <= 1) #= e118: =# + @constraint(m, x[76] <= 0.8) #= e119: =# + @constraint(m, x[77] <= 0.8) #= e120: =# + @constraint(m, x[78] <= 0.8) #= e121: =# + @constraint(m, x[85] <= 1) #= e122: =# + @constraint(m, x[86] <= 1) #= e123: =# + @constraint(m, x[87] <= 1) #= e124: =# + @constraint(m, x[88] <= 0.8) #= e125: =# + @constraint(m, x[89] <= 0.8) #= e126: =# + @constraint(m, x[90] <= 0.8) #= e127: =# + @constraint(m, -x[73] >= -1.3) #= e128: =# + @constraint(m, -x[74] >= -1.3) #= e129: =# + @constraint(m, -x[75] >= -1.3) #= e130: =# + @constraint(m, -x[76] >= -1.4) #= e131: =# + @constraint(m, -x[77] >= -1.4) #= e132: =# + @constraint(m, -x[78] >= -1.4) #= e133: =# + @constraint(m, -x[85] >= -1.7) #= e134: =# + @constraint(m, -x[86] >= -1.7) #= e135: =# + @constraint(m, -x[87] >= -1.7) #= e136: =# + @constraint(m, -x[88] >= -1.8) #= e137: =# + @constraint(m, -x[89] >= -1.8) #= e138: =# + @constraint(m, -x[90] >= -1.8) #= e139: =# + @constraint(m, -x[73] >= -1) #= e140: =# + @constraint(m, -x[74] >= -1) #= e141: =# + @constraint(m, -x[75] >= -1) #= e142: =# + @constraint(m, -x[76] >= -1.4) #= e143: =# + @constraint(m, -x[77] >= -1.4) #= e144: =# + @constraint(m, -x[78] >= -1.4) #= e145: =# + @constraint(m, -x[85] >= -1) #= e146: =# + @constraint(m, -x[86] >= -1) #= e147: =# + @constraint(m, -x[87] >= -1) #= e148: =# + @constraint(m, -x[88] >= -1.4) #= e149: =# + @constraint(m, -x[89] >= -1.4) #= e150: =# + @constraint(m, -x[90] >= -1.4) #= e151: =# + @constraint(m, -x[37] + x[95] <= 0.9) #= e152: =# + @constraint(m, -x[38] + x[96] <= 0.9) #= e153: =# + @constraint(m, -x[37] + x[98] <= 0) #= e154: =# + @constraint(m, -x[38] + x[99] <= 0) #= e155: =# + @constraint(m, -x[40] + x[101] <= 0.9) #= e156: =# + @constraint(m, -x[41] + x[102] <= 0.9) #= e157: =# + @constraint(m, -x[43] + x[95] <= 0.6) #= e158: =# + @constraint(m, -x[44] + x[96] <= 0.6) #= e159: =# + @constraint(m, -x[43] + x[98] <= 0.4) #= e160: =# + @constraint(m, -x[44] + x[99] <= 0.4) #= e161: =# + @constraint(m, -x[46] + x[101] <= 0.6) #= e162: =# + @constraint(m, -x[47] + x[102] <= 0.6) #= e163: =# + @constraint(m, -x[37] - x[95] >= -1.9) #= e164: =# + @constraint(m, -x[38] - x[96] >= -1.9) #= e165: =# + @constraint(m, -x[37] - x[98] >= -2) #= e166: =# + @constraint(m, -x[38] - x[99] >= -2) #= e167: =# + @constraint(m, -x[40] - x[101] >= -1.9) #= e168: =# + @constraint(m, -x[41] - x[102] >= -1.9) #= e169: =# + @constraint(m, -x[43] - x[95] >= -1.4) #= e170: =# + @constraint(m, -x[44] - x[96] >= -1.4) #= e171: =# + @constraint(m, -x[43] - x[98] >= -1.8) #= e172: =# + @constraint(m, -x[44] - x[99] >= -1.8) #= e173: =# + @constraint(m, -x[46] - x[101] >= -1.4) #= e174: =# + @constraint(m, -x[47] - x[102] >= -1.4) #= e175: =# + @constraint(m, x[94] <= 1.1) #= e176: =# + @constraint(m, x[97] <= 0.2) #= e177: =# + @constraint(m, x[100] <= 1.6) #= e178: =# + @constraint(m, x[94] <= 1.1) #= e179: =# + @constraint(m, x[97] <= 0.9) #= e180: =# + @constraint(m, x[100] <= 1.2) #= e181: =# + @constraint(m, -x[94] >= -1.7) #= e182: =# + @constraint(m, -x[97] >= -1.8) #= e183: =# + @constraint(m, -x[100] >= -1.2) #= e184: =# + @constraint(m, -x[94] >= -0.9) #= e185: =# + @constraint(m, -x[97] >= -1.3) #= e186: =# + @constraint(m, -x[100] >= -0.8) #= e187: =# + @constraint(m, x[67] + x[91] <= 1) #= e188: =# + @constraint(m, x[68] + x[92] <= 1) #= e189: =# + @constraint(m, x[69] + x[93] <= 1) #= e190: =# + @constraint(m, x[67] + x[94] <= 1) #= e191: =# + @constraint(m, x[68] + x[95] <= 1) #= e192: =# + @constraint(m, x[69] + x[96] <= 1) #= e193: =# + @constraint(m, x[67] + x[97] <= 1) #= e194: =# + @constraint(m, x[68] + x[98] <= 1) #= e195: =# + @constraint(m, x[69] + x[99] <= 1) #= e196: =# + @constraint(m, x[79] + x[91] <= 1) #= e197: =# + @constraint(m, x[80] + x[92] <= 1) #= e198: =# + @constraint(m, x[81] + x[93] <= 1) #= e199: =# + @constraint(m, x[79] + x[94] <= 1) #= e200: =# + @constraint(m, x[80] + x[95] <= 1) #= e201: =# + @constraint(m, x[81] + x[96] <= 1) #= e202: =# + @constraint(m, x[79] + x[97] <= 1) #= e203: =# + @constraint(m, x[80] + x[98] <= 1) #= e204: =# + @constraint(m, x[81] + x[99] <= 1) #= e205: =# + @constraint(m, x[70] + x[100] <= 1) #= e206: =# + @constraint(m, x[71] + x[101] <= 1) #= e207: =# + @constraint(m, x[72] + x[102] <= 1) #= e208: =# + @constraint(m, x[82] + x[100] <= 1) #= e209: =# + @constraint(m, x[83] + x[101] <= 1) #= e210: =# + @constraint(m, x[84] + x[102] <= 1) #= e211: =# + @constraint(m, x[91] + x[100] <= 1) #= e212: =# + @constraint(m, x[92] + x[101] <= 1) #= e213: =# + @constraint(m, x[93] + x[102] <= 1) #= e214: =# return m end diff --git a/examples/MINLPs/brainpc3.jl b/examples/MINLPs/brainpc3.jl index db1d337e..6b2231f2 100644 --- a/examples/MINLPs/brainpc3.jl +++ b/examples/MINLPs/brainpc3.jl @@ -1,11 +1,43 @@ -function brainpc3(;solver = nothing) - +function brainpc3(; solver = nothing) m = Model(solver) # ----- Variables ----- # @variable(m, x[1:6907]) - @NLobjective(m, Min, ((-0.003214)+x[16]-(x[16]+x[3467])*x[6903]+x[3467]+6.34e-6*x[6903])^2+ (x[46]-(x[46]+x[3497])*x[6903]+x[3497]+0.01551*x[6903])^2+ (x[76]-(x[76]+x[3527])*x[6903]+x[3527]+0.008919*x[6903])^2+ (x[106]-(x[106]+x[3557])*x[6903]+x[3557]+0.005968*x[6903])^2+ (x[136]-(x[136]+x[3587])*x[6903]+x[3587]+0.005773*x[6903])^2+ (x[166]-(x[166]+x[3617])*x[6903]+x[3617]+0.004985*x[6903])^2+ (x[196]-(x[196]+x[3647])*x[6903]+x[3647]+0.004795*x[6903])^2+ (x[226]-(x[226]+x[3677])*x[6903]+x[3677]+0.004409*x[6903])^2+ (x[271]-(x[271]+x[3722])*x[6903]+x[3722]+0.003829*x[6903])^2+ (x[331]-(x[331]+x[3782])*x[6903]+x[3782]+0.003269*x[6903])^2+ (x[391]-(x[391]+x[3842])*x[6903]+x[3842]+0.00317*x[6903])^2+ (x[451]-(x[451]+x[3902])*x[6903]+x[3902]+0.00307*x[6903])^2+ (x[511]-(x[511]+x[3962])*x[6903]+x[3962]+0.002971*x[6903])^2+ (x[631]-(x[631]+x[4082])*x[6903]+x[4082]+0.002765*x[6903])^2+ (x[811]-(x[811]+x[4262])*x[6903]+x[4262]+0.00247*x[6903])^2+ (x[991]-(x[991]+x[4442])*x[6903]+x[4442]+0.002252*x[6903])^2+ (x[1171]-(x[1171]+x[4622])*x[6903]+x[4622]+0.002066*x[6903])^2+ (x[1351]-(x[1351]+x[4802])*x[6903]+x[4802]+0.001891*x[6903])^2+ (x[1531]-(x[1531]+x[4982])*x[6903]+x[4982]+0.00173*x[6903])^2+ (x[1711]-(x[1711]+x[5162])*x[6903]+x[5162]+0.001713*x[6903])^2+ (x[1951]-(x[1951]+x[5402])*x[6903]+x[5402]+0.00166*x[6903])^2+ (x[2251]-(x[2251]+x[5702])*x[6903]+x[5702]+0.001548*x[6903])^2+ (x[2551]-(x[2551]+x[6002])*x[6903]+x[6002]+0.001435*x[6903])^2+ (x[2851]-(x[2851]+x[6302])*x[6903]+x[6302]+0.001323*x[6903])^2+ (x[3151]-(x[3151]+x[6602])*x[6903]+x[6602]+0.00121*x[6903])^2+ (x[3451]-(x[3451]+x[6902])*x[6903]+x[6902]+0.001098*x[6903])^2) + @NLobjective( + m, + Min, + ( + (-0.003214) + x[16] - (x[16] + x[3467]) * x[6903] + + x[3467] + + 6.34e-6 * x[6903] + )^2 + + (x[46] - (x[46] + x[3497]) * x[6903] + x[3497] + 0.01551 * x[6903])^2 + + (x[76] - (x[76] + x[3527]) * x[6903] + x[3527] + 0.008919 * x[6903])^2 + + (x[106] - (x[106] + x[3557]) * x[6903] + x[3557] + 0.005968 * x[6903])^2 + + (x[136] - (x[136] + x[3587]) * x[6903] + x[3587] + 0.005773 * x[6903])^2 + + (x[166] - (x[166] + x[3617]) * x[6903] + x[3617] + 0.004985 * x[6903])^2 + + (x[196] - (x[196] + x[3647]) * x[6903] + x[3647] + 0.004795 * x[6903])^2 + + (x[226] - (x[226] + x[3677]) * x[6903] + x[3677] + 0.004409 * x[6903])^2 + + (x[271] - (x[271] + x[3722]) * x[6903] + x[3722] + 0.003829 * x[6903])^2 + + (x[331] - (x[331] + x[3782]) * x[6903] + x[3782] + 0.003269 * x[6903])^2 + + (x[391] - (x[391] + x[3842]) * x[6903] + x[3842] + 0.00317 * x[6903])^2 + + (x[451] - (x[451] + x[3902]) * x[6903] + x[3902] + 0.00307 * x[6903])^2 + + (x[511] - (x[511] + x[3962]) * x[6903] + x[3962] + 0.002971 * x[6903])^2 + + (x[631] - (x[631] + x[4082]) * x[6903] + x[4082] + 0.002765 * x[6903])^2 + + (x[811] - (x[811] + x[4262]) * x[6903] + x[4262] + 0.00247 * x[6903])^2 + + (x[991] - (x[991] + x[4442]) * x[6903] + x[4442] + 0.002252 * x[6903])^2 + + (x[1171] - (x[1171] + x[4622]) * x[6903] + x[4622] + 0.002066 * x[6903])^2 + + (x[1351] - (x[1351] + x[4802]) * x[6903] + x[4802] + 0.001891 * x[6903])^2 + + (x[1531] - (x[1531] + x[4982]) * x[6903] + x[4982] + 0.00173 * x[6903])^2 + + (x[1711] - (x[1711] + x[5162]) * x[6903] + x[5162] + 0.001713 * x[6903])^2 + + (x[1951] - (x[1951] + x[5402]) * x[6903] + x[5402] + 0.00166 * x[6903])^2 + + (x[2251] - (x[2251] + x[5702]) * x[6903] + x[5702] + 0.001548 * x[6903])^2 + + (x[2551] - (x[2551] + x[6002]) * x[6903] + x[6002] + 0.001435 * x[6903])^2 + + (x[2851] - (x[2851] + x[6302]) * x[6903] + x[6302] + 0.001323 * x[6903])^2 + + (x[3151] - (x[3151] + x[6602]) * x[6903] + x[6602] + 0.00121 * x[6903])^2 + + (x[3451] - (x[3451] + x[6902]) * x[6903] + x[6902] + 0.001098 * x[6903])^2 + ) - return m # model get returned when including this script. + return m # model get returned when including this script. end diff --git a/examples/MINLPs/castro.jl b/examples/MINLPs/castro.jl index f28a5060..9d235cd7 100644 --- a/examples/MINLPs/castro.jl +++ b/examples/MINLPs/castro.jl @@ -1,305 +1,420 @@ -function castro2m2(;solver = nothing) - - m = Model(solver) +function castro2m2(; solver = nothing) + m = Model(solver) - @variable(m, 0 <= x[1:41] <= 1E5) + @variable(m, 0 <= x[1:41] <= 1E5) @variable(m, obj) @objective(m, Min, obj) - @NLconstraint(m, e31,x[28]*x[30]-x[16]==0.0) - @NLconstraint(m, e32,x[28]*x[31]-x[17]==0.0) - @NLconstraint(m, e33,x[29]*x[32]-x[18]==0.0) - @NLconstraint(m, e34,x[29]*x[33]-x[19]==0.0) - @NLconstraint(m, e35,x[28]*x[36]-x[22]==0.0) - @NLconstraint(m, e36,x[29]*x[37]-x[23]==0.0) - @NLconstraint(m, e37,x[14]*x[30]-x[1]==0.0) - @NLconstraint(m, e38,x[14]*x[31]-x[2]==0.0) - @NLconstraint(m, e39,x[15]*x[32]-x[3]==0.0) - @NLconstraint(m, e40,x[15]*x[33]-x[4]==0.0) - @NLconstraint(m, e41,x[14]*x[36]-x[7]==0.0) - @NLconstraint(m, e42,x[15]*x[37]-x[8]==0.0) + @NLconstraint(m, e31, x[28] * x[30] - x[16] == 0.0) + @NLconstraint(m, e32, x[28] * x[31] - x[17] == 0.0) + @NLconstraint(m, e33, x[29] * x[32] - x[18] == 0.0) + @NLconstraint(m, e34, x[29] * x[33] - x[19] == 0.0) + @NLconstraint(m, e35, x[28] * x[36] - x[22] == 0.0) + @NLconstraint(m, e36, x[29] * x[37] - x[23] == 0.0) + @NLconstraint(m, e37, x[14] * x[30] - x[1] == 0.0) + @NLconstraint(m, e38, x[14] * x[31] - x[2] == 0.0) + @NLconstraint(m, e39, x[15] * x[32] - x[3] == 0.0) + @NLconstraint(m, e40, x[15] * x[33] - x[4] == 0.0) + @NLconstraint(m, e41, x[14] * x[36] - x[7] == 0.0) + @NLconstraint(m, e42, x[15] * x[37] - x[8] == 0.0) - @constraint(m, e1, -x[14]-x[15]+obj==0.0) - @constraint(m, e2, -x[5]-x[9]-x[10]==-60.0) - @constraint(m, e3, -x[6]-x[11]-x[12]==-20.0) - @constraint(m, e4, -x[1]-x[3]-x[9]-x[11]+x[14]==0.0) - @constraint(m, e5, -x[2]-x[4]-x[10]-x[12]+x[15]==0.0) - @constraint(m, e6, -x[1]-x[2]-x[7]+x[14]==0.0) - @constraint(m, e7, -x[3]-x[4]-x[8]+x[15]==0.0) - @constraint(m, e8, -x[5]-x[6]-x[7]-x[8]+x[13]==0.0) - @constraint(m, e9, -x[20]-x[24]-x[25]==-24000.0) - @constraint(m, e10, -x[21]-x[26]-x[27]==-16000.0) - @constraint(m, e11, -x[24]+24000*x[38]==0.0) - @constraint(m, e12, -x[25]+24000*x[39]==0.0) - @constraint(m, e13, -x[26]+16000*x[40]==0.0) - @constraint(m, e14, -x[27]+16000*x[41]==0.0) - @constraint(m, e15, -x[20]+24000*x[34]==0.0) - @constraint(m, e16, -x[21]+16000*x[35]==0.0) - @constraint(m, e17, -x[9]+60*x[38]==0.0) - @constraint(m, e18, -x[10]+60*x[39]==0.0) - @constraint(m, e19, -x[11]+20*x[40]==0.0) - @constraint(m, e20, -x[12]+20*x[41]==0.0) - @constraint(m, e21, -x[5]+60*x[34]==0.0) - @constraint(m, e22, -x[6]+20*x[35]==0.0) - @constraint(m, e23, x[34]+x[38]+x[39]==1.0) - @constraint(m, e24, x[35]+x[40]+x[41]==1.0) - @constraint(m, e25, -200*x[14]+x[16]+x[18]+x[24]+x[26]<=0.0) - @constraint(m, e26, -1000*x[15]+x[17]+x[19]+x[25]+x[27]<=0.0) - @constraint(m, e27, 0.01*x[16]+0.01*x[18]+0.01*x[24]+0.01*x[26]-x[28]==0.0) - @constraint(m, e28, 0.2*x[17]+0.2*x[19]+0.2*x[25]+0.2*x[27]-x[29]==0.0) - @constraint(m, e29, -x[16]-x[17]-x[22]+x[28]==0.0) - @constraint(m, e30, -x[18]-x[19]-x[23]+x[29]==0.0) - @constraint(m, e43, x[30]+x[31]+x[36]==1.0) - @constraint(m, e44, x[32]+x[33]+x[37]==1.0) - @constraint(m, e45, -10*x[13]+x[20]+x[21]+x[22]+x[23]<=0.0) + @constraint(m, e1, -x[14] - x[15] + obj == 0.0) + @constraint(m, e2, -x[5] - x[9] - x[10] == -60.0) + @constraint(m, e3, -x[6] - x[11] - x[12] == -20.0) + @constraint(m, e4, -x[1] - x[3] - x[9] - x[11] + x[14] == 0.0) + @constraint(m, e5, -x[2] - x[4] - x[10] - x[12] + x[15] == 0.0) + @constraint(m, e6, -x[1] - x[2] - x[7] + x[14] == 0.0) + @constraint(m, e7, -x[3] - x[4] - x[8] + x[15] == 0.0) + @constraint(m, e8, -x[5] - x[6] - x[7] - x[8] + x[13] == 0.0) + @constraint(m, e9, -x[20] - x[24] - x[25] == -24000.0) + @constraint(m, e10, -x[21] - x[26] - x[27] == -16000.0) + @constraint(m, e11, -x[24] + 24000 * x[38] == 0.0) + @constraint(m, e12, -x[25] + 24000 * x[39] == 0.0) + @constraint(m, e13, -x[26] + 16000 * x[40] == 0.0) + @constraint(m, e14, -x[27] + 16000 * x[41] == 0.0) + @constraint(m, e15, -x[20] + 24000 * x[34] == 0.0) + @constraint(m, e16, -x[21] + 16000 * x[35] == 0.0) + @constraint(m, e17, -x[9] + 60 * x[38] == 0.0) + @constraint(m, e18, -x[10] + 60 * x[39] == 0.0) + @constraint(m, e19, -x[11] + 20 * x[40] == 0.0) + @constraint(m, e20, -x[12] + 20 * x[41] == 0.0) + @constraint(m, e21, -x[5] + 60 * x[34] == 0.0) + @constraint(m, e22, -x[6] + 20 * x[35] == 0.0) + @constraint(m, e23, x[34] + x[38] + x[39] == 1.0) + @constraint(m, e24, x[35] + x[40] + x[41] == 1.0) + @constraint(m, e25, -200 * x[14] + x[16] + x[18] + x[24] + x[26] <= 0.0) + @constraint(m, e26, -1000 * x[15] + x[17] + x[19] + x[25] + x[27] <= 0.0) + @constraint( + m, + e27, + 0.01 * x[16] + 0.01 * x[18] + 0.01 * x[24] + 0.01 * x[26] - x[28] == 0.0 + ) + @constraint( + m, + e28, + 0.2 * x[17] + 0.2 * x[19] + 0.2 * x[25] + 0.2 * x[27] - x[29] == 0.0 + ) + @constraint(m, e29, -x[16] - x[17] - x[22] + x[28] == 0.0) + @constraint(m, e30, -x[18] - x[19] - x[23] + x[29] == 0.0) + @constraint(m, e43, x[30] + x[31] + x[36] == 1.0) + @constraint(m, e44, x[32] + x[33] + x[37] == 1.0) + @constraint(m, e45, -10 * x[13] + x[20] + x[21] + x[22] + x[23] <= 0.0) return m end -function castro6m2(;solver = nothing) +function castro6m2(; solver = nothing) + m = Model(solver) - m = Model(solver) + @variable(m, 0 <= x[1:133] <= 1E6) + @variable(m, obj) + @variable(m, b[1:40]) #Additional variables to increase degree of freedom and Ipopt's convergence + @objective(m, Min, obj) - @variable(m, 0 <= x[1:133] <= 1E6) - @variable(m, obj) - @variable(m, b[1:40]) #Additional variables to increase degree of freedom and Ipopt's convergence - @objective(m, Min, obj) - - # Non-Linear Constraints - @NLconstraint(m, e99,x[101]*x[110]-x[29]==0.0) - @NLconstraint(m, e100,x[102]*x[110]-x[30]==0.0) - @NLconstraint(m, e101,x[103]*x[110]-x[31]==0.0) - @NLconstraint(m, e102,x[101]*x[111]-x[32]==0.0) - @NLconstraint(m, e103,x[102]*x[111]-x[33]==0.0) - @NLconstraint(m, e104,x[103]*x[111]-x[34]==0.0) - @NLconstraint(m, e105,x[101]*x[112]-x[35]==0.0) - @NLconstraint(m, e106,x[102]*x[112]-x[36]==0.0) - @NLconstraint(m, e107,x[103]*x[112]-x[37]==0.0) - @NLconstraint(m, e108,x[104]*x[113]-x[38]==0.0) - @NLconstraint(m, e109,x[105]*x[113]-x[39]==0.0) - @NLconstraint(m, e110,x[106]*x[113]-x[40]==0.0) - @NLconstraint(m, e111,x[104]*x[114]-x[41]==0.0) - @NLconstraint(m, e112,x[105]*x[114]-x[42]==0.0) - @NLconstraint(m, e113,x[106]*x[114]-x[43]==0.0) - @NLconstraint(m, e114,x[104]*x[115]-x[44]==0.0) - @NLconstraint(m, e115,x[105]*x[115]-x[45]==0.0) - @NLconstraint(m, e116,x[106]*x[115]-x[46]==0.0) - @NLconstraint(m, e117,x[107]*x[116]-x[47]==0.0) - @NLconstraint(m, e118,x[108]*x[116]-x[48]==0.0) - @NLconstraint(m, e119,x[109]*x[116]-x[49]==0.0) - @NLconstraint(m, e120,x[107]*x[117]-x[50]==0.0) - @NLconstraint(m, e121,x[108]*x[117]-x[51]==0.0) - @NLconstraint(m, e122,x[109]*x[117]-x[52]==0.0) - @NLconstraint(m, e123,x[107]*x[118]-x[53]==0.0) - @NLconstraint(m, e124,x[108]*x[118]-x[54]==0.0) - @NLconstraint(m, e125,x[109]*x[118]-x[55]==0.0) - @NLconstraint(m, e126,x[101]*x[122]-x[65]==0.0) - @NLconstraint(m, e127,x[102]*x[122]-x[66]==0.0) - @NLconstraint(m, e128,x[103]*x[122]-x[67]==0.0) - @NLconstraint(m, e129,x[104]*x[123]-x[68]==0.0) - @NLconstraint(m, e130,x[105]*x[123]-x[69]==0.0) - @NLconstraint(m, e131,x[106]*x[123]-x[70]==0.0) - @NLconstraint(m, e132,x[107]*x[124]-x[71]==0.0) - @NLconstraint(m, e133,x[108]*x[124]-x[72]==0.0) - @NLconstraint(m, e134,x[109]*x[124]-x[73]==0.0) - @NLconstraint(m, e135,x[26]*x[110]-x[1]==0.0) - @NLconstraint(m, e136,x[26]*x[111]-x[2]==0.0) - @NLconstraint(m, e137,x[26]*x[112]-x[3]==0.0) - @NLconstraint(m, e138,x[27]*x[113]-x[4]==0.0) - @NLconstraint(m, e139,x[27]*x[114]-x[5]==0.0) - @NLconstraint(m, e140,x[27]*x[115]-x[6]==0.0) - @NLconstraint(m, e141,x[28]*x[116]-x[7]==0.0) - @NLconstraint(m, e142,x[28]*x[117]-x[8]==0.0) - @NLconstraint(m, e143,x[28]*x[118]-x[9]==0.0) - @NLconstraint(m, e144,x[26]*x[122]-x[13]==0.0) - @NLconstraint(m, e145,x[27]*x[123]-x[14]==0.0) - @NLconstraint(m, e146,x[28]*x[124]-x[15]==0.0) + # Non-Linear Constraints + @NLconstraint(m, e99, x[101] * x[110] - x[29] == 0.0) + @NLconstraint(m, e100, x[102] * x[110] - x[30] == 0.0) + @NLconstraint(m, e101, x[103] * x[110] - x[31] == 0.0) + @NLconstraint(m, e102, x[101] * x[111] - x[32] == 0.0) + @NLconstraint(m, e103, x[102] * x[111] - x[33] == 0.0) + @NLconstraint(m, e104, x[103] * x[111] - x[34] == 0.0) + @NLconstraint(m, e105, x[101] * x[112] - x[35] == 0.0) + @NLconstraint(m, e106, x[102] * x[112] - x[36] == 0.0) + @NLconstraint(m, e107, x[103] * x[112] - x[37] == 0.0) + @NLconstraint(m, e108, x[104] * x[113] - x[38] == 0.0) + @NLconstraint(m, e109, x[105] * x[113] - x[39] == 0.0) + @NLconstraint(m, e110, x[106] * x[113] - x[40] == 0.0) + @NLconstraint(m, e111, x[104] * x[114] - x[41] == 0.0) + @NLconstraint(m, e112, x[105] * x[114] - x[42] == 0.0) + @NLconstraint(m, e113, x[106] * x[114] - x[43] == 0.0) + @NLconstraint(m, e114, x[104] * x[115] - x[44] == 0.0) + @NLconstraint(m, e115, x[105] * x[115] - x[45] == 0.0) + @NLconstraint(m, e116, x[106] * x[115] - x[46] == 0.0) + @NLconstraint(m, e117, x[107] * x[116] - x[47] == 0.0) + @NLconstraint(m, e118, x[108] * x[116] - x[48] == 0.0) + @NLconstraint(m, e119, x[109] * x[116] - x[49] == 0.0) + @NLconstraint(m, e120, x[107] * x[117] - x[50] == 0.0) + @NLconstraint(m, e121, x[108] * x[117] - x[51] == 0.0) + @NLconstraint(m, e122, x[109] * x[117] - x[52] == 0.0) + @NLconstraint(m, e123, x[107] * x[118] - x[53] == 0.0) + @NLconstraint(m, e124, x[108] * x[118] - x[54] == 0.0) + @NLconstraint(m, e125, x[109] * x[118] - x[55] == 0.0) + @NLconstraint(m, e126, x[101] * x[122] - x[65] == 0.0) + @NLconstraint(m, e127, x[102] * x[122] - x[66] == 0.0) + @NLconstraint(m, e128, x[103] * x[122] - x[67] == 0.0) + @NLconstraint(m, e129, x[104] * x[123] - x[68] == 0.0) + @NLconstraint(m, e130, x[105] * x[123] - x[69] == 0.0) + @NLconstraint(m, e131, x[106] * x[123] - x[70] == 0.0) + @NLconstraint(m, e132, x[107] * x[124] - x[71] == 0.0) + @NLconstraint(m, e133, x[108] * x[124] - x[72] == 0.0) + @NLconstraint(m, e134, x[109] * x[124] - x[73] == 0.0) + @NLconstraint(m, e135, x[26] * x[110] - x[1] == 0.0) + @NLconstraint(m, e136, x[26] * x[111] - x[2] == 0.0) + @NLconstraint(m, e137, x[26] * x[112] - x[3] == 0.0) + @NLconstraint(m, e138, x[27] * x[113] - x[4] == 0.0) + @NLconstraint(m, e139, x[27] * x[114] - x[5] == 0.0) + @NLconstraint(m, e140, x[27] * x[115] - x[6] == 0.0) + @NLconstraint(m, e141, x[28] * x[116] - x[7] == 0.0) + @NLconstraint(m, e142, x[28] * x[117] - x[8] == 0.0) + @NLconstraint(m, e143, x[28] * x[118] - x[9] == 0.0) + @NLconstraint(m, e144, x[26] * x[122] - x[13] == 0.0) + @NLconstraint(m, e145, x[27] * x[123] - x[14] == 0.0) + @NLconstraint(m, e146, x[28] * x[124] - x[15] == 0.0) - @constraint(m, e1, -x[26]-x[27]-x[28]+obj==0.0) - @constraint(m, e2, -x[10]-x[16]-x[17]-x[18]==-13.1) - @constraint(m, e3, -x[11]-x[19]-x[20]-x[21]==-32.7) - @constraint(m, e4, -x[12]-x[22]-x[23]-x[24]==-56.5) - @constraint(m, e5, -x[1]-x[4]-x[7]-x[16]-x[19]-x[22]+x[26]==0.0) - @constraint(m, e6, -x[2]-x[5]-x[8]-x[17]-x[20]-x[23]+x[27]==0.0) - @constraint(m, e7, -x[3]-x[6]-x[9]-x[18]-x[21]-x[24]+x[28]==0.0) - @constraint(m, e8, -x[1]-x[2]-x[3]-x[13]+x[26]==0.0) - @constraint(m, e9, -x[4]-x[5]-x[6]-x[14]+x[27]==0.0) - @constraint(m, e10, -x[7]-x[8]-x[9]-x[15]+x[28]==0.0) - @constraint(m, e11, -x[10]-x[11]-x[12]-x[13]-x[14]-x[15]+x[25]==0.0) - @constraint(m, e12, -x[56]-x[74]-x[77]-x[80]==-131.0) - @constraint(m, e13, -x[57]-x[75]-x[78]-x[81]==-5109.0) - @constraint(m, e14, -x[58]-x[76]-x[79]-x[82]==-3275.0) - @constraint(m, e15, -x[59]-x[83]-x[86]-x[89]==-3597.0) - @constraint(m, e16, -x[60]-x[84]-x[87]-x[90]==-548706.0) - @constraint(m, e17, -x[61]-x[85]-x[88]-x[91]==-13080.0) - @constraint(m, e18, -x[62]-x[92]-x[95]-x[98]==-5650.0) - @constraint(m, e19, -x[63]-x[93]-x[96]-x[99]==-1412.5) - @constraint(m, e20, -x[64]-x[94]-x[97]-x[100]==-19775.0) - @constraint(m, e21, -x[74]+131*x[125]==0.0) - @constraint(m, e22, -x[75]+5109*x[125]==0.0) - @constraint(m, e23, -x[76]+3275*x[125]==0.0) - @constraint(m, e24, -x[77]+131*x[126]==0.0) - @constraint(m, e25, -x[78]+5109*x[126]==0.0) - @constraint(m, e26, -x[79]+3275*x[126]==0.0) - @constraint(m, e27, -x[80]+131*x[127]==0.0) - @constraint(m, e28, -x[81]+5109*x[127]==0.0) - @constraint(m, e29, -x[82]+3275*x[127]==0.0) - @constraint(m, e30, -x[83]+3597*x[128]==0.0) - @constraint(m, e31, -x[84]+548706*x[128]==0.0) - @constraint(m, e32, -x[85]+13080*x[128]==0.0) - @constraint(m, e33, -x[86]+3597*x[129]==0.0) - @constraint(m, e34, -x[87]+548706*x[129]==0.0) - @constraint(m, e35, -x[88]+13080*x[129]==0.0) - @constraint(m, e36, -x[89]+3597*x[130]==0.0) - @constraint(m, e37, -x[90]+548706*x[130]==0.0) - @constraint(m, e38, -x[91]+13080*x[130]==0.0) - @constraint(m, e39, -x[92]+5650*x[131]==0.0) - @constraint(m, e40, -x[93]+1412.5*x[131]==0.0) - @constraint(m, e41, -x[94]+19775*x[131]==0.0) - @constraint(m, e42, -x[95]+5650*x[132]==0.0) - @constraint(m, e43, -x[96]+1412.5*x[132]==0.0) - @constraint(m, e44, -x[97]+19775*x[132]==0.0) - @constraint(m, e45, -x[98]+5650*x[133]==0.0) - @constraint(m, e46, -x[99]+1412.5*x[133]==0.0) - @constraint(m, e47, -x[100]+19775*x[133]==0.0) - @constraint(m, e48, -x[56]+131*x[119]==0.0) - @constraint(m, e49, -x[57]+5109*x[119]==0.0) - @constraint(m, e50, -x[58]+3275*x[119]==0.0) - @constraint(m, e51, -x[59]+3597*x[120]==0.0) - @constraint(m, e52, -x[60]+548706*x[120]==0.0) - @constraint(m, e53, -x[61]+13080*x[120]==0.0) - @constraint(m, e54, -x[62]+5650*x[121]==0.0) - @constraint(m, e55, -x[63]+1412.5*x[121]==0.0) - @constraint(m, e56, -x[64]+19775*x[121]==0.0) - @constraint(m, e57, -x[16]+13.1*x[125]==0.0) - @constraint(m, e58, -x[17]+13.1*x[126]==0.0) - @constraint(m, e59, -x[18]+13.1*x[127]==0.0) - @constraint(m, e60, -x[19]+32.7*x[128]==0.0) - @constraint(m, e61, -x[20]+32.7*x[129]==0.0) - @constraint(m, e62, -x[21]+32.7*x[130]==0.0) - @constraint(m, e63, -x[22]+56.5*x[131]==0.0) - @constraint(m, e64, -x[23]+56.5*x[132]==0.0) - @constraint(m, e65, -x[24]+56.5*x[133]==0.0) - @constraint(m, e66, -x[10]+13.1*x[119]==0.0) - @constraint(m, e67, -x[11]+32.7*x[120]==0.0) - @constraint(m, e68, -x[12]+56.5*x[121]==0.0) - @constraint(m, e69, x[119]+x[125]+x[126]+x[127]==1.0) - @constraint(m, e70, x[120]+x[128]+x[129]+x[130]==1.0) - @constraint(m, e71, x[121]+x[131]+x[132]+x[133]==1.0) - @constraint(m, e72, -110*x[26]+x[29]+x[38]+x[47]+x[74]+x[83]+x[92]<=0.0) - @constraint(m, e73, -16780*x[26]+x[30]+x[39]+x[48]+x[75]+x[84]+x[93]<=0.0) - @constraint(m, e74, -400*x[26]+x[31]+x[40]+x[49]+x[76]+x[85]+x[94]<=0.0) - @constraint(m, e75, -110*x[27]+x[32]+x[41]+x[50]+x[77]+x[86]+x[95]<=0.0) - @constraint(m, e76, -16780*x[27]+x[33]+x[42]+x[51]+x[78]+x[87]+x[96]<=0.0) - @constraint(m, e77, -400*x[27]+x[34]+x[43]+x[52]+x[79]+x[88]+x[97]<=0.0) - @constraint(m, e78, -110*x[28]+x[35]+x[44]+x[53]+x[80]+x[89]+x[98]<=0.0) - @constraint(m, e79, -16780*x[28]+x[36]+x[45]+x[54]+x[81]+x[90]+x[99]<=0.0) - @constraint(m, e80, -400*x[28]+x[37]+x[46]+x[55]+x[82]+x[91]+x[100]<=0.0) - @constraint(m, e81, x[29]+x[38]+x[47]+x[74]+x[83]+x[92]-x[101]==0.0) - @constraint(m, e82, 0.001*x[30]+0.001*x[39]+0.001*x[48]+0.001*x[75]+0.001*x[84]+0.001*x[93]-x[102]==0.0) - @constraint(m, e83, x[31]+x[40]+x[49]+x[76]+x[85]+x[94]-x[103]==0.0) - @constraint(m, e84, 0.3*x[32]+0.3*x[41]+0.3*x[50]+0.3*x[77]+0.3*x[86]+0.3*x[95]-x[104]==0.0) - @constraint(m, e85, 0.1*x[33]+0.1*x[42]+0.1*x[51]+0.1*x[78]+0.1*x[87]+0.1*x[96]-x[105]==0.0) - @constraint(m, e86, 0.02*x[34]+0.02*x[43]+0.02*x[52]+0.02*x[79]+0.02*x[88]+0.02*x[97]-x[106]==0.0) - @constraint(m, e87, 0.3*x[35]+0.3*x[44]+0.3*x[53]+0.3*x[80]+0.3*x[89]+0.3*x[98]-x[107]==0.0) - @constraint(m, e88, x[36]+x[45]+x[54]+x[81]+x[90]+x[99]-x[108]==0.0) - @constraint(m, e89, 0.5*x[37]+0.5*x[46]+0.5*x[55]+0.5*x[82]+0.5*x[91]+0.5*x[100]-x[109]==0.0) - @constraint(m, e90, -x[29]-x[32]-x[35]-x[65]+x[101]==0.0) - @constraint(m, e91, -x[30]-x[33]-x[36]-x[66]+x[102]==0.0) - @constraint(m, e92, -x[31]-x[34]-x[37]-x[67]+x[103]==0.0) - @constraint(m, e93, -x[38]-x[41]-x[44]-x[68]+x[104]==0.0) - @constraint(m, e94, -x[39]-x[42]-x[45]-x[69]+x[105]==0.0) - @constraint(m, e95, -x[40]-x[43]-x[46]-x[70]+x[106]==0.0) - @constraint(m, e96, -x[47]-x[50]-x[53]-x[71]+x[107]==0.0) - @constraint(m, e97, -x[48]-x[51]-x[54]-x[72]+x[108]==0.0) - @constraint(m, e98, -x[49]-x[52]-x[55]-x[73]+x[109]==0.0) - @constraint(m, e147, x[110]+x[111]+x[112]+x[122]==1.0) - @constraint(m, e148, x[113]+x[114]+x[115]+x[123]==1.0) - @constraint(m, e149, x[116]+x[117]+x[118]+x[124]==1.0) - @constraint(m, e150, -20*x[25]+x[56]+x[59]+x[62]+x[65]+x[68]+x[71]<=0.0) - @constraint(m, e151, -5*x[25]+x[57]+x[60]+x[63]+x[66]+x[69]+x[72]<=0.0) - @constraint(m, e152, -100*x[25]+x[58]+x[61]+x[64]+x[67]+x[70]+x[73]<=0.0) + @constraint(m, e1, -x[26] - x[27] - x[28] + obj == 0.0) + @constraint(m, e2, -x[10] - x[16] - x[17] - x[18] == -13.1) + @constraint(m, e3, -x[11] - x[19] - x[20] - x[21] == -32.7) + @constraint(m, e4, -x[12] - x[22] - x[23] - x[24] == -56.5) + @constraint(m, e5, -x[1] - x[4] - x[7] - x[16] - x[19] - x[22] + x[26] == 0.0) + @constraint(m, e6, -x[2] - x[5] - x[8] - x[17] - x[20] - x[23] + x[27] == 0.0) + @constraint(m, e7, -x[3] - x[6] - x[9] - x[18] - x[21] - x[24] + x[28] == 0.0) + @constraint(m, e8, -x[1] - x[2] - x[3] - x[13] + x[26] == 0.0) + @constraint(m, e9, -x[4] - x[5] - x[6] - x[14] + x[27] == 0.0) + @constraint(m, e10, -x[7] - x[8] - x[9] - x[15] + x[28] == 0.0) + @constraint(m, e11, -x[10] - x[11] - x[12] - x[13] - x[14] - x[15] + x[25] == 0.0) + @constraint(m, e12, -x[56] - x[74] - x[77] - x[80] == -131.0) + @constraint(m, e13, -x[57] - x[75] - x[78] - x[81] == -5109.0) + @constraint(m, e14, -x[58] - x[76] - x[79] - x[82] == -3275.0) + @constraint(m, e15, -x[59] - x[83] - x[86] - x[89] == -3597.0) + @constraint(m, e16, -x[60] - x[84] - x[87] - x[90] == -548706.0) + @constraint(m, e17, -x[61] - x[85] - x[88] - x[91] == -13080.0) + @constraint(m, e18, -x[62] - x[92] - x[95] - x[98] == -5650.0) + @constraint(m, e19, -x[63] - x[93] - x[96] - x[99] == -1412.5) + @constraint(m, e20, -x[64] - x[94] - x[97] - x[100] == -19775.0) + @constraint(m, e21, -x[74] + 131 * x[125] == 0.0) + @constraint(m, e22, -x[75] + 5109 * x[125] == 0.0) + @constraint(m, e23, -x[76] + 3275 * x[125] == 0.0) + @constraint(m, e24, -x[77] + 131 * x[126] == 0.0) + @constraint(m, e25, -x[78] + 5109 * x[126] == 0.0) + @constraint(m, e26, -x[79] + 3275 * x[126] == 0.0) + @constraint(m, e27, -x[80] + 131 * x[127] == 0.0) + @constraint(m, e28, -x[81] + 5109 * x[127] == 0.0) + @constraint(m, e29, -x[82] + 3275 * x[127] == 0.0) + @constraint(m, e30, -x[83] + 3597 * x[128] == 0.0) + @constraint(m, e31, -x[84] + 548706 * x[128] == 0.0) + @constraint(m, e32, -x[85] + 13080 * x[128] == 0.0) + @constraint(m, e33, -x[86] + 3597 * x[129] == 0.0) + @constraint(m, e34, -x[87] + 548706 * x[129] == 0.0) + @constraint(m, e35, -x[88] + 13080 * x[129] == 0.0) + @constraint(m, e36, -x[89] + 3597 * x[130] == 0.0) + @constraint(m, e37, -x[90] + 548706 * x[130] == 0.0) + @constraint(m, e38, -x[91] + 13080 * x[130] == 0.0) + @constraint(m, e39, -x[92] + 5650 * x[131] == 0.0) + @constraint(m, e40, -x[93] + 1412.5 * x[131] == 0.0) + @constraint(m, e41, -x[94] + 19775 * x[131] == 0.0) + @constraint(m, e42, -x[95] + 5650 * x[132] == 0.0) + @constraint(m, e43, -x[96] + 1412.5 * x[132] == 0.0) + @constraint(m, e44, -x[97] + 19775 * x[132] == 0.0) + @constraint(m, e45, -x[98] + 5650 * x[133] == 0.0) + @constraint(m, e46, -x[99] + 1412.5 * x[133] == 0.0) + @constraint(m, e47, -x[100] + 19775 * x[133] == 0.0) + @constraint(m, e48, -x[56] + 131 * x[119] == 0.0) + @constraint(m, e49, -x[57] + 5109 * x[119] == 0.0) + @constraint(m, e50, -x[58] + 3275 * x[119] == 0.0) + @constraint(m, e51, -x[59] + 3597 * x[120] == 0.0) + @constraint(m, e52, -x[60] + 548706 * x[120] == 0.0) + @constraint(m, e53, -x[61] + 13080 * x[120] == 0.0) + @constraint(m, e54, -x[62] + 5650 * x[121] == 0.0) + @constraint(m, e55, -x[63] + 1412.5 * x[121] == 0.0) + @constraint(m, e56, -x[64] + 19775 * x[121] == 0.0) + @constraint(m, e57, -x[16] + 13.1 * x[125] == 0.0) + @constraint(m, e58, -x[17] + 13.1 * x[126] == 0.0) + @constraint(m, e59, -x[18] + 13.1 * x[127] == 0.0) + @constraint(m, e60, -x[19] + 32.7 * x[128] == 0.0) + @constraint(m, e61, -x[20] + 32.7 * x[129] == 0.0) + @constraint(m, e62, -x[21] + 32.7 * x[130] == 0.0) + @constraint(m, e63, -x[22] + 56.5 * x[131] == 0.0) + @constraint(m, e64, -x[23] + 56.5 * x[132] == 0.0) + @constraint(m, e65, -x[24] + 56.5 * x[133] == 0.0) + @constraint(m, e66, -x[10] + 13.1 * x[119] == 0.0) + @constraint(m, e67, -x[11] + 32.7 * x[120] == 0.0) + @constraint(m, e68, -x[12] + 56.5 * x[121] == 0.0) + @constraint(m, e69, x[119] + x[125] + x[126] + x[127] == 1.0) + @constraint(m, e70, x[120] + x[128] + x[129] + x[130] == 1.0) + @constraint(m, e71, x[121] + x[131] + x[132] + x[133] == 1.0) + @constraint( + m, + e72, + -110 * x[26] + x[29] + x[38] + x[47] + x[74] + x[83] + x[92] <= 0.0 + ) + @constraint( + m, + e73, + -16780 * x[26] + x[30] + x[39] + x[48] + x[75] + x[84] + x[93] <= 0.0 + ) + @constraint( + m, + e74, + -400 * x[26] + x[31] + x[40] + x[49] + x[76] + x[85] + x[94] <= 0.0 + ) + @constraint( + m, + e75, + -110 * x[27] + x[32] + x[41] + x[50] + x[77] + x[86] + x[95] <= 0.0 + ) + @constraint( + m, + e76, + -16780 * x[27] + x[33] + x[42] + x[51] + x[78] + x[87] + x[96] <= 0.0 + ) + @constraint( + m, + e77, + -400 * x[27] + x[34] + x[43] + x[52] + x[79] + x[88] + x[97] <= 0.0 + ) + @constraint( + m, + e78, + -110 * x[28] + x[35] + x[44] + x[53] + x[80] + x[89] + x[98] <= 0.0 + ) + @constraint( + m, + e79, + -16780 * x[28] + x[36] + x[45] + x[54] + x[81] + x[90] + x[99] <= 0.0 + ) + @constraint( + m, + e80, + -400 * x[28] + x[37] + x[46] + x[55] + x[82] + x[91] + x[100] <= 0.0 + ) + @constraint(m, e81, x[29] + x[38] + x[47] + x[74] + x[83] + x[92] - x[101] == 0.0) + @constraint( + m, + e82, + 0.001 * x[30] + + 0.001 * x[39] + + 0.001 * x[48] + + 0.001 * x[75] + + 0.001 * x[84] + + 0.001 * x[93] - x[102] == 0.0 + ) + @constraint(m, e83, x[31] + x[40] + x[49] + x[76] + x[85] + x[94] - x[103] == 0.0) + @constraint( + m, + e84, + 0.3 * x[32] + + 0.3 * x[41] + + 0.3 * x[50] + + 0.3 * x[77] + + 0.3 * x[86] + + 0.3 * x[95] - x[104] == 0.0 + ) + @constraint( + m, + e85, + 0.1 * x[33] + + 0.1 * x[42] + + 0.1 * x[51] + + 0.1 * x[78] + + 0.1 * x[87] + + 0.1 * x[96] - x[105] == 0.0 + ) + @constraint( + m, + e86, + 0.02 * x[34] + + 0.02 * x[43] + + 0.02 * x[52] + + 0.02 * x[79] + + 0.02 * x[88] + + 0.02 * x[97] - x[106] == 0.0 + ) + @constraint( + m, + e87, + 0.3 * x[35] + + 0.3 * x[44] + + 0.3 * x[53] + + 0.3 * x[80] + + 0.3 * x[89] + + 0.3 * x[98] - x[107] == 0.0 + ) + @constraint(m, e88, x[36] + x[45] + x[54] + x[81] + x[90] + x[99] - x[108] == 0.0) + @constraint( + m, + e89, + 0.5 * x[37] + + 0.5 * x[46] + + 0.5 * x[55] + + 0.5 * x[82] + + 0.5 * x[91] + + 0.5 * x[100] - x[109] == 0.0 + ) + @constraint(m, e90, -x[29] - x[32] - x[35] - x[65] + x[101] == 0.0) + @constraint(m, e91, -x[30] - x[33] - x[36] - x[66] + x[102] == 0.0) + @constraint(m, e92, -x[31] - x[34] - x[37] - x[67] + x[103] == 0.0) + @constraint(m, e93, -x[38] - x[41] - x[44] - x[68] + x[104] == 0.0) + @constraint(m, e94, -x[39] - x[42] - x[45] - x[69] + x[105] == 0.0) + @constraint(m, e95, -x[40] - x[43] - x[46] - x[70] + x[106] == 0.0) + @constraint(m, e96, -x[47] - x[50] - x[53] - x[71] + x[107] == 0.0) + @constraint(m, e97, -x[48] - x[51] - x[54] - x[72] + x[108] == 0.0) + @constraint(m, e98, -x[49] - x[52] - x[55] - x[73] + x[109] == 0.0) + @constraint(m, e147, x[110] + x[111] + x[112] + x[122] == 1.0) + @constraint(m, e148, x[113] + x[114] + x[115] + x[123] == 1.0) + @constraint(m, e149, x[116] + x[117] + x[118] + x[124] == 1.0) + @constraint( + m, + e150, + -20 * x[25] + x[56] + x[59] + x[62] + x[65] + x[68] + x[71] <= 0.0 + ) + @constraint( + m, + e151, + -5 * x[25] + x[57] + x[60] + x[63] + x[66] + x[69] + x[72] <= 0.0 + ) + @constraint( + m, + e152, + -100 * x[25] + x[58] + x[61] + x[64] + x[67] + x[70] + x[73] <= 0.0 + ) return m end -function castro4m2(;solver = nothing) - +function castro4m2(; solver = nothing) m = Model(solver) - # ----- Variables ----- # - @variable(m, 0 <= x[1:55] <= 1E6) - @variable(m, obj) + # ----- Variables ----- # + @variable(m, 0 <= x[1:55] <= 1E6) + @variable(m, obj) @variable(m, b[1:20]) #Additional variables to increase degree of freedom and Ipopt's convergence @objective(m, Min, obj) - @NLconstraint(m, e45,x[40]*x[44]-x[16]==0.0) - @NLconstraint(m, e46,x[41]*x[44]-x[17]==0.0) - @NLconstraint(m, e47,x[40]*x[45]-x[18]==0.0) - @NLconstraint(m, e48,x[41]*x[45]-x[19]==0.0) - @NLconstraint(m, e49,x[42]*x[46]-x[20]==0.0) - @NLconstraint(m, e50,x[43]*x[46]-x[21]==0.0) - @NLconstraint(m, e51,x[42]*x[47]-x[22]==0.0) - @NLconstraint(m, e52,x[43]*x[47]-x[23]==0.0) - @NLconstraint(m, e53,x[40]*x[50]-x[28]==0.0) - @NLconstraint(m, e54,x[41]*x[50]-x[29]==0.0) - @NLconstraint(m, e55,x[42]*x[51]-x[30]==0.0) - @NLconstraint(m, e56,x[43]*x[51]-x[31]==0.0) - @NLconstraint(m, e57,x[14]*x[44]-x[1]==0.0) - @NLconstraint(m, e58,x[14]*x[45]-x[2]==0.0) - @NLconstraint(m, e59,x[15]*x[46]-x[3]==0.0) - @NLconstraint(m, e60,x[15]*x[47]-x[4]==0.0) - @NLconstraint(m, e61,x[14]*x[50]-x[7]==0.0) - @NLconstraint(m, e62,x[15]*x[51]-x[8]==0.0) + @NLconstraint(m, e45, x[40] * x[44] - x[16] == 0.0) + @NLconstraint(m, e46, x[41] * x[44] - x[17] == 0.0) + @NLconstraint(m, e47, x[40] * x[45] - x[18] == 0.0) + @NLconstraint(m, e48, x[41] * x[45] - x[19] == 0.0) + @NLconstraint(m, e49, x[42] * x[46] - x[20] == 0.0) + @NLconstraint(m, e50, x[43] * x[46] - x[21] == 0.0) + @NLconstraint(m, e51, x[42] * x[47] - x[22] == 0.0) + @NLconstraint(m, e52, x[43] * x[47] - x[23] == 0.0) + @NLconstraint(m, e53, x[40] * x[50] - x[28] == 0.0) + @NLconstraint(m, e54, x[41] * x[50] - x[29] == 0.0) + @NLconstraint(m, e55, x[42] * x[51] - x[30] == 0.0) + @NLconstraint(m, e56, x[43] * x[51] - x[31] == 0.0) + @NLconstraint(m, e57, x[14] * x[44] - x[1] == 0.0) + @NLconstraint(m, e58, x[14] * x[45] - x[2] == 0.0) + @NLconstraint(m, e59, x[15] * x[46] - x[3] == 0.0) + @NLconstraint(m, e60, x[15] * x[47] - x[4] == 0.0) + @NLconstraint(m, e61, x[14] * x[50] - x[7] == 0.0) + @NLconstraint(m, e62, x[15] * x[51] - x[8] == 0.0) - @constraint(m, e1, -x[14]-x[15]+obj==0.0) - @constraint(m, e2, -x[5]-x[9]-x[10]==-40.0) - @constraint(m, e3, -x[6]-x[11]-x[12]==-40.0) - @constraint(m, e4, -x[1]-x[3]-x[9]-x[11]+x[14]==0.0) - @constraint(m, e5, -x[2]-x[4]-x[10]-x[12]+x[15]==0.0) - @constraint(m, e6, -x[1]-x[2]-x[7]+x[14]==0.0) - @constraint(m, e7, -x[3]-x[4]-x[8]+x[15]==0.0) - @constraint(m, e8, -x[5]-x[6]-x[7]-x[8]+x[13]==0.0) - @constraint(m, e9, -x[24]-x[32]-x[34]==-4000.0) - @constraint(m, e10, -x[25]-x[33]-x[35]==-800.0) - @constraint(m, e11, -x[26]-x[36]-x[38]==-600.0) - @constraint(m, e12, -x[27]-x[37]-x[39]==-8000.0) - @constraint(m, e13, -x[32]+4000*x[52]==0.0) - @constraint(m, e14, -x[33]+800*x[52]==0.0) - @constraint(m, e15, -x[34]+4000*x[53]==0.0) - @constraint(m, e16, -x[35]+800*x[53]==0.0) - @constraint(m, e17, -x[36]+600*x[54]==0.0) - @constraint(m, e18, -x[37]+8000*x[54]==0.0) - @constraint(m, e19, -x[38]+600*x[55]==0.0) - @constraint(m, e20, -x[39]+8000*x[55]==0.0) - @constraint(m, e21, -x[24]+4000*x[48]==0.0) - @constraint(m, e22, -x[25]+800*x[48]==0.0) - @constraint(m, e23, -x[26]+600*x[49]==0.0) - @constraint(m, e24, -x[27]+8000*x[49]==0.0) - @constraint(m, e25, -x[9]+40*x[52]==0.0) - @constraint(m, e26, -x[10]+40*x[53]==0.0) - @constraint(m, e27, -x[11]+40*x[54]==0.0) - @constraint(m, e28, -x[12]+40*x[55]==0.0) - @constraint(m, e29, -x[5]+40*x[48]==0.0) - @constraint(m, e30, -x[6]+40*x[49]==0.0) - @constraint(m, e31, x[48]+x[52]+x[53]==1.0) - @constraint(m, e32, x[49]+x[54]+x[55]==1.0) - @constraint(m, e33, -200*x[14]+x[16]+x[20]+x[32]+x[36]<=0.0) - @constraint(m, e34, -200*x[14]+x[17]+x[21]+x[33]+x[37]<=0.0) - @constraint(m, e35, -200*x[15]+x[18]+x[22]+x[34]+x[38]<=0.0) - @constraint(m, e36, -200*x[15]+x[19]+x[23]+x[35]+x[39]<=0.0) - @constraint(m, e37, 0.05*x[16]+0.05*x[20]+0.05*x[32]+0.05*x[36]-x[40]==0.0) - @constraint(m, e38, x[17]+x[21]+x[33]+x[37]-x[41]==0.0) - @constraint(m, e39, x[18]+x[22]+x[34]+x[38]-x[42]==0.0) - @constraint(m, e40, 0.024*x[19]+0.024*x[23]+0.024*x[35]+0.024*x[39]-x[43]==0.0) - @constraint(m, e41, -x[16]-x[18]-x[28]+x[40]==0.0) - @constraint(m, e42, -x[17]-x[19]-x[29]+x[41]==0.0) - @constraint(m, e43, -x[20]-x[22]-x[30]+x[42]==0.0) - @constraint(m, e44, -x[21]-x[23]-x[31]+x[43]==0.0) - @constraint(m, e63, x[44]+x[45]+x[50]==1.0) - @constraint(m, e64, x[46]+x[47]+x[51]==1.0) - @constraint(m, e65, -10*x[13]+x[24]+x[26]+x[28]+x[30]<=0.0) - @constraint(m, e66, -10*x[13]+x[25]+x[27]+x[29]+x[31]<=0.0) + @constraint(m, e1, -x[14] - x[15] + obj == 0.0) + @constraint(m, e2, -x[5] - x[9] - x[10] == -40.0) + @constraint(m, e3, -x[6] - x[11] - x[12] == -40.0) + @constraint(m, e4, -x[1] - x[3] - x[9] - x[11] + x[14] == 0.0) + @constraint(m, e5, -x[2] - x[4] - x[10] - x[12] + x[15] == 0.0) + @constraint(m, e6, -x[1] - x[2] - x[7] + x[14] == 0.0) + @constraint(m, e7, -x[3] - x[4] - x[8] + x[15] == 0.0) + @constraint(m, e8, -x[5] - x[6] - x[7] - x[8] + x[13] == 0.0) + @constraint(m, e9, -x[24] - x[32] - x[34] == -4000.0) + @constraint(m, e10, -x[25] - x[33] - x[35] == -800.0) + @constraint(m, e11, -x[26] - x[36] - x[38] == -600.0) + @constraint(m, e12, -x[27] - x[37] - x[39] == -8000.0) + @constraint(m, e13, -x[32] + 4000 * x[52] == 0.0) + @constraint(m, e14, -x[33] + 800 * x[52] == 0.0) + @constraint(m, e15, -x[34] + 4000 * x[53] == 0.0) + @constraint(m, e16, -x[35] + 800 * x[53] == 0.0) + @constraint(m, e17, -x[36] + 600 * x[54] == 0.0) + @constraint(m, e18, -x[37] + 8000 * x[54] == 0.0) + @constraint(m, e19, -x[38] + 600 * x[55] == 0.0) + @constraint(m, e20, -x[39] + 8000 * x[55] == 0.0) + @constraint(m, e21, -x[24] + 4000 * x[48] == 0.0) + @constraint(m, e22, -x[25] + 800 * x[48] == 0.0) + @constraint(m, e23, -x[26] + 600 * x[49] == 0.0) + @constraint(m, e24, -x[27] + 8000 * x[49] == 0.0) + @constraint(m, e25, -x[9] + 40 * x[52] == 0.0) + @constraint(m, e26, -x[10] + 40 * x[53] == 0.0) + @constraint(m, e27, -x[11] + 40 * x[54] == 0.0) + @constraint(m, e28, -x[12] + 40 * x[55] == 0.0) + @constraint(m, e29, -x[5] + 40 * x[48] == 0.0) + @constraint(m, e30, -x[6] + 40 * x[49] == 0.0) + @constraint(m, e31, x[48] + x[52] + x[53] == 1.0) + @constraint(m, e32, x[49] + x[54] + x[55] == 1.0) + @constraint(m, e33, -200 * x[14] + x[16] + x[20] + x[32] + x[36] <= 0.0) + @constraint(m, e34, -200 * x[14] + x[17] + x[21] + x[33] + x[37] <= 0.0) + @constraint(m, e35, -200 * x[15] + x[18] + x[22] + x[34] + x[38] <= 0.0) + @constraint(m, e36, -200 * x[15] + x[19] + x[23] + x[35] + x[39] <= 0.0) + @constraint( + m, + e37, + 0.05 * x[16] + 0.05 * x[20] + 0.05 * x[32] + 0.05 * x[36] - x[40] == 0.0 + ) + @constraint(m, e38, x[17] + x[21] + x[33] + x[37] - x[41] == 0.0) + @constraint(m, e39, x[18] + x[22] + x[34] + x[38] - x[42] == 0.0) + @constraint( + m, + e40, + 0.024 * x[19] + 0.024 * x[23] + 0.024 * x[35] + 0.024 * x[39] - x[43] == 0.0 + ) + @constraint(m, e41, -x[16] - x[18] - x[28] + x[40] == 0.0) + @constraint(m, e42, -x[17] - x[19] - x[29] + x[41] == 0.0) + @constraint(m, e43, -x[20] - x[22] - x[30] + x[42] == 0.0) + @constraint(m, e44, -x[21] - x[23] - x[31] + x[43] == 0.0) + @constraint(m, e63, x[44] + x[45] + x[50] == 1.0) + @constraint(m, e64, x[46] + x[47] + x[51] == 1.0) + @constraint(m, e65, -10 * x[13] + x[24] + x[26] + x[28] + x[30] <= 0.0) + @constraint(m, e66, -10 * x[13] + x[25] + x[27] + x[29] + x[31] <= 0.0) return m end diff --git a/examples/MINLPs/circle.jl b/examples/MINLPs/circle.jl index 30b067dc..f08a1068 100644 --- a/examples/MINLPs/circle.jl +++ b/examples/MINLPs/circle.jl @@ -1,36 +1,76 @@ -function circle(;solver = nothing) - m = Model(solver) +function circle(; solver = nothing) + m = Model(solver) @variable(m, 0 <= x[1:2] <= 2) @NLconstraint(m, x[1]^2 + x[2]^2 >= 2) @objective(m, Min, x[1] + x[2]) - return m + return m end -function circle_MINLPLib(;solver = nothing) +function circle_MINLPLib(; solver = nothing) # Source: https://www.minlplib.org/circle.html # Above instance has been mofified to convert the problem into a non-convex NLP # Global solution: 4.45670663096, arg min = [4.2536125, 3.4367961] - m = Model(solver) + m = Model(solver) @variable(m, objvar >= 0) x_Idx = Any[1, 2] @variable(m, -10 <= x[x_Idx] <= 10) - @NLconstraint(m, e1, (2.545724188-x[1])^2+ (9.983058643-x[2])^2- (objvar)^2 >= 0.0) - @NLconstraint(m, e2, (8.589400372-x[1])^2+ (6.208600402-x[2])^2- (objvar)^2 >= 0.0) - @NLconstraint(m, e3, (5.953378204-x[1])^2+ (9.920197351-x[2])^2- (objvar)^2 >= 0.0) - @NLconstraint(m, e4, (3.710241136-x[1])^2+ (7.860254203-x[2])^2- (objvar)^2 >= 0.0) - @NLconstraint(m, e5, (3.629909053-x[1])^2+ (2.176232347-x[2])^2- (objvar)^2 <= 0.0) - @NLconstraint(m, e6, (3.016475803-x[1])^2+ (6.757468831-x[2])^2- (objvar)^2 <= 0.0) - @NLconstraint(m, e7, (4.148474536-x[1])^2+ (2.435660776-x[2])^2- (objvar)^2 <= 0.0) - @NLconstraint(m, e8, (8.706433123-x[1])^2+ (3.250724797-x[2])^2- (objvar)^2 <= 0.0) - @NLconstraint(m, e9, (1.604023507-x[1])^2+ (7.020357481-x[2])^2- (objvar)^2 <= 0.0) - @NLconstraint(m, e10, (5.501896021-x[1])^2+ (4.918207429-x[2])^2- (objvar)^2 <= 0.0) + @NLconstraint( + m, + e1, + (2.545724188 - x[1])^2 + (9.983058643 - x[2])^2 - (objvar)^2 >= 0.0 + ) + @NLconstraint( + m, + e2, + (8.589400372 - x[1])^2 + (6.208600402 - x[2])^2 - (objvar)^2 >= 0.0 + ) + @NLconstraint( + m, + e3, + (5.953378204 - x[1])^2 + (9.920197351 - x[2])^2 - (objvar)^2 >= 0.0 + ) + @NLconstraint( + m, + e4, + (3.710241136 - x[1])^2 + (7.860254203 - x[2])^2 - (objvar)^2 >= 0.0 + ) + @NLconstraint( + m, + e5, + (3.629909053 - x[1])^2 + (2.176232347 - x[2])^2 - (objvar)^2 <= 0.0 + ) + @NLconstraint( + m, + e6, + (3.016475803 - x[1])^2 + (6.757468831 - x[2])^2 - (objvar)^2 <= 0.0 + ) + @NLconstraint( + m, + e7, + (4.148474536 - x[1])^2 + (2.435660776 - x[2])^2 - (objvar)^2 <= 0.0 + ) + @NLconstraint( + m, + e8, + (8.706433123 - x[1])^2 + (3.250724797 - x[2])^2 - (objvar)^2 <= 0.0 + ) + @NLconstraint( + m, + e9, + (1.604023507 - x[1])^2 + (7.020357481 - x[2])^2 - (objvar)^2 <= 0.0 + ) + @NLconstraint( + m, + e10, + (5.501896021 - x[1])^2 + (4.918207429 - x[2])^2 - (objvar)^2 <= 0.0 + ) @objective(m, Min, objvar) - return m + return m end diff --git a/examples/MINLPs/convex.jl b/examples/MINLPs/convex.jl index a0a5ae13..ce34270d 100644 --- a/examples/MINLPs/convex.jl +++ b/examples/MINLPs/convex.jl @@ -1,63 +1,70 @@ -function convex_test(;solver = nothing) - - m = Model(solver) - - @variable(m, 0<=x[1:5]<=2) - - @constraint(m, 3*x[1]*x[1] + 4*x[2]*x[2] <= 25) # 1: true - @constraint(m, 3*x[1]*x[1] - 25 + 4*x[2]*x[2] <= 0) # 2: true - @constraint(m, 3(x[1]x[1]) + 4*x[2]*x[2] <= -5) # 3: false - @constraint(m, 3(x[1]x[1]) + 4*x[2]^2 <= 10) # 4: true - @constraint(m, 3x[1]^2 + 4x[2]^2 + 6x[3]^2 <= 10) # 5: true - - @NLconstraint(m, 3x[1]^0.5 + 4x[2]^0.5 + 5x[5]^0.5 <= 100) # 6: true | type-C - @NLconstraint(m, -3x[1]^0.5 -4x[2]^0.5 >= -100) # 7: true | type-C - @NLconstraint(m, 3x[1]^3 + x[2]^3 + 5x[3]^3 <= 200) # 8: true | type-a - @NLconstraint(m, x[1]*x[1]*x[1] + x[2]*x[2]*x[2] + x[3]*x[3]*x[3] + 5*x[4]*20*x[4]*x[4] <= 200) # 9: true - @NLconstraint(m, 3*x[1]*x[1] + 4*x[2]*x[2] <= 25) # 10: true - - @NLconstraint(m, (3*x[1]*x[1] + 4*x[2]*x[2]) <= 25) # 11: true - @NLconstraint(m, 3*x[1]*x[1] + 4*x[2]*x[2] - 25 <= 0) # 12: true - @NLconstraint(m, -3*x[1]*x[1] -4*x[2]*x[2] >= -25) # 13: true - @NLconstraint(m, 3*x[1]*x[1] + 5x[2]*x[2] <= 25) # 14: true - @NLconstraint(m, x[1]*3*x[1] + x[2]*x[2]*5 + x[4]^(3-1) <= 25) # 15: true - - @NLconstraint(m, 4*x[1]^2 + 5x[2]^2 <= 25) # 16: true - @NLconstraint(m, 3*x[1]*x[1] - 25 + 4*x[2]*x[2] <= 0) # 17: false (unsupported when with @NLconstraint) - @NLconstraint(m, 3*x[1]*x[1] + 4*x[2]*x[1] <= 25) # 18: false - @NLconstraint(m, 3*x[1]*x[1] + 16*x[2]^2 <= 40) # 19: true - @NLconstraint(m, 3*x[1]^2 + 16*x[2]^2 + 17 <= 16) # 20: false - - @NLconstraint(m, 3*x[1]^3 + 16*x[2]^2 <= 20 - 20) # 21: false - @NLconstraint(m, 3*x[1]*x[1] + 4*x[2]*x[2] + 5*x[3]*x[3] + 6x[4]x[4] <= 15) # 22: true - @NLconstraint(m, 3x[1]x[1] + 4x[2]x[2] + 5x[3]^2 <= -15) # 23: false - @NLconstraint(m, 3x[1]^2 + 4x[2]^2 >= 15) # 24: false - @NLconstraint(m, sum(x[i]^2 for i in 1:5) <= 99999) # 25: true - - @NLconstraint(m, 3x[1]^4 + 4x[2]^4 <= 200) # 26: true - @NLconstraint(m, 3x[1]^4 + 4x[2]x[2]x[2]x[2] - 200 <= 0) # 27: true - @NLconstraint(m, 3x[1]^4 + 4x[2]^2*x[2]*x[2] <= 200) # 28: true - @NLconstraint(m, 3x[1]^4 + 4x[2]^3 <= 200) # 29: false - @NLconstraint(m, 3x[1]^8 + 16*25*x[2]^8 - 30x[3]^8 <= 50) # 30: false - - @objective(m, Max, x[1]^2+x[3]^2) # true - - return m +function convex_test(; solver = nothing) + m = Model(solver) + + @variable(m, 0 <= x[1:5] <= 2) + + @constraint(m, 3 * x[1] * x[1] + 4 * x[2] * x[2] <= 25) # 1: true + @constraint(m, 3 * x[1] * x[1] - 25 + 4 * x[2] * x[2] <= 0) # 2: true + @constraint(m, 3(x[1]x[1]) + 4 * x[2] * x[2] <= -5) # 3: false + @constraint(m, 3(x[1]x[1]) + 4 * x[2]^2 <= 10) # 4: true + @constraint(m, 3x[1]^2 + 4x[2]^2 + 6x[3]^2 <= 10) # 5: true + + @NLconstraint(m, 3x[1]^0.5 + 4x[2]^0.5 + 5x[5]^0.5 <= 100)# 6: true | type-C + @NLconstraint(m, -3x[1]^0.5 - 4x[2]^0.5 >= -100)# 7: true | type-C + @NLconstraint(m, 3x[1]^3 + x[2]^3 + 5x[3]^3 <= 200) # 8: true | type-a + @NLconstraint( + m, + x[1] * x[1] * x[1] + + x[2] * x[2] * x[2] + + x[3] * x[3] * x[3] + + 5 * x[4] * 20 * x[4] * x[4] <= 200 + ) # 9: true + @NLconstraint(m, 3 * x[1] * x[1] + 4 * x[2] * x[2] <= 25) # 10: true + + @NLconstraint(m, (3 * x[1] * x[1] + 4 * x[2] * x[2]) <= 25) # 11: true + @NLconstraint(m, 3 * x[1] * x[1] + 4 * x[2] * x[2] - 25 <= 0) # 12: true + @NLconstraint(m, -3 * x[1] * x[1] - 4 * x[2] * x[2] >= -25) # 13: true + @NLconstraint(m, 3 * x[1] * x[1] + 5x[2] * x[2] <= 25) # 14: true + @NLconstraint(m, x[1] * 3 * x[1] + x[2] * x[2] * 5 + x[4]^(3 - 1) <= 25) # 15: true + + @NLconstraint(m, 4 * x[1]^2 + 5x[2]^2 <= 25) # 16: true + @NLconstraint(m, 3 * x[1] * x[1] - 25 + 4 * x[2] * x[2] <= 0) # 17: false (unsupported when with @NLconstraint) + @NLconstraint(m, 3 * x[1] * x[1] + 4 * x[2] * x[1] <= 25) # 18: false + @NLconstraint(m, 3 * x[1] * x[1] + 16 * x[2]^2 <= 40) # 19: true + @NLconstraint(m, 3 * x[1]^2 + 16 * x[2]^2 + 17 <= 16) # 20: false + + @NLconstraint(m, 3 * x[1]^3 + 16 * x[2]^2 <= 20 - 20) # 21: false + @NLconstraint( + m, + 3 * x[1] * x[1] + 4 * x[2] * x[2] + 5 * x[3] * x[3] + 6x[4]x[4] <= 15 + ) # 22: true + @NLconstraint(m, 3x[1]x[1] + 4x[2]x[2] + 5x[3]^2 <= -15) # 23: false + @NLconstraint(m, 3x[1]^2 + 4x[2]^2 >= 15) # 24: false + @NLconstraint(m, sum(x[i]^2 for i in 1:5) <= 99999) # 25: true + + @NLconstraint(m, 3x[1]^4 + 4x[2]^4 <= 200) # 26: true + @NLconstraint(m, 3x[1]^4 + 4x[2]x[2]x[2]x[2] - 200 <= 0) # 27: true + @NLconstraint(m, 3x[1]^4 + 4x[2]^2 * x[2] * x[2] <= 200) # 28: true + @NLconstraint(m, 3x[1]^4 + 4x[2]^3 <= 200) # 29: false + @NLconstraint(m, 3x[1]^8 + 16 * 25 * x[2]^8 - 30x[3]^8 <= 50) # 30: false + + @objective(m, Max, x[1]^2 + x[3]^2) # true + + return m end -function convex_solve(;solver = nothing) +function convex_solve(; solver = nothing) + m = Model(solver) - m = Model(solver) + @variable(m, 0 <= x[1:5] <= 100) - @variable(m, 0<=x[1:5]<=100) + @NLconstraint(m, 3 * x[1] * x[1] + 4 * x[2] * x[2] <= 25) # 1: true + @NLconstraint(m, 3(x[1]x[1]) + 4 * x[2]^2 <= 10) # 4: true + @NLconstraint(m, 3x[1]^2 + 4x[2]^2 + 6x[3]^2 <= 10) # 5: true + @NLconstraint(m, (x[1] + x[2])^2 <= 100) + @NLconstraint(m, -3 * x[1] * x[1] - 4 * x[2] * x[2] >= -25) # 13: true - @NLconstraint(m, 3*x[1]*x[1] + 4*x[2]*x[2] <= 25) # 1: true - @NLconstraint(m, 3(x[1]x[1]) + 4*x[2]^2 <= 10) # 4: true - @NLconstraint(m, 3x[1]^2 + 4x[2]^2 + 6x[3]^2 <= 10) # 5: true - @NLconstraint(m, (x[1]+x[2])^2 <= 100) - @NLconstraint(m, -3*x[1]*x[1] -4*x[2]*x[2] >= -25) # 13: true + @objective(m, Max, x[1]^2 + x[3]^2) # true - @objective(m, Max, x[1]^2+x[3]^2) # true - - return m + return m end diff --git a/examples/MINLPs/discretemulti.jl b/examples/MINLPs/discretemulti.jl index 172192c5..09df1e84 100644 --- a/examples/MINLPs/discretemulti.jl +++ b/examples/MINLPs/discretemulti.jl @@ -1,163 +1,161 @@ -function binprod_nlp3(;solver = nothing) - - m = Model(solver) - - LB = [100, 1000, 1000, 10, 10, 10, 10, 10] - UB = [10000, 10000, 10000, 1000, 1000, 1000, 1000, 1000] - - @variable(m, LB[i] <= x[i=1:8] <= UB[i]) - @variable(m, 0 <= y[1:5] <= 1, Bin) - - @constraint(m, 0.0025*(x[4]*y[1] + x[6]*y[2]) <= 1) - @constraint(m, 0.0025*(x[5] - x[4]*y[1] + x[7]) <= 1) - @constraint(m, 0.01(x[8]-x[5]*y[3]) <= 1) - @NLconstraint(m, 100*x[1] - x[1]*x[6]*y[1] + 833.33252*x[4]*y[1] <= 83333.333) - @NLconstraint(m, x[2]*x[4]*y[4] - x[2]*x[7] - 1250*x[4] + 1250*x[5] <= 0) - @NLconstraint(m, x[3]*x[5]*y[2]*y[5] - x[3]*x[8]*y[5] - 2500*x[5]*y[1]*y[4] + 1250000 <= 0) - - @NLconstraint(m, y[1]*y[2]*y[3] <= 0) - @NLconstraint(m, y[2]*y[3] >= y[4]*y[5]) - @NLconstraint(m, y[1]*y[5] <= y[2]*y[4]) - - @objective(m, Min, x[1]+x[2]+x[3]) - - return m +function binprod_nlp3(; solver = nothing) + m = Model(solver) + + LB = [100, 1000, 1000, 10, 10, 10, 10, 10] + UB = [10000, 10000, 10000, 1000, 1000, 1000, 1000, 1000] + + @variable(m, LB[i] <= x[i = 1:8] <= UB[i]) + @variable(m, 0 <= y[1:5] <= 1, Bin) + + @constraint(m, 0.0025 * (x[4] * y[1] + x[6] * y[2]) <= 1) + @constraint(m, 0.0025 * (x[5] - x[4] * y[1] + x[7]) <= 1) + @constraint(m, 0.01(x[8] - x[5] * y[3]) <= 1) + @NLconstraint( + m, + 100 * x[1] - x[1] * x[6] * y[1] + 833.33252 * x[4] * y[1] <= 83333.333 + ) + @NLconstraint(m, x[2] * x[4] * y[4] - x[2] * x[7] - 1250 * x[4] + 1250 * x[5] <= 0) + @NLconstraint( + m, + x[3] * x[5] * y[2] * y[5] - x[3] * x[8] * y[5] - 2500 * x[5] * y[1] * y[4] + + 1250000 <= 0 + ) + + @NLconstraint(m, y[1] * y[2] * y[3] <= 0) + @NLconstraint(m, y[2] * y[3] >= y[4] * y[5]) + @NLconstraint(m, y[1] * y[5] <= y[2] * y[4]) + + @objective(m, Min, x[1] + x[2] + x[3]) + + return m end -function circlebin(;verbose = false, solver = nothing) - - m = Model(solver) +function circlebin(; verbose = false, solver = nothing) + m = Model(solver) @variable(m, 0 <= x[1:5] <= 1, Bin) @NLconstraint(m, x[1]^2 + x[2]^2 >= 2) - @objective(m, Min, x[1]+x[2]) + @objective(m, Min, x[1] + x[2]) - return m + return m end -function bpml(;verbose = false, solver = nothing) - - m = Model(solver) +function bpml(; verbose = false, solver = nothing) + m = Model(solver) - @variable(m, 0 <= x[1:5] <= 1, Bin) - @variable(m, y[1:5]>=0) + @variable(m, 0 <= x[1:5] <= 1, Bin) + @variable(m, y[1:5] >= 0) - @NLconstraint(m, x[1]*y[1] >= 10) - @NLconstraint(m, x[1]*x[2]*y[1] >= 10) - @NLconstraint(m, x[1]*x[2]*x[3]*y[1] >= 10) - @NLconstraint(m, x[1]*y[1]*y[2] >= 10) - @NLconstraint(m, x[1]*y[1]*y[2]*y[3] >= 10) - @NLconstraint(m, x[1]*x[2]*x[3]*y[1]*y[2]*y[3] >= 10) - @NLconstraint(m, x[1]*x[2]*x[3]*x[4]*x[5] >= 1) - @NLconstraint(m, y[1]*y[2]*y[4]*y[5]*y[1] >= 99) + @NLconstraint(m, x[1] * y[1] >= 10) + @NLconstraint(m, x[1] * x[2] * y[1] >= 10) + @NLconstraint(m, x[1] * x[2] * x[3] * y[1] >= 10) + @NLconstraint(m, x[1] * y[1] * y[2] >= 10) + @NLconstraint(m, x[1] * y[1] * y[2] * y[3] >= 10) + @NLconstraint(m, x[1] * x[2] * x[3] * y[1] * y[2] * y[3] >= 10) + @NLconstraint(m, x[1] * x[2] * x[3] * x[4] * x[5] >= 1) + @NLconstraint(m, y[1] * y[2] * y[4] * y[5] * y[1] >= 99) - @objective(m, Min, x[1]+x[2]+x[3]) + @objective(m, Min, x[1] + x[2] + x[3]) - return m + return m end -function bmpl_linearlifting(;solver = nothing) - - m = Model(solver) +function bmpl_linearlifting(; solver = nothing) + m = Model(solver) - @variable(m, 0 <= x[1:5] <= 1, Bin) - @variable(m, y[1:5]>=0) + @variable(m, 0 <= x[1:5] <= 1, Bin) + @variable(m, y[1:5] >= 0) - @NLconstraint(m, 15*x[1]*(2*y[1]+y[2]) >= 10) - @NLconstraint(m, 15*(x[1]+x[2]*y[1])*(y[1]+y[2]*x[1]*x[2]) + 10 >= 10) - @NLconstraint(m, 15*x[2]*(y[1]+y[2]*x[3]*y[5]*x[4]) + 50 >= 10) + @NLconstraint(m, 15 * x[1] * (2 * y[1] + y[2]) >= 10) + @NLconstraint(m, 15 * (x[1] + x[2] * y[1]) * (y[1] + y[2] * x[1] * x[2]) + 10 >= 10) + @NLconstraint(m, 15 * x[2] * (y[1] + y[2] * x[3] * y[5] * x[4]) + 50 >= 10) - @NLobjective(m, Min, x[1] * (y[1]*y[2]*y[3] + x[2]*x[3])) + @NLobjective(m, Min, x[1] * (y[1] * y[2] * y[3] + x[2] * x[3])) - return m + return m end -function bpml_lnl(;solver = nothing) - - m = Model(solver) +function bpml_lnl(; solver = nothing) + m = Model(solver) - Random.seed!(10) - @variable(m, 0 <= X[1:5] <= 1, Bin) - @variable(m, 0.1<=Y[1:5]<=0.1+10*rand()) - @constraint(m, sum(X) >= 3) - @NLobjective(m, Min, sum(X[i]*Y[i] for i in 1:5)) + Random.seed!(10) + @variable(m, 0 <= X[1:5] <= 1, Bin) + @variable(m, 0.1 <= Y[1:5] <= 0.1 + 10 * rand()) + @constraint(m, sum(X) >= 3) + @NLobjective(m, Min, sum(X[i] * Y[i] for i in 1:5)) - return m + return m end -function bpml_binl(;solver = nothing) - - m = Model(solver) +function bpml_binl(; solver = nothing) + m = Model(solver) - Random.seed!(10) - @variable(m, 0 <= X[1:5] <= 1, Bin) - @variable(m, 50 <= Y[1:5] <= 50+100*rand()*rand()) - @constraint(m, sum(X) >= 3) - @NLobjective(m, Max, sum(X[i]*Y[i]*Y[i+1] for i in 1:4) - X[5]*Y[5]*Y[1]) + Random.seed!(10) + @variable(m, 0 <= X[1:5] <= 1, Bin) + @variable(m, 50 <= Y[1:5] <= 50 + 100 * rand() * rand()) + @constraint(m, sum(X) >= 3) + @NLobjective(m, Max, sum(X[i] * Y[i] * Y[i+1] for i in 1:4) - X[5] * Y[5] * Y[1]) - return m + return m end -function bpml_monl(;solver = nothing) +function bpml_monl(; solver = nothing) + m = Model(solver) - m = Model(solver) + Random.seed!(10) + @variable(m, 0 <= X[1:5] <= 1, Bin) + @variable(m, 50 <= Y[1:5] <= 50 + 100 * rand() * rand()) + @constraint(m, sum(X) >= 3) + @NLobjective(m, Max, sum(X[i] * Y[i] * Y[i] for i in 1:5)) - Random.seed!(10) - @variable(m, 0 <= X[1:5] <= 1, Bin) - @variable(m, 50<=Y[1:5]<=50+100*rand()*rand()) - @constraint(m, sum(X) >= 3) - @NLobjective(m, Max, sum(X[i]*Y[i]*Y[i] for i in 1:5)) - - return m + return m end -function bpml_negative(;solver = nothing) - - m = Model(solver) - - Random.seed!(10) - @variable(m, 0 <= X[1:5] <= 1, Bin) - @variable(m, 50<=Y[1:5]<=50+100*rand()*rand()) - JuMP.set_lower_bound(Y[1], -10) - JuMP.set_upper_bound(Y[1], -1) - JuMP.set_lower_bound(Y[2], -40) - JuMP.set_lower_bound(Y[3], -30) - JuMP.set_lower_bound(Y[4], -50) - @constraint(m, sum(X) >= 3) - @NLobjective(m, Max, sum(X[i]*Y[i]*Y[i+1] for i in 1:4) - X[5]*Y[5]*Y[1]) - - return m +function bpml_negative(; solver = nothing) + m = Model(solver) + + Random.seed!(10) + @variable(m, 0 <= X[1:5] <= 1, Bin) + @variable(m, 50 <= Y[1:5] <= 50 + 100 * rand() * rand()) + JuMP.set_lower_bound(Y[1], -10) + JuMP.set_upper_bound(Y[1], -1) + JuMP.set_lower_bound(Y[2], -40) + JuMP.set_lower_bound(Y[3], -30) + JuMP.set_lower_bound(Y[4], -50) + @constraint(m, sum(X) >= 3) + @NLobjective(m, Max, sum(X[i] * Y[i] * Y[i+1] for i in 1:4) - X[5] * Y[5] * Y[1]) + + return m end -function intprod_basic(;solver = nothing) - m = Model(solver) +function intprod_basic(; solver = nothing) + m = Model(solver) - @variable(m, 1 <= Z[1:10] <= 10, Int) - @NLconstraint(m, (Z[1]+Z[2])*(Z[3]+Z[4]) >= 25) - @NLconstraint(m, Z[1]*(Z[2]+Z[3])*Z[4] >= 25) - @NLconstraint(m, Z[1]-Z[2]*Z[3]*Z[4]+15 >= 25) - @NLconstraint(m, Z[5]*(Z[2]-Z[3])*Z[5]^2 >= 40) - @NLobjective(m, Min, sum(Z[i] for i in 1:5)*Z[2]) + @variable(m, 1 <= Z[1:10] <= 10, Int) + @NLconstraint(m, (Z[1] + Z[2]) * (Z[3] + Z[4]) >= 25) + @NLconstraint(m, Z[1] * (Z[2] + Z[3]) * Z[4] >= 25) + @NLconstraint(m, Z[1] - Z[2] * Z[3] * Z[4] + 15 >= 25) + @NLconstraint(m, Z[5] * (Z[2] - Z[3]) * Z[5]^2 >= 40) + @NLobjective(m, Min, sum(Z[i] for i in 1:5) * Z[2]) - return m + return m end -function discretemulti_basic(;solver = nothing) - - m = Model(solver) - - Random.seed!(10) - @variable(m, 0 <= X[1:5] <= 1, Bin) - @variable(m, 0.1<=Y[1:5]<=0.1+10*rand()) - @variable(m, 1<=Z[1:5]<=10, Int) - @constraint(m, sum(X) >= 3) - @constraint(m, sum(Z) >= 10) - @NLobjective(m, Min, sum(X[i]*Y[i] for i in 1:5)) - @NLconstraint(m, sum(X[i]*Z[i] for i in 1:5) >= 8) - @NLconstraint(m, [i in 1:5], Y[i]*Z[i] >= 17.1) - @NLconstraint(m, [i in 1:4], Y[i]*Z[i]*Z[i+1] >= 18.6) - @NLconstraint(m, [i in 1:5], X[i]*Y[i]*Z[i] <= 28.1) - @NLconstraint(m, [i in 1:4], X[i]*X[i+1]*Y[i]*Y[i+1]*Z[i]*Z[i+1] <= 33.2) - - return m +function discretemulti_basic(; solver = nothing) + m = Model(solver) + + Random.seed!(10) + @variable(m, 0 <= X[1:5] <= 1, Bin) + @variable(m, 0.1 <= Y[1:5] <= 0.1 + 10 * rand()) + @variable(m, 1 <= Z[1:5] <= 10, Int) + @constraint(m, sum(X) >= 3) + @constraint(m, sum(Z) >= 10) + @NLobjective(m, Min, sum(X[i] * Y[i] for i in 1:5)) + @NLconstraint(m, sum(X[i] * Z[i] for i in 1:5) >= 8) + @NLconstraint(m, [i in 1:5], Y[i] * Z[i] >= 17.1) + @NLconstraint(m, [i in 1:4], Y[i] * Z[i] * Z[i+1] >= 18.6) + @NLconstraint(m, [i in 1:5], X[i] * Y[i] * Z[i] <= 28.1) + @NLconstraint(m, [i in 1:4], X[i] * X[i+1] * Y[i] * Y[i+1] * Z[i] * Z[i+1] <= 33.2) + + return m end diff --git a/examples/MINLPs/div.jl b/examples/MINLPs/div.jl index 17d358d0..d016a676 100644 --- a/examples/MINLPs/div.jl +++ b/examples/MINLPs/div.jl @@ -1,22 +1,33 @@ -function div(;verbose = false,solver = nothing) +function div(; verbose = false, solver = nothing) + m = Model(solver) - m = Model(solver) + @variable(m, 1 <= x[1:2] <= 10) - @variable(m, 1<=x[1:2]<=10) + @NLobjective(m, Min, 6 * x[1]^2 + 4 * x[2]^2 - 2.5 / 5 * x[1] * x[2]) - @NLobjective(m, Min, 6*x[1]^2 + 4*x[2]^2 - 2.5/5*x[1]*x[2]) + @constraint(m, x[1] * (-1 * 3 / 5 * 5) >= 0) + @constraint(m, x[2] * 5 / 20 >= 0) + @constraint(m, x[2] * (5 * 15 / 15) >= 0) + @constraint(m, x[2] * (120 * 2 / -2) >= 0) + @constraint(m, 1 * 2 * 3 * 4 * 5 * 6 * x[2] / 0.01 >= 0) + @constraint(m, x[1] * 1 * 2 * 3 * 4 * 5 * 6 / 0.01 >= 0) + @NLconstraint(m, (3 / 5) * x[1] * (60 / 60) * x[2] >= 8) + @NLconstraint( + m, + (1 * 2 * 3 * 4 / 5 / 6 * 7) * x[2] - x[1] * 1 * 2 * 3 * 4 * 5 * 6 * x[2] / 0.01 >= + 0 + ) + @NLconstraint( + m, + (1 * 2 * 3 * 4 / 5 / 6 * 7) * x[2] - + 0.5(x[1] * 1 * 2 * 3 * 4 * 5 * 6 * x[2] / 0.01) >= 0 + ) + @NLconstraint( + m, + (1 * 2 * 3 * 4 / 5 / 6 * 7) * x[2] - + 0.5(x[1] * 2 * 3 * x[2] / 0.01 + 5 * 7 / 10 * x[2]) >= 0 + ) + @NLconstraint(m, (1 * 2 * 3 * 4 / 5 / 6 * 7) * x[2] - 0.5 * (x[1] - x[2]x[1]) >= 0) - @constraint(m, x[1]*(-1*3/5*5) >= 0) - @constraint(m, x[2]*5/20 >= 0) - @constraint(m, x[2]*(5*15/15) >= 0) - @constraint(m, x[2]*(120*2/-2) >= 0) - @constraint(m, 1*2*3*4*5*6*x[2]/0.01>=0) - @constraint(m, x[1]*1*2*3*4*5*6/0.01>=0) - @NLconstraint(m, (3/5)*x[1]*(60/60)*x[2] >= 8) - @NLconstraint(m, (1*2*3*4/5/6*7)*x[2]-x[1]*1*2*3*4*5*6*x[2]/0.01>=0) - @NLconstraint(m, (1*2*3*4/5/6*7)*x[2]-0.5(x[1]*1*2*3*4*5*6*x[2]/0.01)>=0) - @NLconstraint(m, (1*2*3*4/5/6*7)*x[2]-0.5(x[1]*2*3*x[2]/0.01+5*7/10*x[2])>=0) - @NLconstraint(m, (1*2*3*4/5/6*7)*x[2]-0.5*(x[1]-x[2]x[1])>=0) - - return m + return m end diff --git a/examples/MINLPs/exprstest.jl b/examples/MINLPs/exprstest.jl index 76048d32..77be678a 100644 --- a/examples/MINLPs/exprstest.jl +++ b/examples/MINLPs/exprstest.jl @@ -1,185 +1,203 @@ -function exprstest(;solver = nothing) - - m = Model(solver) - - @variable(m, px[i=1:6]>=1) # At some point if an initial value is given, keep them - - @NLconstraint(m, sum(3*px[i]^2 for i=1:4) >= 111) - @NLconstraint(m, -px[1] * px[2] + 4*5*px[3]*px[4] >= 222) - @NLconstraint(m, -px[1] * px[2] <= 115) - @NLconstraint(m, -px[1] * -px[2] >= 115) - @NLconstraint(m, px[1] * -px[2] <= 115) - @constraint(m, -px[1] + (-5) - 4 <= 100) - @NLconstraint(m, px[1]+ px[2]*px[3] >= 555) # => px[1] + x23 >= 555 && x23 == px[2]*px[3] - @NLconstraint(m, px[1]^2 - 7*px[2]^2 + px[3]^2 + px[4] <= 6666) - @NLconstraint(m, 13*px[1] - px[2] + 5*px[3]*6 + px[4] >= 77) - - @NLobjective(m, Min, 7*px[1]*6*px[4]*2+5+17+px[1]+px[2]+px[3]+8+3*5*px[1]^2*4) - - return m +function exprstest(; solver = nothing) + m = Model(solver) + + @variable(m, px[i = 1:6] >= 1) # At some point if an initial value is given, keep them + + @NLconstraint(m, sum(3 * px[i]^2 for i in 1:4) >= 111) + @NLconstraint(m, -px[1] * px[2] + 4 * 5 * px[3] * px[4] >= 222) + @NLconstraint(m, -px[1] * px[2] <= 115) + @NLconstraint(m, -px[1] * -px[2] >= 115) + @NLconstraint(m, px[1] * -px[2] <= 115) + @constraint(m, -px[1] + (-5) - 4 <= 100) + @NLconstraint(m, px[1] + px[2] * px[3] >= 555) # => px[1] + x23 >= 555 && x23 == px[2]*px[3] + @NLconstraint(m, px[1]^2 - 7 * px[2]^2 + px[3]^2 + px[4] <= 6666) + @NLconstraint(m, 13 * px[1] - px[2] + 5 * px[3] * 6 + px[4] >= 77) + + @NLobjective( + m, + Min, + 7 * px[1] * 6 * px[4] * 2 + + 5 + + 17 + + px[1] + + px[2] + + px[3] + + 8 + + 3 * 5 * px[1]^2 * 4 + ) + + return m end -function operator_b(;solver = nothing) - - m = Model(solver) - - @variable(m, x[1:4]>=0) - @variable(m, y[1:3]<=0) - # PARSING TARGETS # - @constraint(m, x[1] + x[2] + -y[1] >= 1) # None - @constraint(m, 5x[1] + 8x[2] + 9y[2] <= 2) # None - @constraint(m, 4*x[1] + 5*x[2] + -3*y[1] >= 3) # None - # @constraint(m, 3 <= x[1] + x[2] <= 4) # None - - @NLconstraint(m, x[1]*x[2] + 3*x[2]*x[3] >= 5) # x[1]*x[2] and 3*x[2]*x[3] - @NLconstraint(m, x[1]*(x[2]+4) + 10*44*x[2]*5*x[3] <= 6) # x[2]*x[3] - @NLconstraint(m, x[1]*4 + x[2]*(x[2]+x[3]) >= 7) # None - @NLconstraint(m, 3*x[1]*x[2] + x[2] - x[3] <= 8) # x[1]*x[2] - - @NLconstraint(m, -1*x[1]^2 - x[2]^2 >= 9) # x[1]^2 and x[2]^2 - @NLconstraint(m, x[1]^(1+1) + 5*x[2]^2 + 3*x[3]^3 <= 10) # x[1]^2 and x[2]^2 - @NLconstraint(m, (x[1]+5)^2 >= 11) # None - @NLconstraint(m, x[1]^3 + x[3]^99 >= 12) # None - - @NLconstraint(m, x[1]*x[2]*x[3] <= 13) # x[1]*x[2]*x[3] - @NLconstraint(m, (x[1]*x[2])*x[3] >= 14) # x[1]*x[2] ****** - @NLconstraint(m, x[1]*(x[2]*x[3]) <= 15) # x[2]*x[3] ****** - @NLconstraint(m, x[1]*x[2]*x[3]*x[4] >= 16) # x[1]*x[2]*x[3]*x[4] - @NLconstraint(m, (x[1]*x[2])*(x[3]*x[4]) <= 17) # x[1]*x[2] and x[3]*x[4] - @NLconstraint(m, x[1]*(x[2]*x[3])*x[4] >= 18) # x[2]*x[3] ****** - @NLconstraint(m, (x[1]*x[2])*x[3]*x[4] <= 19) # x[1]*x[2] ****** - @NLconstraint(m, ((x[1]*x[2])*x[3])*x[4] >= 20) # x[1]*x[2] ****** - @NLconstraint(m, (x[1]*(x[2]*x[3])*x[4]) <= 21) # x[2]*x[3] ****** - - @NLconstraint(m, 4*5*6*x[1]*x[2]*x[3]*x[4] >= 22) # x[1]*x[2]*x[3]*x[4] - @NLconstraint(m, x[1]^2*x[2]^2*x[3]^2*x[4] <= 23) # None - @NLconstraint(m, x[1]*x[1]*x[2]*x[2]*x[3]*x[3] >= 24) # x[1]*x[1]*x[2]*x[2]*x[3]*x[3] - @NLconstraint(m, (x[1]+1)*(x[2]+2)*(x[3]+3)*(x[4]+4) <= 25) # None - - @NLconstraint(m, 50sin(x[1]) - 32*cos(x[2]) >= 26) # sin(x[1]), cos(x[2]) - @NLconstraint(m, sin(x[1]+x[2]) - cos(x[2]-x[3]) + sin(-x[2]+x[3]) <= 27) - @NLconstraint(m, sin(4*x[1]*x[2]) + cos(x[2]*-1*x[3]) >= 28)# x[1]*x[2] and x[2]*-1*x[3] ****** - @NLconstraint(m, sin(x[1]*x[2]*x[3]) <= 29) # x[1]*x[2]*x[3] - - return m +function operator_b(; solver = nothing) + m = Model(solver) + + @variable(m, x[1:4] >= 0) + @variable(m, y[1:3] <= 0) + # PARSING TARGETS # + @constraint(m, x[1] + x[2] + -y[1] >= 1)# None + @constraint(m, 5x[1] + 8x[2] + 9y[2] <= 2)# None + @constraint(m, 4 * x[1] + 5 * x[2] + -3 * y[1] >= 3)# None + # @constraint(m, 3 <= x[1] + x[2] <= 4) # None + + @NLconstraint(m, x[1] * x[2] + 3 * x[2] * x[3] >= 5)# x[1]*x[2] and 3*x[2]*x[3] + @NLconstraint(m, x[1] * (x[2] + 4) + 10 * 44 * x[2] * 5 * x[3] <= 6)# x[2]*x[3] + @NLconstraint(m, x[1] * 4 + x[2] * (x[2] + x[3]) >= 7)# None + @NLconstraint(m, 3 * x[1] * x[2] + x[2] - x[3] <= 8)# x[1]*x[2] + + @NLconstraint(m, -1 * x[1]^2 - x[2]^2 >= 9)# x[1]^2 and x[2]^2 + @NLconstraint(m, x[1]^(1 + 1) + 5 * x[2]^2 + 3 * x[3]^3 <= 10)# x[1]^2 and x[2]^2 + @NLconstraint(m, (x[1] + 5)^2 >= 11)# None + @NLconstraint(m, x[1]^3 + x[3]^99 >= 12)# None + + @NLconstraint(m, x[1] * x[2] * x[3] <= 13)# x[1]*x[2]*x[3] + @NLconstraint(m, (x[1] * x[2]) * x[3] >= 14)# x[1]*x[2] ****** + @NLconstraint(m, x[1] * (x[2] * x[3]) <= 15)# x[2]*x[3] ****** + @NLconstraint(m, x[1] * x[2] * x[3] * x[4] >= 16)# x[1]*x[2]*x[3]*x[4] + @NLconstraint(m, (x[1] * x[2]) * (x[3] * x[4]) <= 17)# x[1]*x[2] and x[3]*x[4] + @NLconstraint(m, x[1] * (x[2] * x[3]) * x[4] >= 18)# x[2]*x[3] ****** + @NLconstraint(m, (x[1] * x[2]) * x[3] * x[4] <= 19)# x[1]*x[2] ****** + @NLconstraint(m, ((x[1] * x[2]) * x[3]) * x[4] >= 20)# x[1]*x[2] ****** + @NLconstraint(m, (x[1] * (x[2] * x[3]) * x[4]) <= 21)# x[2]*x[3] ****** + + @NLconstraint(m, 4 * 5 * 6 * x[1] * x[2] * x[3] * x[4] >= 22)# x[1]*x[2]*x[3]*x[4] + @NLconstraint(m, x[1]^2 * x[2]^2 * x[3]^2 * x[4] <= 23)# None + @NLconstraint(m, x[1] * x[1] * x[2] * x[2] * x[3] * x[3] >= 24)# x[1]*x[1]*x[2]*x[2]*x[3]*x[3] + @NLconstraint(m, (x[1] + 1) * (x[2] + 2) * (x[3] + 3) * (x[4] + 4) <= 25)# None + + @NLconstraint(m, 50sin(x[1]) - 32 * cos(x[2]) >= 26)# sin(x[1]), cos(x[2]) + @NLconstraint(m, sin(x[1] + x[2]) - cos(x[2] - x[3]) + sin(-x[2] + x[3]) <= 27) + @NLconstraint(m, sin(4 * x[1] * x[2]) + cos(x[2] * -1 * x[3]) >= 28)# x[1]*x[2] and x[2]*-1*x[3] ****** + @NLconstraint(m, sin(x[1] * x[2] * x[3]) <= 29)# x[1]*x[2]*x[3] + + return m end -function operator_basic(;solver = nothing) - - m = Model(solver) - - @variable(m, x[1:4]>=0) - - @NLconstraint(m, x[1]^2 >= 1) - @NLconstraint(m, x[1]*x[2] <= 1) - @NLconstraint(m, x[1]^2 + x[2]*x[3] <= 1) - - @NLconstraint(m, x[1] * (x[2]*x[3]) >= 1) - @NLconstraint(m, x[1]^2 * (x[2]^2 * x[3]^2) <= 1) - - @NLconstraint(m, (x[1] * x[2]) * x[3] >= 1) - @NLconstraint(m, (x[1]^2 * x[2]^2) * x[3]^2 <= 1) - - @NLconstraint(m, x[1] * (x[2]^2 * x[3]^2) >= 1) - @NLconstraint(m, (x[1]^2 * x[2]) * x[3]^2 <= 1) - @NLconstraint(m, x[1]^2 * (x[2] * x[3]) >= 1) - @NLconstraint(m, (x[1] * x[2]^2) * x[3] <= 1) - - @NLconstraint(m, ((x[1]*x[2])*x[3])*x[4] >= 1) - @NLconstraint(m, ((x[1]^2*x[2])*x[3])*x[4] <= 1) - @NLconstraint(m, ((x[1]*x[2]^2)*x[3])*x[4] >= 1) - @NLconstraint(m, ((x[1]*x[2])*x[3]^2)*x[4] <= 1) - @NLconstraint(m, ((x[1]*x[2])*x[3])*x[4]^2 >= 1) - @NLconstraint(m, ((x[1]^2*x[2]^2)*x[3]^2)*x[4]^2 <=1) - - @NLconstraint(m, x[1]*(x[2]*(x[3]*x[4])) >= 1) - @NLconstraint(m, x[1]^2*(x[2]*(x[3]*x[4])) <= 1) - @NLconstraint(m, x[1]*(x[2]^2*(x[3]*x[4])) >= 1) - @NLconstraint(m, x[1]*(x[2]*(x[3]^2*x[4])) <= 1) - @NLconstraint(m, x[1]*(x[2]*(x[3]*x[4]^2)) >= 1) - @NLconstraint(m, x[1]^2*(x[2]^2*(x[3]^2*x[4]^2)) <= 1) - - @NLconstraint(m, x[1]*x[2]*x[3] >= 1) - @NLconstraint(m, x[1]^2*x[2]*x[3] >= 1) - @NLconstraint(m, x[1]*x[2]^2*x[3] >= 1) - @NLconstraint(m, x[1]*x[2]*x[3]^2 >= 1) - @NLconstraint(m, x[1]^2*x[2]^2*x[3] >= 1) - @NLconstraint(m, x[1]*x[2]^2*x[3]^2 >= 1) - @NLconstraint(m, x[1]^2*x[2]*x[3]^2 >= 1) - @NLconstraint(m, x[1]^2*x[2]^2*x[3]^2 >= 1) - - @NLconstraint(m, (x[1]*x[2])*(x[3]*x[4]) >= 1) - @NLconstraint(m, (x[1]^2*x[2])*(x[3]*x[4]) >= 1) - @NLconstraint(m, (x[1]*x[2]^2)*(x[3]*x[4]) >= 1) - @NLconstraint(m, (x[1]*x[2])*(x[3]^2*x[4]) >= 1) - @NLconstraint(m, (x[1]*x[2])*(x[3]^2*x[4]^2) >= 1) - @NLconstraint(m, (x[1]^2*x[2])*(x[3]*x[4]^2) >= 1) - @NLconstraint(m, (x[1]^2*x[2])*(x[3]^2*x[4]) >= 1) - - @NLconstraint(m, x[1]*x[2]*x[3]*x[4] >= 1) - @NLconstraint(m, x[1]^2*x[2]*x[3]*x[4] >= 1) - @NLconstraint(m, x[1]*x[2]^2*x[3]*x[4] >= 1) - @NLconstraint(m, x[1]*x[2]*x[3]^2*x[4]^2 >= 1) - @NLconstraint(m, x[1]*x[2]^2*x[3]^2*x[4] >= 1) - @NLconstraint(m, x[1]^2*x[2]*x[3]*x[4]^2 >= 1) - @NLconstraint(m, x[1]^2*x[2]^2*x[3]^2*x[4]^2 >= 1) - - @NLconstraint(m, (x[1]*x[2]*x[3])*x[4] >= 1) - @NLconstraint(m, (x[1]^2*x[2]*x[3])*x[4] >= 1) - @NLconstraint(m, (x[1]*x[2]^2*x[3])*x[4] >= 1) - @NLconstraint(m, (x[1]*x[2]*x[3]^2)*x[4] >= 1) - @NLconstraint(m, (x[1]*x[2]*x[3])*x[4]^2 >= 1) - @NLconstraint(m, (x[1]^2*x[2]^2*x[3]^2)*x[4]^2 >= 1) - - @NLconstraint(m, x[1]*(x[2]*x[3])*x[4] >= 1) - @NLconstraint(m, x[1]^2*(x[2]*x[3])*x[4] >= 1) - @NLconstraint(m, x[1]*(x[2]^2*x[3])*x[4] >= 1) - @NLconstraint(m, x[1]*(x[2]*x[3]^2)*x[4] >= 1) - @NLconstraint(m, x[1]*(x[2]*x[3])*x[4]^2 >= 1) - @NLconstraint(m, x[1]^2*(x[2]*x[3])*x[4]^2 >= 1) - @NLconstraint(m, x[1]*(x[2]^2*x[3]^2)*x[4] >= 1) - @NLconstraint(m, x[1]^2*(x[2]^2*x[3])*x[4] >= 1) - @NLconstraint(m, x[1]*(x[2]*x[3]^2)*x[4]^2 >= 1) - - @NLconstraint(m, x[1]*(x[2]*x[3]*x[4]) >= 1) - @NLconstraint(m, x[1]^2*(x[2]*x[3]*x[4]) >= 1) - @NLconstraint(m, x[1]*(x[2]^2*x[3]*x[4]) >= 1) - @NLconstraint(m, x[1]*(x[2]*x[3]^2*x[4]) >= 1) - @NLconstraint(m, x[1]*(x[2]*x[3]*x[4]^2) >= 1) - @NLconstraint(m, x[1]^2*(x[2]*x[3]^2*x[4]) >= 1) - @NLconstraint(m, x[1]^2*(x[2]^2*x[3]^2*x[4]^2) >= 1) - - @NLconstraint(m, x[1]*x[2]*(x[3]*x[4]) >= 1) - @NLconstraint(m, x[1]^2*x[2]*(x[3]*x[4]) >= 1) - @NLconstraint(m, x[1]*x[2]^2*(x[3]*x[4]) >= 1) - @NLconstraint(m, x[1]*x[2]*(x[3]^2*x[4]) >= 1) - @NLconstraint(m, x[1]*x[2]*(x[3]*x[4]^2) >= 1) - @NLconstraint(m, x[1]^2*x[2]^2*(x[3]^2*x[4]^2) >= 1) - - @NLconstraint(m, (x[1]*x[2])*x[3]*x[4] >= 1) - @NLconstraint(m, (x[1]^2*x[2])*x[3]*x[4] >= 1) - @NLconstraint(m, (x[1]*x[2]^2)*x[3]*x[4] >= 1) - @NLconstraint(m, (x[1]*x[2])*x[3]^2*x[4] >= 1) - @NLconstraint(m, (x[1]*x[2])*x[3]*x[4]^2 >= 1) - @NLconstraint(m, (x[1]*x[2])*x[3]^2*x[4]^2 >= 1) - @NLconstraint(m, (x[1]^2*x[2]^2)*x[3]^2*x[4]^2 >= 1) - - return m +function operator_basic(; solver = nothing) + m = Model(solver) + + @variable(m, x[1:4] >= 0) + + @NLconstraint(m, x[1]^2 >= 1) + @NLconstraint(m, x[1] * x[2] <= 1) + @NLconstraint(m, x[1]^2 + x[2] * x[3] <= 1) + + @NLconstraint(m, x[1] * (x[2] * x[3]) >= 1) + @NLconstraint(m, x[1]^2 * (x[2]^2 * x[3]^2) <= 1) + + @NLconstraint(m, (x[1] * x[2]) * x[3] >= 1) + @NLconstraint(m, (x[1]^2 * x[2]^2) * x[3]^2 <= 1) + + @NLconstraint(m, x[1] * (x[2]^2 * x[3]^2) >= 1) + @NLconstraint(m, (x[1]^2 * x[2]) * x[3]^2 <= 1) + @NLconstraint(m, x[1]^2 * (x[2] * x[3]) >= 1) + @NLconstraint(m, (x[1] * x[2]^2) * x[3] <= 1) + + @NLconstraint(m, ((x[1] * x[2]) * x[3]) * x[4] >= 1) + @NLconstraint(m, ((x[1]^2 * x[2]) * x[3]) * x[4] <= 1) + @NLconstraint(m, ((x[1] * x[2]^2) * x[3]) * x[4] >= 1) + @NLconstraint(m, ((x[1] * x[2]) * x[3]^2) * x[4] <= 1) + @NLconstraint(m, ((x[1] * x[2]) * x[3]) * x[4]^2 >= 1) + @NLconstraint(m, ((x[1]^2 * x[2]^2) * x[3]^2) * x[4]^2 <= 1) + + @NLconstraint(m, x[1] * (x[2] * (x[3] * x[4])) >= 1) + @NLconstraint(m, x[1]^2 * (x[2] * (x[3] * x[4])) <= 1) + @NLconstraint(m, x[1] * (x[2]^2 * (x[3] * x[4])) >= 1) + @NLconstraint(m, x[1] * (x[2] * (x[3]^2 * x[4])) <= 1) + @NLconstraint(m, x[1] * (x[2] * (x[3] * x[4]^2)) >= 1) + @NLconstraint(m, x[1]^2 * (x[2]^2 * (x[3]^2 * x[4]^2)) <= 1) + + @NLconstraint(m, x[1] * x[2] * x[3] >= 1) + @NLconstraint(m, x[1]^2 * x[2] * x[3] >= 1) + @NLconstraint(m, x[1] * x[2]^2 * x[3] >= 1) + @NLconstraint(m, x[1] * x[2] * x[3]^2 >= 1) + @NLconstraint(m, x[1]^2 * x[2]^2 * x[3] >= 1) + @NLconstraint(m, x[1] * x[2]^2 * x[3]^2 >= 1) + @NLconstraint(m, x[1]^2 * x[2] * x[3]^2 >= 1) + @NLconstraint(m, x[1]^2 * x[2]^2 * x[3]^2 >= 1) + + @NLconstraint(m, (x[1] * x[2]) * (x[3] * x[4]) >= 1) + @NLconstraint(m, (x[1]^2 * x[2]) * (x[3] * x[4]) >= 1) + @NLconstraint(m, (x[1] * x[2]^2) * (x[3] * x[4]) >= 1) + @NLconstraint(m, (x[1] * x[2]) * (x[3]^2 * x[4]) >= 1) + @NLconstraint(m, (x[1] * x[2]) * (x[3]^2 * x[4]^2) >= 1) + @NLconstraint(m, (x[1]^2 * x[2]) * (x[3] * x[4]^2) >= 1) + @NLconstraint(m, (x[1]^2 * x[2]) * (x[3]^2 * x[4]) >= 1) + + @NLconstraint(m, x[1] * x[2] * x[3] * x[4] >= 1) + @NLconstraint(m, x[1]^2 * x[2] * x[3] * x[4] >= 1) + @NLconstraint(m, x[1] * x[2]^2 * x[3] * x[4] >= 1) + @NLconstraint(m, x[1] * x[2] * x[3]^2 * x[4]^2 >= 1) + @NLconstraint(m, x[1] * x[2]^2 * x[3]^2 * x[4] >= 1) + @NLconstraint(m, x[1]^2 * x[2] * x[3] * x[4]^2 >= 1) + @NLconstraint(m, x[1]^2 * x[2]^2 * x[3]^2 * x[4]^2 >= 1) + + @NLconstraint(m, (x[1] * x[2] * x[3]) * x[4] >= 1) + @NLconstraint(m, (x[1]^2 * x[2] * x[3]) * x[4] >= 1) + @NLconstraint(m, (x[1] * x[2]^2 * x[3]) * x[4] >= 1) + @NLconstraint(m, (x[1] * x[2] * x[3]^2) * x[4] >= 1) + @NLconstraint(m, (x[1] * x[2] * x[3]) * x[4]^2 >= 1) + @NLconstraint(m, (x[1]^2 * x[2]^2 * x[3]^2) * x[4]^2 >= 1) + + @NLconstraint(m, x[1] * (x[2] * x[3]) * x[4] >= 1) + @NLconstraint(m, x[1]^2 * (x[2] * x[3]) * x[4] >= 1) + @NLconstraint(m, x[1] * (x[2]^2 * x[3]) * x[4] >= 1) + @NLconstraint(m, x[1] * (x[2] * x[3]^2) * x[4] >= 1) + @NLconstraint(m, x[1] * (x[2] * x[3]) * x[4]^2 >= 1) + @NLconstraint(m, x[1]^2 * (x[2] * x[3]) * x[4]^2 >= 1) + @NLconstraint(m, x[1] * (x[2]^2 * x[3]^2) * x[4] >= 1) + @NLconstraint(m, x[1]^2 * (x[2]^2 * x[3]) * x[4] >= 1) + @NLconstraint(m, x[1] * (x[2] * x[3]^2) * x[4]^2 >= 1) + + @NLconstraint(m, x[1] * (x[2] * x[3] * x[4]) >= 1) + @NLconstraint(m, x[1]^2 * (x[2] * x[3] * x[4]) >= 1) + @NLconstraint(m, x[1] * (x[2]^2 * x[3] * x[4]) >= 1) + @NLconstraint(m, x[1] * (x[2] * x[3]^2 * x[4]) >= 1) + @NLconstraint(m, x[1] * (x[2] * x[3] * x[4]^2) >= 1) + @NLconstraint(m, x[1]^2 * (x[2] * x[3]^2 * x[4]) >= 1) + @NLconstraint(m, x[1]^2 * (x[2]^2 * x[3]^2 * x[4]^2) >= 1) + + @NLconstraint(m, x[1] * x[2] * (x[3] * x[4]) >= 1) + @NLconstraint(m, x[1]^2 * x[2] * (x[3] * x[4]) >= 1) + @NLconstraint(m, x[1] * x[2]^2 * (x[3] * x[4]) >= 1) + @NLconstraint(m, x[1] * x[2] * (x[3]^2 * x[4]) >= 1) + @NLconstraint(m, x[1] * x[2] * (x[3] * x[4]^2) >= 1) + @NLconstraint(m, x[1]^2 * x[2]^2 * (x[3]^2 * x[4]^2) >= 1) + + @NLconstraint(m, (x[1] * x[2]) * x[3] * x[4] >= 1) + @NLconstraint(m, (x[1]^2 * x[2]) * x[3] * x[4] >= 1) + @NLconstraint(m, (x[1] * x[2]^2) * x[3] * x[4] >= 1) + @NLconstraint(m, (x[1] * x[2]) * x[3]^2 * x[4] >= 1) + @NLconstraint(m, (x[1] * x[2]) * x[3] * x[4]^2 >= 1) + @NLconstraint(m, (x[1] * x[2]) * x[3]^2 * x[4]^2 >= 1) + @NLconstraint(m, (x[1]^2 * x[2]^2) * x[3]^2 * x[4]^2 >= 1) + + return m end -function operator_c(;solver = nothing) - - m = Model(solver) - - @variable(m, px[i=1:6]>=1) # At some point if an initial value is given, keep them - - @NLconstraint(m, sum(3*px[i]^2 for i=1:4) >= 111) - @NLconstraint(m, -1 * px[1]*px[2] + 4*5*px[3]*px[4] >= 222) - @NLconstraint(m, px[1]+ px[2] * px[3] >= 555) # => px[1] + x23 >= 555 && x23 == px[2]*px[3] - @NLconstraint(m, px[1]^2 - 7 * px[2]^2 + px[3]^2 + px[4] <= 6666) - @NLconstraint(m, 13*px[1] - px[2] + 5*px[3]*6 + px[4] >= 77) - - @NLobjective(m, Min, 7*px[1]*6*px[4]*2+5+17+px[1]+px[2]+px[3]+8+3*5*px[1]^2*4) - - return m +function operator_c(; solver = nothing) + m = Model(solver) + + @variable(m, px[i = 1:6] >= 1) # At some point if an initial value is given, keep them + + @NLconstraint(m, sum(3 * px[i]^2 for i in 1:4) >= 111) + @NLconstraint(m, -1 * px[1] * px[2] + 4 * 5 * px[3] * px[4] >= 222) + @NLconstraint(m, px[1] + px[2] * px[3] >= 555) # => px[1] + x23 >= 555 && x23 == px[2]*px[3] + @NLconstraint(m, px[1]^2 - 7 * px[2]^2 + px[3]^2 + px[4] <= 6666) + @NLconstraint(m, 13 * px[1] - px[2] + 5 * px[3] * 6 + px[4] >= 77) + + @NLobjective( + m, + Min, + 7 * px[1] * 6 * px[4] * 2 + + 5 + + 17 + + px[1] + + px[2] + + px[3] + + 8 + + 3 * 5 * px[1]^2 * 4 + ) + + return m end diff --git a/examples/MINLPs/integer.jl b/examples/MINLPs/integer.jl index 3d39c2b3..93ec37f9 100644 --- a/examples/MINLPs/integer.jl +++ b/examples/MINLPs/integer.jl @@ -1,4 +1,4 @@ -function ex1225a(;solver = nothing) +function ex1225a(; solver = nothing) # GOpt: 131670.377903 # This problem may be numerically sensitive @@ -29,44 +29,89 @@ function ex1225a(;solver = nothing) JuMP.set_upper_bound(x[14], 1.0) JuMP.set_upper_bound(x[15], 1.0) - # ----- Constraints ----- # - @NLconstraint(m, e1, -((6329.03+1800*x[1])*i[16]*i[19]*b[22]+(2489.31+1800*x[2])*i[17]*i[20]*b[23]+(3270.27+1800*x[3])*i[18]*i[21]*b[24])+objvar == 0.0) - @NLconstraint(m, e2, (-19.9* (0.000338983050847458*x[4])^3)-0.161* (0.000338983050847458*x[4])^2*x[10]+1.90169491525424e-7*x[4]* (x[10])^2+x[1] == 0.0) - @NLconstraint(m, e3, (-1.21* (0.000338983050847458*x[5])^3)-0.0644* (0.000338983050847458*x[5])^2*x[11]+1.91186440677966e-7*x[5]* (x[11])^2+x[2] == 0.0) - @NLconstraint(m, e4, (-6.52* (0.000338983050847458*x[6])^3)-0.102* (0.000338983050847458*x[6])^2*x[12]+7.86440677966102e-8*x[6]* (x[12])^2+x[3] == 0.0) - @NLconstraint(m, e5, (-0.00023593220338983*x[4]*x[10])-629* (0.000338983050847458*x[4])^2+0.0116* (x[10])^2+x[7] == 0.0) - @NLconstraint(m, e6, (-0.001*x[5]*x[11])-215* (0.000338983050847458*x[5])^2+0.115* (x[11])^2+x[8] == 0.0) - @NLconstraint(m, e7, (-0.000179661016949153*x[6]*x[12])-361* (0.000338983050847458*x[6])^2+0.00946* (x[12])^2+x[9] == 0.0) - @constraint(m, e8, x[13]+x[14]+x[15] == 1.0) - @NLconstraint(m, e9, 0.00285714285714286*x[10]*i[16]-x[13] == 0.0) - @NLconstraint(m, e10, 0.00285714285714286*x[11]*i[17]-x[14] == 0.0) - @NLconstraint(m, e11, 0.00285714285714286*x[12]*i[18]-x[15] == 0.0) - @NLconstraint(m, e12, 0.0025*x[7]*i[19]-b[22] == 0.0) - @NLconstraint(m, e13, 0.0025*x[8]*i[20]-b[23] == 0.0) - @NLconstraint(m, e14, 0.0025*x[9]*i[21]-b[24] == 0.0) - @constraint(m, e15, 0.000338983050847458*x[4]-b[22] <= 0.0) - @constraint(m, e16, 0.000338983050847458*x[5]-b[23] <= 0.0) - @constraint(m, e17, 0.000338983050847458*x[6]-b[24] <= 0.0) - @constraint(m, e18, 0.0125*x[1]-b[22] <= 0.0) - @constraint(m, e19, 0.04*x[2]-b[23] <= 0.0) - @constraint(m, e20, 0.0222222222222222*x[3]-b[24] <= 0.0) - @constraint(m, e21, 0.0025*x[7]-b[22] <= 0.0) - @constraint(m, e22, 0.0025*x[8]-b[23] <= 0.0) - @constraint(m, e23, 0.0025*x[9]-b[24] <= 0.0) - @constraint(m, e24, 0.00285714285714286*x[10]-b[22] <= 0.0) - @constraint(m, e25, 0.00285714285714286*x[11]-b[23] <= 0.0) - @constraint(m, e26, 0.00285714285714286*x[12]-b[24] <= 0.0) - @constraint(m, e27, x[13]-b[22] <= 0.0) - @constraint(m, e28, x[14]-b[23] <= 0.0) - @constraint(m, e29, x[15]-b[24] <= 0.0) - @constraint(m, e30, i[16]-3*b[22] <= 0.0) - @constraint(m, e31, i[17]-3*b[23] <= 0.0) - @constraint(m, e32, i[18]-3*b[24] <= 0.0) - @constraint(m, e33, i[19]-3*b[22] <= 0.0) - @constraint(m, e34, i[20]-3*b[23] <= 0.0) - @constraint(m, e35, i[21]-3*b[24] <= 0.0) - + @NLconstraint( + m, + e1, + -( + (6329.03 + 1800 * x[1]) * i[16] * i[19] * b[22] + + (2489.31 + 1800 * x[2]) * i[17] * i[20] * b[23] + + (3270.27 + 1800 * x[3]) * i[18] * i[21] * b[24] + ) + objvar == 0.0 + ) + @NLconstraint( + m, + e2, + (-19.9 * (0.000338983050847458 * x[4])^3) - + 0.161 * (0.000338983050847458 * x[4])^2 * x[10] + + 1.90169491525424e-7 * x[4] * (x[10])^2 + + x[1] == 0.0 + ) + @NLconstraint( + m, + e3, + (-1.21 * (0.000338983050847458 * x[5])^3) - + 0.0644 * (0.000338983050847458 * x[5])^2 * x[11] + + 1.91186440677966e-7 * x[5] * (x[11])^2 + + x[2] == 0.0 + ) + @NLconstraint( + m, + e4, + (-6.52 * (0.000338983050847458 * x[6])^3) - + 0.102 * (0.000338983050847458 * x[6])^2 * x[12] + + 7.86440677966102e-8 * x[6] * (x[12])^2 + + x[3] == 0.0 + ) + @NLconstraint( + m, + e5, + (-0.00023593220338983 * x[4] * x[10]) - 629 * (0.000338983050847458 * x[4])^2 + + 0.0116 * (x[10])^2 + + x[7] == 0.0 + ) + @NLconstraint( + m, + e6, + (-0.001 * x[5] * x[11]) - 215 * (0.000338983050847458 * x[5])^2 + + 0.115 * (x[11])^2 + + x[8] == 0.0 + ) + @NLconstraint( + m, + e7, + (-0.000179661016949153 * x[6] * x[12]) - 361 * (0.000338983050847458 * x[6])^2 + + 0.00946 * (x[12])^2 + + x[9] == 0.0 + ) + @constraint(m, e8, x[13] + x[14] + x[15] == 1.0) + @NLconstraint(m, e9, 0.00285714285714286 * x[10] * i[16] - x[13] == 0.0) + @NLconstraint(m, e10, 0.00285714285714286 * x[11] * i[17] - x[14] == 0.0) + @NLconstraint(m, e11, 0.00285714285714286 * x[12] * i[18] - x[15] == 0.0) + @NLconstraint(m, e12, 0.0025 * x[7] * i[19] - b[22] == 0.0) + @NLconstraint(m, e13, 0.0025 * x[8] * i[20] - b[23] == 0.0) + @NLconstraint(m, e14, 0.0025 * x[9] * i[21] - b[24] == 0.0) + @constraint(m, e15, 0.000338983050847458 * x[4] - b[22] <= 0.0) + @constraint(m, e16, 0.000338983050847458 * x[5] - b[23] <= 0.0) + @constraint(m, e17, 0.000338983050847458 * x[6] - b[24] <= 0.0) + @constraint(m, e18, 0.0125 * x[1] - b[22] <= 0.0) + @constraint(m, e19, 0.04 * x[2] - b[23] <= 0.0) + @constraint(m, e20, 0.0222222222222222 * x[3] - b[24] <= 0.0) + @constraint(m, e21, 0.0025 * x[7] - b[22] <= 0.0) + @constraint(m, e22, 0.0025 * x[8] - b[23] <= 0.0) + @constraint(m, e23, 0.0025 * x[9] - b[24] <= 0.0) + @constraint(m, e24, 0.00285714285714286 * x[10] - b[22] <= 0.0) + @constraint(m, e25, 0.00285714285714286 * x[11] - b[23] <= 0.0) + @constraint(m, e26, 0.00285714285714286 * x[12] - b[24] <= 0.0) + @constraint(m, e27, x[13] - b[22] <= 0.0) + @constraint(m, e28, x[14] - b[23] <= 0.0) + @constraint(m, e29, x[15] - b[24] <= 0.0) + @constraint(m, e30, i[16] - 3 * b[22] <= 0.0) + @constraint(m, e31, i[17] - 3 * b[23] <= 0.0) + @constraint(m, e32, i[18] - 3 * b[24] <= 0.0) + @constraint(m, e33, i[19] - 3 * b[22] <= 0.0) + @constraint(m, e34, i[20] - 3 * b[23] <= 0.0) + @constraint(m, e35, i[21] - 3 * b[24] <= 0.0) # ----- Objective ----- # @objective(m, Min, objvar) @@ -74,7 +119,7 @@ function ex1225a(;solver = nothing) return m end -function ex1264a(;solver = nothing) +function ex1264a(; solver = nothing) # Source: http://minlplib.org/ex1264a.html # GOpt: 8.6 @@ -86,51 +131,95 @@ function ex1264a(;solver = nothing) i_Idx = Any[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 21, 22, 23, 24] @variable(m, i[i_Idx] >= 0, Int) - for j=1:16 + for j in 1:16 JuMP.set_upper_bound(i[j], 5.0) - end + end JuMP.set_upper_bound(i[21], 15.0) JuMP.set_upper_bound(i[22], 12.0) JuMP.set_upper_bound(i[23], 9.0) JuMP.set_upper_bound(i[24], 6.0) - @constraint(m, e1, -0.1*b[17]-0.2*b[18]-0.3*b[19]-0.4*b[20]-i[21]-i[22]-i[23]-i[24]+objvar == 0.0) - @NLconstraint(m, e2, i[21]*i[1]+i[22]*i[2]+i[23]*i[3]+i[24]*i[4] >= 9.0) - @NLconstraint(m, e3, i[21]*i[5]+i[22]*i[6]+i[23]*i[7]+i[24]*i[8] >= 7.0) - @NLconstraint(m, e4, i[21]*i[9]+i[22]*i[10]+i[23]*i[11]+i[24]*i[12] >= 12.0) - @NLconstraint(m, e5, i[21]*i[13]+i[22]*i[14]+i[23]*i[15]+i[24]*i[16] >= 11.0) - @constraint(m, e6, -330*i[1]-360*i[5]-385*i[9]-415*i[13]+1700*b[17] <= 0.0) - @constraint(m, e7, -330*i[2]-360*i[6]-385*i[10]-415*i[14]+1700*b[18] <= 0.0) - @constraint(m, e8, -330*i[3]-360*i[7]-385*i[11]-415*i[15]+1700*b[19] <= 0.0) - @constraint(m, e9, -330*i[4]-360*i[8]-385*i[12]-415*i[16]+1700*b[20] <= 0.0) - @constraint(m, e10, 330*i[1]+360*i[5]+385*i[9]+415*i[13]-1900*b[17] <= 0.0) - @constraint(m, e11, 330*i[2]+360*i[6]+385*i[10]+415*i[14]-1900*b[18] <= 0.0) - @constraint(m, e12, 330*i[3]+360*i[7]+385*i[11]+415*i[15]-1900*b[19] <= 0.0) - @constraint(m, e13, 330*i[4]+360*i[8]+385*i[12]+415*i[16]-1900*b[20] <= 0.0) - @constraint(m, e14, -i[1]-i[5]-i[9]-i[13]+b[17] <= 0.0) - @constraint(m, e15, -i[2]-i[6]-i[10]-i[14]+b[18] <= 0.0) - @constraint(m, e16, -i[3]-i[7]-i[11]-i[15]+b[19] <= 0.0) - @constraint(m, e17, -i[4]-i[8]-i[12]-i[16]+b[20] <= 0.0) - @constraint(m, e18, i[1]+i[5]+i[9]+i[13]-5*b[17] <= 0.0) - @constraint(m, e19, i[2]+i[6]+i[10]+i[14]-5*b[18] <= 0.0) - @constraint(m, e20, i[3]+i[7]+i[11]+i[15]-5*b[19] <= 0.0) - @constraint(m, e21, i[4]+i[8]+i[12]+i[16]-5*b[20] <= 0.0) - @constraint(m, e22, b[17]-i[21] <= 0.0) - @constraint(m, e23, b[18]-i[22] <= 0.0) - @constraint(m, e24, b[19]-i[23] <= 0.0) - @constraint(m, e25, b[20]-i[24] <= 0.0) - @constraint(m, e26, -15*b[17]+i[21] <= 0.0) - @constraint(m, e27, -12*b[18]+i[22] <= 0.0) - @constraint(m, e28, -9*b[19]+i[23] <= 0.0) - @constraint(m, e29, -6*b[20]+i[24] <= 0.0) - @constraint(m, e30, i[21]+i[22]+i[23]+i[24] >= 8.0) - @constraint(m, e31, -b[17]+b[18] <= 0.0) - @constraint(m, e32, -b[18]+b[19] <= 0.0) - @constraint(m, e33, -b[19]+b[20] <= 0.0) - @constraint(m, e34, -i[21]+i[22] <= 0.0) - @constraint(m, e35, -i[22]+i[23] <= 0.0) - @constraint(m, e36, -i[23]+i[24] <= 0.0) - + @constraint( + m, + e1, + -0.1 * b[17] - 0.2 * b[18] - 0.3 * b[19] - 0.4 * b[20] - i[21] - i[22] - i[23] - + i[24] + objvar == 0.0 + ) + @NLconstraint(m, e2, i[21] * i[1] + i[22] * i[2] + i[23] * i[3] + i[24] * i[4] >= 9.0) + @NLconstraint(m, e3, i[21] * i[5] + i[22] * i[6] + i[23] * i[7] + i[24] * i[8] >= 7.0) + @NLconstraint( + m, + e4, + i[21] * i[9] + i[22] * i[10] + i[23] * i[11] + i[24] * i[12] >= 12.0 + ) + @NLconstraint( + m, + e5, + i[21] * i[13] + i[22] * i[14] + i[23] * i[15] + i[24] * i[16] >= 11.0 + ) + @constraint( + m, + e6, + -330 * i[1] - 360 * i[5] - 385 * i[9] - 415 * i[13] + 1700 * b[17] <= 0.0 + ) + @constraint( + m, + e7, + -330 * i[2] - 360 * i[6] - 385 * i[10] - 415 * i[14] + 1700 * b[18] <= 0.0 + ) + @constraint( + m, + e8, + -330 * i[3] - 360 * i[7] - 385 * i[11] - 415 * i[15] + 1700 * b[19] <= 0.0 + ) + @constraint( + m, + e9, + -330 * i[4] - 360 * i[8] - 385 * i[12] - 415 * i[16] + 1700 * b[20] <= 0.0 + ) + @constraint( + m, + e10, + 330 * i[1] + 360 * i[5] + 385 * i[9] + 415 * i[13] - 1900 * b[17] <= 0.0 + ) + @constraint( + m, + e11, + 330 * i[2] + 360 * i[6] + 385 * i[10] + 415 * i[14] - 1900 * b[18] <= 0.0 + ) + @constraint( + m, + e12, + 330 * i[3] + 360 * i[7] + 385 * i[11] + 415 * i[15] - 1900 * b[19] <= 0.0 + ) + @constraint( + m, + e13, + 330 * i[4] + 360 * i[8] + 385 * i[12] + 415 * i[16] - 1900 * b[20] <= 0.0 + ) + @constraint(m, e14, -i[1] - i[5] - i[9] - i[13] + b[17] <= 0.0) + @constraint(m, e15, -i[2] - i[6] - i[10] - i[14] + b[18] <= 0.0) + @constraint(m, e16, -i[3] - i[7] - i[11] - i[15] + b[19] <= 0.0) + @constraint(m, e17, -i[4] - i[8] - i[12] - i[16] + b[20] <= 0.0) + @constraint(m, e18, i[1] + i[5] + i[9] + i[13] - 5 * b[17] <= 0.0) + @constraint(m, e19, i[2] + i[6] + i[10] + i[14] - 5 * b[18] <= 0.0) + @constraint(m, e20, i[3] + i[7] + i[11] + i[15] - 5 * b[19] <= 0.0) + @constraint(m, e21, i[4] + i[8] + i[12] + i[16] - 5 * b[20] <= 0.0) + @constraint(m, e22, b[17] - i[21] <= 0.0) + @constraint(m, e23, b[18] - i[22] <= 0.0) + @constraint(m, e24, b[19] - i[23] <= 0.0) + @constraint(m, e25, b[20] - i[24] <= 0.0) + @constraint(m, e26, -15 * b[17] + i[21] <= 0.0) + @constraint(m, e27, -12 * b[18] + i[22] <= 0.0) + @constraint(m, e28, -9 * b[19] + i[23] <= 0.0) + @constraint(m, e29, -6 * b[20] + i[24] <= 0.0) + @constraint(m, e30, i[21] + i[22] + i[23] + i[24] >= 8.0) + @constraint(m, e31, -b[17] + b[18] <= 0.0) + @constraint(m, e32, -b[18] + b[19] <= 0.0) + @constraint(m, e33, -b[19] + b[20] <= 0.0) + @constraint(m, e34, -i[21] + i[22] <= 0.0) + @constraint(m, e35, -i[22] + i[23] <= 0.0) + @constraint(m, e36, -i[23] + i[24] <= 0.0) # ----- Objective ----- # @objective(m, Min, objvar) @@ -138,7 +227,7 @@ function ex1264a(;solver = nothing) return m end -function prob03(;solver = nothing) +function prob03(; solver = nothing) # Source: http://minlplib.org/prob03.html # GOpt: 10.0000 @@ -148,15 +237,15 @@ function prob03(;solver = nothing) i_Idx = Any[1, 2] @variable(m, 1 <= i[i_Idx] <= 5, Int) - @constraint(m, e1, -3*i[1] - 2*i[2] + objvar == 0.0) - @NLconstraint(m, e2, -i[1]*i[2] <= -3.5) + @constraint(m, e1, -3 * i[1] - 2 * i[2] + objvar == 0.0) + @NLconstraint(m, e2, -i[1] * i[2] <= -3.5) @objective(m, Min, objvar) return m end -function prob10(;solver = nothing) +function prob10(; solver = nothing) # Source: http://minlplib.org/prob10.html # GOpt: 3.44550379 @@ -168,16 +257,21 @@ function prob10(;solver = nothing) i_Idx = Any[3] @variable(m, 0 <= i[i_Idx] <= 10, Int) - @constraint(m, e1, 0.7*x[2]+i[3] <= 7.0) - @constraint(m, e2, 2.5*x[2]+i[3] <= 19.0) - @NLconstraint(m, e3, 1.1*( (2*x[2]-10)^2+ (i[3]-5)^2) + sin((2*x[2]-10)^2+ (i[3]-5)^2) - objvar == 0.0) + @constraint(m, e1, 0.7 * x[2] + i[3] <= 7.0) + @constraint(m, e2, 2.5 * x[2] + i[3] <= 19.0) + @NLconstraint( + m, + e3, + 1.1 * ((2 * x[2] - 10)^2 + (i[3] - 5)^2) + sin((2 * x[2] - 10)^2 + (i[3] - 5)^2) - + objvar == 0.0 + ) @objective(m, Min, objvar) return m end -function st_miqp1(;solver = nothing) +function st_miqp1(; solver = nothing) # source: http://minlplib.org/st_miqp1.html # GOpt: 281.0000 @@ -190,8 +284,23 @@ function st_miqp1(;solver = nothing) @variable(m, 0 <= i[i_Idx] <= 1, Int) # ----- Constraints ----- # - @constraint(m, e1, 20*i[1] + 12*i[2] + 11*i[3] + 7*i[4] + 4*i[5] >= 40.0) - @NLconstraint(m, e2, -(50*i[1]^2 + 42*i[1] + 50*i[2]^2 + 44*i[2]+ 50*i[3]^2 + 45*i[3] + 50*i[4]^2 + 47*i[4]+ 50*i[5]^2 + 47.5*i[5]) + objvar == 0.0) + @constraint(m, e1, 20 * i[1] + 12 * i[2] + 11 * i[3] + 7 * i[4] + 4 * i[5] >= 40.0) + @NLconstraint( + m, + e2, + -( + 50 * i[1]^2 + + 42 * i[1] + + 50 * i[2]^2 + + 44 * i[2] + + 50 * i[3]^2 + + 45 * i[3] + + 50 * i[4]^2 + + 47 * i[4] + + 50 * i[5]^2 + + 47.5 * i[5] + ) + objvar == 0.0 + ) # ----- Objective ----- # @objective(m, Min, objvar) @@ -199,10 +308,10 @@ function st_miqp1(;solver = nothing) return m end -function st_miqp2(;solver = nothing) +function st_miqp2(; solver = nothing) # Source: http://minlplib.org/st_miqp2.html # GOpt: 2.0000 - + m = Model(solver) # ----- Variables ----- # @@ -215,10 +324,15 @@ function st_miqp2(;solver = nothing) JuMP.set_upper_bound(i[4], 1.0e10) # ----- Constraints ----- # - @constraint(m, e1, -10*i[1]+i[3] <= 0.0) - @constraint(m, e2, -20*i[2]+i[4] <= 0.0) - @constraint(m, e3, i[3]+i[4] >= 5.0) - @NLconstraint(m, e4, -(4*i[3]^2 - 3*i[3] + 2*i[4]^2 - 10*i[4]) - 4*i[1] -5*i[2] + objvar == 0.0) + @constraint(m, e1, -10 * i[1] + i[3] <= 0.0) + @constraint(m, e2, -20 * i[2] + i[4] <= 0.0) + @constraint(m, e3, i[3] + i[4] >= 5.0) + @NLconstraint( + m, + e4, + -(4 * i[3]^2 - 3 * i[3] + 2 * i[4]^2 - 10 * i[4]) - 4 * i[1] - 5 * i[2] + + objvar == 0.0 + ) # ----- Objective ----- # @objective(m, Min, objvar) @@ -226,7 +340,7 @@ function st_miqp2(;solver = nothing) return m end -function st_miqp3(;solver = nothing) +function st_miqp3(; solver = nothing) # Source: http://minlplib.org/st_miqp3.html # GOpt: -6.0000 @@ -240,9 +354,8 @@ function st_miqp3(;solver = nothing) JuMP.set_upper_bound(i[2], 1.0e15) # ----- Constraints ----- # - @constraint(m, e1, -4*i[1]+i[2] <= 0.0) - @NLconstraint(m, e2, -6*i[1]^2 + 3*i[2] + objvar == 0.0) - + @constraint(m, e1, -4 * i[1] + i[2] <= 0.0) + @NLconstraint(m, e2, -6 * i[1]^2 + 3 * i[2] + objvar == 0.0) # ----- Objective ----- # @objective(m, Min, objvar) @@ -250,7 +363,7 @@ function st_miqp3(;solver = nothing) return m end -function st_miqp4(;solver = nothing) +function st_miqp4(; solver = nothing) # Source: http://minlplib.org/st_miqp4.html # GOpt: -4574.0000 @@ -264,11 +377,16 @@ function st_miqp4(;solver = nothing) @variable(m, 0 <= i[i_Idx] <= 1, Int) # ----- Constraints ----- # - @constraint(m, e1, x[4]+x[5]-x[6] >= 0.0) - @constraint(m, e2, -5*i[1]+x[4] <= 0.0) - @constraint(m, e3, -10*i[2]+x[5] <= 0.0) - @constraint(m, e4, -30*i[3]+x[6] <= 0.0) - @NLconstraint(m, e5, -(5*x[4]^2 + 2*x[4] + 5*x[5]^2 + 3*x[5] + 10*x[6]^2 - 500*x[6]) - 10*i[1] + 4*i[2] - 5*i[3] + objvar == 0.0) + @constraint(m, e1, x[4] + x[5] - x[6] >= 0.0) + @constraint(m, e2, -5 * i[1] + x[4] <= 0.0) + @constraint(m, e3, -10 * i[2] + x[5] <= 0.0) + @constraint(m, e4, -30 * i[3] + x[6] <= 0.0) + @NLconstraint( + m, + e5, + -(5 * x[4]^2 + 2 * x[4] + 5 * x[5]^2 + 3 * x[5] + 10 * x[6]^2 - 500 * x[6]) - + 10 * i[1] + 4 * i[2] - 5 * i[3] + objvar == 0.0 + ) # ----- Objective ----- # @objective(m, Min, objvar) @@ -276,7 +394,7 @@ function st_miqp4(;solver = nothing) return m end -function st_miqp5(;solver = nothing) +function st_miqp5(; solver = nothing) # Source: http://minlplib.org/st_miqp5.html # GOpt: -333.88888890 @@ -288,7 +406,7 @@ function st_miqp5(;solver = nothing) @variable(m, x[x_Idx]) i_Idx = Any[1, 2] @variable(m, 0 <= i[i_Idx] <= 1, Int) - + JuMP.set_lower_bound(x[3], -7.24380468458) JuMP.set_upper_bound(x[3], 22.6826188429) JuMP.set_lower_bound(x[4], -6.0023781122) @@ -301,20 +419,105 @@ function st_miqp5(;solver = nothing) JuMP.set_upper_bound(x[7], 19.4187214575) # ----- Constraints ----- # - @constraint(m, e1, -1.93414531698*x[3]+1.80314509442*x[4]+2.89695789508*x[5]+0.729324957489*x[6]+3.8837442915*x[7] <= 60.0) - @constraint(m, e2, -1.13150591228*x[3]+1.10500971967*x[4]-1.01838569726*x[5]+2.62556984696*x[6]+4.85468036438*x[7] <= 60.0) - @constraint(m, e3, -0.0524800119769*x[3]-0.904837825133*x[4]+0.209520819817*x[5]-0.291729982996*x[6]-0.222506183367*x[7] <= 0.0) - @constraint(m, e4, 0.0524800119769*x[3]+0.904837825133*x[4]-0.209520819817*x[5]+0.291729982996*x[6]+0.222506183367*x[7] <= 1.0) - @constraint(m, e5, 0.445391966818*x[3]+0.301519984248*x[4]+0.587645368916*x[5]-0.145864991498*x[6]-0.586607210695*x[7] <= 0.0) - @constraint(m, e6, -0.445391966818*x[3]-0.301519984248*x[4]-0.587645368916*x[5]+0.145864991498*x[6]+0.586607210695*x[7] <= 1.0) - @constraint(m, e7, -0.328188665272*x[3]+0.199986646277*x[4]+0.506106406938*x[5]-0.583459965992*x[6]+0.505695871289*x[7] >= 0.0) - @constraint(m, e8, -0.345682002598*x[3]-0.101625962101*x[4]+0.57594668021*x[5]+0.729324957489*x[6]+0.0809113394063*x[7] >= 0.0) - @constraint(m, e9, 0.756087294764*x[3]-0.200079270407*x[4]+0.151379235251*x[5]+0.145864991498*x[6]+0.586607210695*x[7] >= 0.0) - @constraint(m, e10, -i[1]+0.0524800119769*x[3]+0.904837825133*x[4]-0.209520819817*x[5]+0.291729982996*x[6]+0.222506183367*x[7] <= 0.0) - @constraint(m, e11, i[1]-0.0524800119769*x[3]-0.904837825133*x[4]+0.209520819817*x[5]-0.291729982996*x[6]-0.222506183367*x[7] <= 0.0) - @constraint(m, e12, -i[2]-0.445391966818*x[3]-0.301519984248*x[4]-0.587645368916*x[5]+0.145864991498*x[6]+0.586607210695*x[7] <= 0.0) - @constraint(m, e13, i[2]+0.445391966818*x[3]+0.301519984248*x[4]+0.587645368916*x[5]-0.145864991498*x[6]-0.586607210695*x[7] <= 0.0) - @NLconstraint(m, e14, -(5*x[6]^2 - 0.875189948987*x[6] + 52*x[7]^2 - 192.710582631*x[7]) + 54.0615511462*x[3] + 45.2691026456*x[4] + 33.0896119339*x[5] + objvar == 0.0) + @constraint( + m, + e1, + -1.93414531698 * x[3] + + 1.80314509442 * x[4] + + 2.89695789508 * x[5] + + 0.729324957489 * x[6] + + 3.8837442915 * x[7] <= 60.0 + ) + @constraint( + m, + e2, + -1.13150591228 * x[3] + 1.10500971967 * x[4] - 1.01838569726 * x[5] + + 2.62556984696 * x[6] + + 4.85468036438 * x[7] <= 60.0 + ) + @constraint( + m, + e3, + -0.0524800119769 * x[3] - 0.904837825133 * x[4] + 0.209520819817 * x[5] - + 0.291729982996 * x[6] - 0.222506183367 * x[7] <= 0.0 + ) + @constraint( + m, + e4, + 0.0524800119769 * x[3] + 0.904837825133 * x[4] - 0.209520819817 * x[5] + + 0.291729982996 * x[6] + + 0.222506183367 * x[7] <= 1.0 + ) + @constraint( + m, + e5, + 0.445391966818 * x[3] + 0.301519984248 * x[4] + 0.587645368916 * x[5] - + 0.145864991498 * x[6] - 0.586607210695 * x[7] <= 0.0 + ) + @constraint( + m, + e6, + -0.445391966818 * x[3] - 0.301519984248 * x[4] - 0.587645368916 * x[5] + + 0.145864991498 * x[6] + + 0.586607210695 * x[7] <= 1.0 + ) + @constraint( + m, + e7, + -0.328188665272 * x[3] + 0.199986646277 * x[4] + 0.506106406938 * x[5] - + 0.583459965992 * x[6] + 0.505695871289 * x[7] >= 0.0 + ) + @constraint( + m, + e8, + -0.345682002598 * x[3] - 0.101625962101 * x[4] + + 0.57594668021 * x[5] + + 0.729324957489 * x[6] + + 0.0809113394063 * x[7] >= 0.0 + ) + @constraint( + m, + e9, + 0.756087294764 * x[3] - 0.200079270407 * x[4] + + 0.151379235251 * x[5] + + 0.145864991498 * x[6] + + 0.586607210695 * x[7] >= 0.0 + ) + @constraint( + m, + e10, + -i[1] + 0.0524800119769 * x[3] + 0.904837825133 * x[4] - 0.209520819817 * x[5] + + 0.291729982996 * x[6] + + 0.222506183367 * x[7] <= 0.0 + ) + @constraint( + m, + e11, + i[1] - 0.0524800119769 * x[3] - 0.904837825133 * x[4] + 0.209520819817 * x[5] - + 0.291729982996 * x[6] - 0.222506183367 * x[7] <= 0.0 + ) + @constraint( + m, + e12, + -i[2] - 0.445391966818 * x[3] - 0.301519984248 * x[4] - 0.587645368916 * x[5] + + 0.145864991498 * x[6] + + 0.586607210695 * x[7] <= 0.0 + ) + @constraint( + m, + e13, + i[2] + 0.445391966818 * x[3] + 0.301519984248 * x[4] + 0.587645368916 * x[5] - + 0.145864991498 * x[6] - 0.586607210695 * x[7] <= 0.0 + ) + @NLconstraint( + m, + e14, + -(5 * x[6]^2 - 0.875189948987 * x[6] + 52 * x[7]^2 - 192.710582631 * x[7]) + + 54.0615511462 * x[3] + + 45.2691026456 * x[4] + + 33.0896119339 * x[5] + + objvar == 0.0 + ) # ----- Objective ----- # @objective(m, Min, objvar) diff --git a/examples/MINLPs/linearlift.jl b/examples/MINLPs/linearlift.jl index c2389022..bfbbf7e1 100644 --- a/examples/MINLPs/linearlift.jl +++ b/examples/MINLPs/linearlift.jl @@ -1,27 +1,30 @@ -function basic_linear_lift(;verbose = false, solver = nothing) +function basic_linear_lift(; verbose = false, solver = nothing) + if solver === nothing + m = Model( + Alpine.Optimizer( + nlp_solver = IpoptSolver(), + mip_solver = CbcSolver(log_level = 0), + log_level = 10000, + ), + ) + else + m = Model(solver) + end - if solver === nothing - m = Model(Alpine.Optimizer(nlp_solver=IpoptSolver(), - mip_solver=CbcSolver(log_level=0), - log_level=10000)) - else - m = Model(solver) - end + @variable(m, x[i = 1:3] >= 1) # At some point if an initial value is given, keep them - @variable(m, x[i=1:3]>=1) # At some point if an initial value is given, keep them + @constraint(m, (x[1] - x[2]) * (3 * x[2] - x[3]) >= 111) + @NLconstraint(m, (x[1] - x[2]) * (3 * x[2] - x[3]) >= 111) + @NLconstraint(m, (x[1] - x[2])^2 >= 100) + @NLconstraint(m, (x[1] - x[2]) * (3 * x[2] - x[3]) * (x[1] + x[3]) >= 111) + @NLconstraint(m, (3 + x[1] + x[2] + x[3]) * (x[1] + x[2])^2 >= 111) - @constraint(m, (x[1]-x[2])*(3*x[2]-x[3]) >= 111) - @NLconstraint(m, (x[1]-x[2])*(3*x[2]-x[3]) >= 111) - @NLconstraint(m, (x[1]-x[2])^2 >= 100) - @NLconstraint(m, (x[1]-x[2])*(3*x[2]-x[3])*(x[1]+x[3]) >= 111) - @NLconstraint(m, (3+x[1]+x[2]+x[3])*(x[1]+x[2])^2 >= 111) + # Next level goal + # @NLconstraint(m, (9-x[1]-x[2]-x[3])^2 >= 111) - # Next level goal - # @NLconstraint(m, (9-x[1]-x[2]-x[3])^2 >= 111) + @objective(m, Min, x[1] + x[2] + x[3]) - @objective(m, Min, x[1]+x[2]+x[3]) + verbose && print(m) - verbose && print(m) - - return m + return m end diff --git a/examples/MINLPs/multi.jl b/examples/MINLPs/multi.jl index b3429af3..2b496457 100644 --- a/examples/MINLPs/multi.jl +++ b/examples/MINLPs/multi.jl @@ -19,169 +19,192 @@ # println("N | K | convhull | exprmode | unifrom | randomub | sos2 | presolve | delta") # println("--------------------------------------------------------------------------") -function multi4(;verbose = false,solver = nothing, exprmode=1) - - m = Model(solver) - - Random.seed!(1) - @variable(m, 0.1<=x[1:4]<=rand()*100) - if exprmode == 1 - @NLobjective(m, Max, x[1]*x[2]*x[3]*x[4]) - elseif exprmode == 2 - @NLobjective(m, Max, (x[1]*x[2])*(x[3]*x[4])) - elseif exprmode == 3 - @NLobjective(m, Max, (x[1]*x[2])*x[3]*x[4]) - elseif exprmode == 4 - @NLobjective(m, Max, x[1]*x[2]*(x[3]*x[4])) - elseif exprmode == 5 - @NLobjective(m, Max, (((x[1]*x[2])*x[3])*x[4])) - elseif exprmode == 6 - @NLobjective(m, Max, (x[1]*x[2]*x[3])*x[4]) - elseif exprmode == 7 - @NLobjective(m, Max, x[1]*(x[2]*(x[3]*x[4]))) - elseif exprmode == 8 - @NLobjective(m, Max, x[1]*(x[2]*x[3])*x[4]) - elseif exprmode == 9 - @NLobjective(m, Max, x[1]*(x[2]*x[3]*x[4])) - elseif exprmode == 10 - @NLobjective(m, Max, x[1]*((x[2]*x[3])*x[4])) - elseif exprmode == 11 - @NLobjective(m, Max, (x[1]*(x[2]*x[3]))*x[4]) - else - error("exprmode argument only taks from 1-7") - end - @constraint(m, sum(x[i] for i in 1:4) <= 4) - - if verbose - print(m) - end - - return m +function multi4(; verbose = false, solver = nothing, exprmode = 1) + m = Model(solver) + + Random.seed!(1) + @variable(m, 0.1 <= x[1:4] <= rand() * 100) + if exprmode == 1 + @NLobjective(m, Max, x[1] * x[2] * x[3] * x[4]) + elseif exprmode == 2 + @NLobjective(m, Max, (x[1] * x[2]) * (x[3] * x[4])) + elseif exprmode == 3 + @NLobjective(m, Max, (x[1] * x[2]) * x[3] * x[4]) + elseif exprmode == 4 + @NLobjective(m, Max, x[1] * x[2] * (x[3] * x[4])) + elseif exprmode == 5 + @NLobjective(m, Max, (((x[1] * x[2]) * x[3]) * x[4])) + elseif exprmode == 6 + @NLobjective(m, Max, (x[1] * x[2] * x[3]) * x[4]) + elseif exprmode == 7 + @NLobjective(m, Max, x[1] * (x[2] * (x[3] * x[4]))) + elseif exprmode == 8 + @NLobjective(m, Max, x[1] * (x[2] * x[3]) * x[4]) + elseif exprmode == 9 + @NLobjective(m, Max, x[1] * (x[2] * x[3] * x[4])) + elseif exprmode == 10 + @NLobjective(m, Max, x[1] * ((x[2] * x[3]) * x[4])) + elseif exprmode == 11 + @NLobjective(m, Max, (x[1] * (x[2] * x[3])) * x[4]) + else + error("exprmode argument only taks from 1-7") + end + @constraint(m, sum(x[i] for i in 1:4) <= 4) + + if verbose + print(m) + end + + return m end -function multi3(;verbose = false, solver = nothing, exprmode=1) - - m = Model(solver) - - Random.seed!(1) - ub = rand() - @variable(m, 0.1<=x[1:3]<=ub*1000) - if exprmode == 1 - @NLobjective(m, Max, x[1]*x[2]*x[3]) - elseif exprmode == 2 - @NLobjective(m, Max, (x[1]*x[2])*x[3]) - elseif exprmode == 3 - @NLobjective(m, Max, x[1]*(x[2]*x[3])) - else - error("exprmode argument only taks from 1-7") - end - - @constraint(m, sum(x[i] for i in 1:3) <= 3) - - if verbose - print(m) - end - - return m +function multi3(; verbose = false, solver = nothing, exprmode = 1) + m = Model(solver) + + Random.seed!(1) + ub = rand() + @variable(m, 0.1 <= x[1:3] <= ub * 1000) + if exprmode == 1 + @NLobjective(m, Max, x[1] * x[2] * x[3]) + elseif exprmode == 2 + @NLobjective(m, Max, (x[1] * x[2]) * x[3]) + elseif exprmode == 3 + @NLobjective(m, Max, x[1] * (x[2] * x[3])) + else + error("exprmode argument only taks from 1-7") + end + + @constraint(m, sum(x[i] for i in 1:3) <= 3) + + if verbose + print(m) + end + + return m end -function multi2(;verbose = false,solver = nothing) - # Global solution: 0.92906489 (arg min: [0.7336635, 1.266336]) +function multi2(; verbose = false, solver = nothing) + # Global solution: 0.92906489 (arg min: [0.7336635, 1.266336]) - m = Model(solver) + m = Model(solver) - Random.seed!(1) - @variable(m, 0.1<=x[1:2]<=rand()*10) - @NLobjective(m, Max, x[1]*x[2]) - @constraint(m, sum(x[i] for i in 1:2) <= 2) + Random.seed!(1) + @variable(m, 0.1 <= x[1:2] <= rand() * 10) + @NLobjective(m, Max, x[1] * x[2]) + @constraint(m, sum(x[i] for i in 1:2) <= 2) - if verbose - print(m) - end + if verbose + print(m) + end - return m + return m end -function multi4N(;verbose = false, exprmode=1, solver = nothing, N=1, randomub=true) - - m = Model(solver) - - M = 1+3*N - Random.seed!(100) - isa(randomub, Bool) ? @variable(m, 0.1 <= x[1:M] <= 100*rand()) : @variable(m, 0.1 <= x[1:M] <= randomub) - - if exprmode == 1 - @NLobjective(m, Max, sum(x[i]*x[i+1]*x[i+2]*x[i+3] for i in 1:3:(M-1))) - elseif exprmode == 2 - @NLobjective(m, Max, sum((x[i]*x[i+1])*(x[i+2]*x[i+3]) for i in 1:3:(M-1))) - elseif exprmode == 3 - @NLobjective(m, Max, sum((x[i]*x[i+1])*x[i+2]*x[i+3] for i in 1:3:(M-1))) - elseif exprmode == 4 - @NLobjective(m, Max, sum(x[i]*x[i+1]*(x[i+2]*x[i+3]) for i in 1:3:(M-1))) - elseif exprmode == 5 - @NLobjective(m, Max, sum((((x[i]*x[i+1])*x[i+2])*x[i+3]) for i in 1:3:(M-1))) - elseif exprmode == 6 - @NLobjective(m, Max, sum((x[i]*x[i+1]*x[i+2])*x[i+3] for i in 1:3:(M-1))) - elseif exprmode == 7 - @NLobjective(m, Max, sum(x[i]*(x[i+1]*(x[i+2]*x[i+3])) for i in 1:3:(M-1))) - elseif exprmode == 8 - @NLobjective(m, Max, sum(x[i]*(x[i+1]*x[i+2])*x[i+3] for i in 1:3:(M-1))) - elseif exprmode == 9 - @NLobjective(m, Max, sum(x[i]*(x[i+1]*x[i+2]*x[i+3]) for i in 1:3:(M-1))) - elseif exprmode == 10 - @NLobjective(m, Max, sum(x[i]*((x[i+1]*x[i+2])*x[i+3]) for i in 1:3:(M-1))) - elseif exprmode == 11 - @NLobjective(m, Max, sum((x[i]*(x[i+1]*x[i+2]))*x[i+3] for i in 1:3:(M-1))) - else - error("exprmode argument only taks from 1-7") - end - - @constraint(m, [i in 1:3:(M-1)], x[i]+x[i+1]+x[i+2]+x[i+3]<=4) - - if verbose - print(m) - end - - return m +function multi4N(; + verbose = false, + exprmode = 1, + solver = nothing, + N = 1, + randomub = true, +) + m = Model(solver) + + M = 1 + 3 * N + Random.seed!(100) + isa(randomub, Bool) ? @variable(m, 0.1 <= x[1:M] <= 100 * rand()) : + @variable(m, 0.1 <= x[1:M] <= randomub) + + if exprmode == 1 + @NLobjective(m, Max, sum(x[i] * x[i+1] * x[i+2] * x[i+3] for i in 1:3:(M-1))) + elseif exprmode == 2 + @NLobjective(m, Max, sum((x[i] * x[i+1]) * (x[i+2] * x[i+3]) for i in 1:3:(M-1))) + elseif exprmode == 3 + @NLobjective(m, Max, sum((x[i] * x[i+1]) * x[i+2] * x[i+3] for i in 1:3:(M-1))) + elseif exprmode == 4 + @NLobjective(m, Max, sum(x[i] * x[i+1] * (x[i+2] * x[i+3]) for i in 1:3:(M-1))) + elseif exprmode == 5 + @NLobjective( + m, + Max, + sum((((x[i] * x[i+1]) * x[i+2]) * x[i+3]) for i in 1:3:(M-1)) + ) + elseif exprmode == 6 + @NLobjective(m, Max, sum((x[i] * x[i+1] * x[i+2]) * x[i+3] for i in 1:3:(M-1))) + elseif exprmode == 7 + @NLobjective(m, Max, sum(x[i] * (x[i+1] * (x[i+2] * x[i+3])) for i in 1:3:(M-1))) + elseif exprmode == 8 + @NLobjective(m, Max, sum(x[i] * (x[i+1] * x[i+2]) * x[i+3] for i in 1:3:(M-1))) + elseif exprmode == 9 + @NLobjective(m, Max, sum(x[i] * (x[i+1] * x[i+2] * x[i+3]) for i in 1:3:(M-1))) + elseif exprmode == 10 + @NLobjective(m, Max, sum(x[i] * ((x[i+1] * x[i+2]) * x[i+3]) for i in 1:3:(M-1))) + elseif exprmode == 11 + @NLobjective(m, Max, sum((x[i] * (x[i+1] * x[i+2])) * x[i+3] for i in 1:3:(M-1))) + else + error("exprmode argument only taks from 1-7") + end + + @constraint(m, [i in 1:3:(M-1)], x[i] + x[i+1] + x[i+2] + x[i+3] <= 4) + + if verbose + print(m) + end + + return m end -function multi3N(;verbose = false, randomub=nothing, solver = nothing, exprmode=1, N=1, delta=4) - - m = Model(solver) - - M = 1+2*N - Random.seed!(100) - isa(randomub, Int) ? @variable(m, 0.1<=x[1:M]<=randomub) : @variable(m, 0.1<=x[1:M]<=rand()*100) - if exprmode == 1 - @NLobjective(m, Max, sum(x[i]*x[i+1]*x[i+2] for i in 1:2:(M-1))) - elseif exprmode == 2 - @NLobjective(m, Max, sum((x[i]*x[i+1])*x[i+2] for i in 1:2:(M-1))) - elseif exprmode == 3 - @NLobjective(m, Max, sum(x[i]*(x[i+1]*x[i+2]) for i in 1:2:(M-1))) - else - error("exprmode argument only taks from 1-7") - end - - @constraint(m, [i in 1:2:(M-1)], x[i] + x[i+1] + x[i+2] <= 3) - - if verbose - print(m) - end - - return m +function multi3N(; + verbose = false, + randomub = nothing, + solver = nothing, + exprmode = 1, + N = 1, + delta = 4, +) + m = Model(solver) + + M = 1 + 2 * N + Random.seed!(100) + isa(randomub, Int) ? @variable(m, 0.1 <= x[1:M] <= randomub) : + @variable(m, 0.1 <= x[1:M] <= rand() * 100) + if exprmode == 1 + @NLobjective(m, Max, sum(x[i] * x[i+1] * x[i+2] for i in 1:2:(M-1))) + elseif exprmode == 2 + @NLobjective(m, Max, sum((x[i] * x[i+1]) * x[i+2] for i in 1:2:(M-1))) + elseif exprmode == 3 + @NLobjective(m, Max, sum(x[i] * (x[i+1] * x[i+2]) for i in 1:2:(M-1))) + else + error("exprmode argument only taks from 1-7") + end + + @constraint(m, [i in 1:2:(M-1)], x[i] + x[i+1] + x[i+2] <= 3) + + if verbose + print(m) + end + + return m end -function multiKND(;verbose = false, solver = nothing, exprmode=1, randomub=true, N=1, K=2, D=1) - - m = Model(solver) - - M = K+(K-D)*(N-1) - Random.seed!(100) - isa(randomub, Int) ? @variable(m, 0.1<=x[1:M]<=randomub) : @variable(m, 0.1<=x[1:M]<=rand()*100) - @NLobjective(m, Max, sum(prod(x[i+k] for k in 0:(K-1)) for i in 1:(K-D):(M-D))) - @constraint(m, [i in 1:(K-D):(M-D)], sum(x[i+k] for k in 0:(K-1)) <= K) - - verbose && print(m) - - return m +function multiKND(; + verbose = false, + solver = nothing, + exprmode = 1, + randomub = true, + N = 1, + K = 2, + D = 1, +) + m = Model(solver) + + M = K + (K - D) * (N - 1) + Random.seed!(100) + isa(randomub, Int) ? @variable(m, 0.1 <= x[1:M] <= randomub) : + @variable(m, 0.1 <= x[1:M] <= rand() * 100) + @NLobjective(m, Max, sum(prod(x[i+k] for k in 0:(K-1)) for i in 1:(K-D):(M-D))) + @constraint(m, [i in 1:(K-D):(M-D)], sum(x[i+k] for k in 0:(K-1)) <= K) + + verbose && print(m) + + return m end diff --git a/examples/MINLPs/nlp.jl b/examples/MINLPs/nlp.jl index ae042594..143eefe2 100644 --- a/examples/MINLPs/nlp.jl +++ b/examples/MINLPs/nlp.jl @@ -1,80 +1,84 @@ -function nlp1(;verbose = false,solver = nothing, convhull=false, presolve=0) - - if solver === nothing - m = Model(Alpine.Optimizer(nlp_solver=IpoptSolver(print_level=0), - mip_solver=GurobiSolver(OutputFlag=0), - bilinear_convexhull=convhull, - monomial_convexhull=convhull, - presolve_bt=(presolve>0), - presolve_bt_algo=presolve, - presolve_bt_bound_tol=1e-1, - log_level=10000)) - else - m = Model(solver) - end - - @variable(m, 1<=x[1:2]<=10) - - @NLconstraint(m, x[1]*x[2] >= 8) - @NLobjective(m, Min, 6*x[1]^2 + 4*x[2]^2 - 2.5*x[1]*x[2]) - - return m +function nlp1(; verbose = false, solver = nothing, convhull = false, presolve = 0) + if solver === nothing + m = Model( + Alpine.Optimizer( + nlp_solver = IpoptSolver(print_level = 0), + mip_solver = GurobiSolver(OutputFlag = 0), + bilinear_convexhull = convhull, + monomial_convexhull = convhull, + presolve_bt = (presolve > 0), + presolve_bt_algo = presolve, + presolve_bt_bound_tol = 1e-1, + log_level = 10000, + ), + ) + else + m = Model(solver) + end + + @variable(m, 1 <= x[1:2] <= 10) + + @NLconstraint(m, x[1] * x[2] >= 8) + @NLobjective(m, Min, 6 * x[1]^2 + 4 * x[2]^2 - 2.5 * x[1] * x[2]) + + return m end -function nlp2(;verbose = false,solver = nothing, convhull=false, presolve=0) - - if solver === nothing - m = Model(Alpine.Optimizer(nlp_solver=IpoptSolver(print_level=0), - mip_solver=GurobiSolver(OutputFlag=0), - bilinear_convexhull=convhull, - monomial_convexhull=convhull, - presolve_bt=(presolve>0), - presolve_bt_algo=presolve, - presolve_bt_bound_tol=1e-1, - log_level=10000)) - else - m = Model(solver) - end - - @variable(m, -500<=x[1:2]<=500) - - @NLobjective(m, Min, sum((x[i]^2 - i)^2 for i in 1:2)) - - return m +function nlp2(; verbose = false, solver = nothing, convhull = false, presolve = 0) + if solver === nothing + m = Model( + Alpine.Optimizer( + nlp_solver = IpoptSolver(print_level = 0), + mip_solver = GurobiSolver(OutputFlag = 0), + bilinear_convexhull = convhull, + monomial_convexhull = convhull, + presolve_bt = (presolve > 0), + presolve_bt_algo = presolve, + presolve_bt_bound_tol = 1e-1, + log_level = 10000, + ), + ) + else + m = Model(solver) + end + + @variable(m, -500 <= x[1:2] <= 500) + + @NLobjective(m, Min, sum((x[i]^2 - i)^2 for i in 1:2)) + + return m end function max_cover_var_picker(m::Alpine.Optimizer) - nodes = Set() - for pair in keys(m.nonconvex_terms) - for i in pair - @assert isa(i.args[2], Int) - push!(nodes, i.args[2]) - end - end - nodes = collect(nodes) - m.num_var_disc_mip = length(nodes) - m.disc_vars = nodes - return + nodes = Set() + for pair in keys(m.nonconvex_terms) + for i in pair + @assert isa(i.args[2], Int) + push!(nodes, i.args[2]) + end + end + nodes = collect(nodes) + m.num_var_disc_mip = length(nodes) + m.disc_vars = nodes + return end - -function nlp3(;solver = nothing) - - m = Model(solver) +function nlp3(; solver = nothing) + m = Model(solver) LB = [100, 1000, 1000, 10, 10, 10, 10, 10] - UB = [10000, 10000, 10000, 1000, 1000, 1000, 1000, 1000] + UB = [10000, 10000, 10000, 1000, 1000, 1000, 1000, 1000] - @variable(m, LB[i] <= x[i=1:8] <= UB[i]) + @variable(m, LB[i] <= x[i = 1:8] <= UB[i]) - @constraint(m, 0.0025*(x[4] + x[6]) <= 1) - @constraint(m, 0.0025*(x[5] - x[4] + x[7]) <= 1) - @constraint(m, 0.01(x[8]-x[5]) <= 1) - @NLconstraint(m, 100*x[1] - x[1]*x[6] + 833.33252*x[4] <= 83333.333) - @NLconstraint(m, x[2]*x[4] - x[2]*x[7] - 1250*x[4] + 1250*x[5] <= 0) - @NLconstraint(m, x[3]*x[5] - x[3]*x[8] - 2500*x[5] + 1250000 <= 0) + @constraint(m, 0.0025 * (x[4] + x[6]) <= 1) + @constraint(m, 0.0025 * (x[5] - x[4] + x[7]) <= 1) + @constraint(m, 0.01(x[8] - x[5]) <= 1) + @NLconstraint(m, 100 * x[1] - x[1] * x[6] + 833.33252 * x[4] <= 83333.333) + @NLconstraint(m, x[2] * x[4] - x[2] * x[7] - 1250 * x[4] + 1250 * x[5] <= 0) + @NLconstraint(m, x[3] * x[5] - x[3] * x[8] - 2500 * x[5] + 1250000 <= 0) - @objective(m, Min, x[1]+x[2]+x[3]) + @objective(m, Min, x[1] + x[2] + x[3]) - return m + return m end diff --git a/examples/MINLPs/rosenbrock.jl b/examples/MINLPs/rosenbrock.jl index f3778ca9..3ce7d647 100644 --- a/examples/MINLPs/rosenbrock.jl +++ b/examples/MINLPs/rosenbrock.jl @@ -1,14 +1,13 @@ # Reference: https://direct.mit.edu/evco/article/14/1/119/1232/A-Note-on-the-Extended-Rosenbrock-Function # Global optimum = 0.0, arg min = (1,1) -function rosenbrock(;solver = nothing) - - m = Model(solver) +function rosenbrock(; solver = nothing) + m = Model(solver) @variable(m, -10 <= x <= 10) @variable(m, -10 <= y <= 10) - @NLobjective(m, Min, 100*(y-x^2)^2 + (1-x)^2) + @NLobjective(m, Min, 100 * (y - x^2)^2 + (1 - x)^2) - return m -end \ No newline at end of file + return m +end diff --git a/examples/MINLPs/sincos.jl b/examples/MINLPs/sincos.jl index c9e30344..2e3c2987 100644 --- a/examples/MINLPs/sincos.jl +++ b/examples/MINLPs/sincos.jl @@ -1,19 +1,17 @@ # Functions in this file are not tested until support for trigonometric functions is added. -function sincos_p1(;solver = nothing) - +function sincos_p1(; solver = nothing) m = Model(solver) - @variable(m, 0.1<=x[1:10]<=10) - @NLconstraint(m, [i in 1:9], x[i]*x[i+1]*sin(x[i])>=0.32) - @NLconstraint(m, [i in 1:9], x[i]*x[i+1]*sin(x[i])<=0.42) - @NLobjective(m, Min, sum(cos(x[i])+sin(x[i]) for i in 1:10)) + @variable(m, 0.1 <= x[1:10] <= 10) + @NLconstraint(m, [i in 1:9], x[i] * x[i+1] * sin(x[i]) >= 0.32) + @NLconstraint(m, [i in 1:9], x[i] * x[i+1] * sin(x[i]) <= 0.42) + @NLobjective(m, Min, sum(cos(x[i]) + sin(x[i]) for i in 1:10)) return m end -function trig(;solver = nothing) - +function trig(; solver = nothing) m = Model(solver) @variable(m, objvar) @@ -22,29 +20,33 @@ function trig(;solver = nothing) JuMP.set_lower_bound(x[1], -2.0) JuMP.set_upper_bound(x[1], 5.0) - @NLconstraint(m, e1, -(sin(11*x[1])+cos(13*x[1])-sin(17*x[1])-cos(19*x[1]))+objvar == 0.0) - @NLconstraint(m, e2, 5*sin(x[1])-x[1] <= 0.0) + @NLconstraint( + m, + e1, + -(sin(11 * x[1]) + cos(13 * x[1]) - sin(17 * x[1]) - cos(19 * x[1])) + objvar == + 0.0 + ) + @NLconstraint(m, e2, 5 * sin(x[1]) - x[1] <= 0.0) @objective(m, Min, objvar) return m end -function specialopts(;verbose = false, solver = nothing) - - m = Model(solver) +function specialopts(; verbose = false, solver = nothing) + m = Model(solver) - @variable(m, x[i=1:6]) + @variable(m, x[i = 1:6]) @NLconstraint(m, sin(x[1]) + cos(x[2]) >= 1) @NLconstraint(m, sin(x[1]) * x[2] >= 1) @NLconstraint(m, sin(x[1]) * cos(x[2]) >= 1) # - @NLconstraint(m, sin(x[1]*x[2]) >= 0.5) - @NLconstraint(m, cos(x[1]+x[2]) >= 0.5) - @NLconstraint(m, cos(x[1]/2) >= 0.5) - @NLconstraint(m, cos(x[1]*x[2]/5) >= 0.5) - @NLconstraint(m, sin(x[1]/5+x[2]/5) >= 0.5) + @NLconstraint(m, sin(x[1] * x[2]) >= 0.5) + @NLconstraint(m, cos(x[1] + x[2]) >= 0.5) + @NLconstraint(m, cos(x[1] / 2) >= 0.5) + @NLconstraint(m, cos(x[1] * x[2] / 5) >= 0.5) + @NLconstraint(m, sin(x[1] / 5 + x[2] / 5) >= 0.5) - return m + return m end diff --git a/examples/Project.toml b/examples/Project.toml index 77bae298..a2e1d062 100644 --- a/examples/Project.toml +++ b/examples/Project.toml @@ -10,5 +10,4 @@ Pavito = "cd433a01-47d1-575d-afb7-6db927ee8d8f" Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" [compat] -JuMP = "~1.0" julia = "1" diff --git a/examples/optimizers.jl b/examples/optimizers.jl index cb1400ea..dd6cca7d 100644 --- a/examples/optimizers.jl +++ b/examples/optimizers.jl @@ -1,43 +1,52 @@ # MIP solver - commercial function get_gurobi() - return optimizer_with_attributes(Gurobi.Optimizer, - MOI.Silent() => true, - "Presolve" => 1) + return optimizer_with_attributes( + Gurobi.Optimizer, + MOI.Silent() => true, + "Presolve" => 1, + ) end function get_cplex() - return optimizer_with_attributes(CPLEX.Optimizer, - MOI.Silent() => true, - "CPX_PARAM_PREIND" => 1) + return optimizer_with_attributes( + CPLEX.Optimizer, + MOI.Silent() => true, + "CPX_PARAM_PREIND" => 1, + ) end # MIP solver - open-source function get_cbc() - return optimizer_with_attributes(Cbc.Optimizer, - MOI.Silent() => true) + return optimizer_with_attributes(Cbc.Optimizer, MOI.Silent() => true) end # Local solver function get_ipopt() - return optimizer_with_attributes(Ipopt.Optimizer, - MOI.Silent() => true, - "sb" => "yes", - "max_iter" => Int(1E4)) + return optimizer_with_attributes( + Ipopt.Optimizer, + MOI.Silent() => true, + "sb" => "yes", + "max_iter" => Int(1E4), + ) end # Convex MINLP solver function get_pavito(mip_solver, cont_solver) - return optimizer_with_attributes(Pavito.Optimizer, - MOI.Silent() => true, - "mip_solver" => mip_solver, - "cont_solver" => cont_solver, - "mip_solver_drives" => false) + return optimizer_with_attributes( + Pavito.Optimizer, + MOI.Silent() => true, + "mip_solver" => mip_solver, + "cont_solver" => cont_solver, + "mip_solver_drives" => false, + ) end # Non-convex Local MINLP solver function get_juniper(mip_solver, nl_solver) - return optimizer_with_attributes(Juniper.Optimizer, - MOI.Silent() => true, - "mip_solver" => mip_solver, - "nl_solver" => nl_solver) -end \ No newline at end of file + return optimizer_with_attributes( + Juniper.Optimizer, + MOI.Silent() => true, + "mip_solver" => mip_solver, + "nl_solver" => nl_solver, + ) +end diff --git a/examples/run_examples.jl b/examples/run_examples.jl index 32abfdf8..4c3792a3 100644 --- a/examples/run_examples.jl +++ b/examples/run_examples.jl @@ -1,5 +1,5 @@ # - Necessary - # -using Alpine +using Alpine using JuMP using Gurobi using Ipopt @@ -15,8 +15,8 @@ include("JuMP_models.jl") include("optimizers.jl") # Choose underlying solvers for Alpine -ipopt = get_ipopt() -gurobi = get_gurobi() +ipopt = get_ipopt() +gurobi = get_gurobi() juniper = get_juniper(gurobi, ipopt) #= Global solver @@ -27,14 +27,16 @@ juniper = get_juniper(gurobi, ipopt) => If you prefer to use Alpine for only OBBT presolve, without any paritioning applied to the nonlinear terms, include option "apply_partitioning" below and set it to false. =# -const alpine = JuMP.optimizer_with_attributes(Alpine.Optimizer, - "minlp_solver" => juniper, - "nlp_solver" => ipopt, - "mip_solver" => gurobi, - "presolve_bt" => true, - "disc_ratio" => 10) +const alpine = JuMP.optimizer_with_attributes( + Alpine.Optimizer, + "minlp_solver" => juniper, + "nlp_solver" => ipopt, + "mip_solver" => gurobi, + "presolve_bt" => true, + "disc_ratio" => 10, +) m = nlp3(solver = alpine) JuMP.optimize!(m) -# Alpine.variable_values(m) \ No newline at end of file +# Alpine.variable_values(m) diff --git a/examples/run_examples_linking.jl b/examples/run_examples_linking.jl index 2e34ec3c..980c52a0 100644 --- a/examples/run_examples_linking.jl +++ b/examples/run_examples_linking.jl @@ -9,11 +9,11 @@ using Logging # Install library package. To install, at your Julia command prompt, # Pkg.add(path="https://github.com/lanl-ansi/MINLPLib.jl.git") # Reference: https://github.com/lanl-ansi/MINLPLib.jl -import MINLPLib +import MINLPLib # Choose underlying solvers for Alpine -ipopt = get_ipopt() -gurobi = get_gurobi() +ipopt = get_ipopt() +gurobi = get_gurobi() juniper = get_juniper(gurobi, ipopt) #= Global solver @@ -26,23 +26,25 @@ juniper = get_juniper(gurobi, ipopt) =# function run(use_linking_constraints, time_limit, instance_name) - alpine = JuMP.optimizer_with_attributes(Alpine.Optimizer, - "minlp_solver" => juniper, - "nlp_solver" => ipopt, - "mip_solver" => gurobi, - "presolve_bt" => true, - "disc_ratio" => 10, - "time_limit" => time_limit, - "linking_constraints" => use_linking_constraints) - m = MINLPLib.fetch_model(instance_name) - JuMP.set_optimizer(m, alpine) - - t_begin = time() - JuMP.optimize!(m) - objval = JuMP.objective_value(m) - soltime = time() - t_begin - - return objval, soltime + alpine = JuMP.optimizer_with_attributes( + Alpine.Optimizer, + "minlp_solver" => juniper, + "nlp_solver" => ipopt, + "mip_solver" => gurobi, + "presolve_bt" => true, + "disc_ratio" => 10, + "time_limit" => time_limit, + "linking_constraints" => use_linking_constraints, + ) + m = MINLPLib.fetch_model(instance_name) + JuMP.set_optimizer(m, alpine) + + t_begin = time() + JuMP.optimize!(m) + objval = JuMP.objective_value(m) + soltime = time() - t_begin + + return objval, soltime end # Linking constraints are only added when there are multilinear terms whose degree is at least 3. diff --git a/src/MOI_wrapper/MOI_function2expr.jl b/src/MOI_wrapper/MOI_function2expr.jl index 1ed42ece..be65ad4a 100644 --- a/src/MOI_wrapper/MOI_function2expr.jl +++ b/src/MOI_wrapper/MOI_function2expr.jl @@ -26,7 +26,13 @@ function _term_to_expr(t::MOI.ScalarQuadraticTerm) if t.variable_1 == t.variable_2 coef /= 2 end - return Expr(:call, :*, coef, _variable_index_to_expr(t.variable_1), _variable_index_to_expr(t.variable_2)) + return Expr( + :call, + :*, + coef, + _variable_index_to_expr(t.variable_1), + _variable_index_to_expr(t.variable_2), + ) end function _add_terms(expr::Expr, terms::Vector) @@ -45,10 +51,11 @@ end function _moi_function_to_expr(t::MOI.ScalarQuadraticTerm) return Expr( - :call, :*, + :call, + :*, MOI.coefficient(t), _variable_index_to_expr(t.variable_1), - _variable_index_to_expr(t.variable_2) + _variable_index_to_expr(t.variable_2), ) end diff --git a/src/MOI_wrapper/MOI_wrapper.jl b/src/MOI_wrapper/MOI_wrapper.jl index 48cf5c42..39bdff04 100644 --- a/src/MOI_wrapper/MOI_wrapper.jl +++ b/src/MOI_wrapper/MOI_wrapper.jl @@ -7,97 +7,100 @@ Alpine.Optimizer struct """ mutable struct Optimizer <: MOI.AbstractOptimizer - - options :: OptimizerOptions # Options set by user + options::OptimizerOptions # Options set by user # Sub-solver identifier for customized solver option - nlp_solver_id :: AbstractString # NLP Solver identifier string - minlp_solver_id :: AbstractString # MINLP local solver identifier string - mip_solver_id :: AbstractString # MIP solver identifier string + nlp_solver_id::AbstractString # NLP Solver identifier string + minlp_solver_id::AbstractString # MINLP local solver identifier string + mip_solver_id::AbstractString # MIP solver identifier string # User inputs - num_var_orig :: Int # Initial number of variables - num_cont_var_orig :: Int # Initial number of continuous variables - num_int_var_orig :: Int # Initial number of binary/integer variables - num_constr_orig :: Int # Initial number of constraints - num_lconstr_orig :: Int # Initial number of linear constraints - num_nlconstr_orig :: Int # Initial number of non-linear constraints - var_type_orig :: Vector{Symbol} # Variable type vector on original variables (only :Bin, :Cont, :Int) - var_start_orig :: Vector{Float64} # Variable warm start vector on original variables - constr_type_orig :: Vector{Symbol} # Constraint type vector on original variables (only :(==), :(>=), :(<=)) - lin_quad_constraints :: Vector{Any} # Constraint `func`-in-`set` values - constr_expr_orig :: Vector{Expr} # Constraint expressions - obj_expr_orig :: Union{Expr,Number} # Objective expression + num_var_orig::Int # Initial number of variables + num_cont_var_orig::Int # Initial number of continuous variables + num_int_var_orig::Int # Initial number of binary/integer variables + num_constr_orig::Int # Initial number of constraints + num_lconstr_orig::Int # Initial number of linear constraints + num_nlconstr_orig::Int # Initial number of non-linear constraints + var_type_orig::Vector{Symbol} # Variable type vector on original variables (only :Bin, :Cont, :Int) + var_start_orig::Vector{Float64} # Variable warm start vector on original variables + constr_type_orig::Vector{Symbol} # Constraint type vector on original variables (only :(==), :(>=), :(<=)) + lin_quad_constraints::Vector{Any} # Constraint `func`-in-`set` values + constr_expr_orig::Vector{Expr} # Constraint expressions + obj_expr_orig::Union{Expr,Number} # Objective expression # Additional user inputs concerning local solves - l_var_orig :: Vector{Float64} # Variable lower bounds - u_var_orig :: Vector{Float64} # Variable upper bounds - constraint_bounds_orig :: Vector{MOI.NLPBoundsPair} # Constraint lower bounds - nl_constraint_bounds_orig :: Vector{MOI.NLPBoundsPair} # Constraint lower bounds - sense_orig :: MOI.OptimizationSense # Problem type (:Min, :Max) - d_orig :: Union{Nothing, MOI.AbstractNLPEvaluator} # Instance of AbstractNLPEvaluator for evaluating gradient, Hessian-vector products, and Hessians of the Lagrangian - disable_hessian :: Bool # Check if there are any user-defined operators, and disable hessians if necessary. - has_nl_objective :: Bool - objective_function :: Union{Nothing, MOI.ScalarAffineFunction{Float64}, MOI.ScalarQuadraticFunction{Float64}} + l_var_orig::Vector{Float64} # Variable lower bounds + u_var_orig::Vector{Float64} # Variable upper bounds + constraint_bounds_orig::Vector{MOI.NLPBoundsPair} # Constraint lower bounds + nl_constraint_bounds_orig::Vector{MOI.NLPBoundsPair} # Constraint lower bounds + sense_orig::MOI.OptimizationSense # Problem type (:Min, :Max) + d_orig::Union{Nothing,MOI.AbstractNLPEvaluator} # Instance of AbstractNLPEvaluator for evaluating gradient, Hessian-vector products, and Hessians of the Lagrangian + disable_hessian::Bool # Check if there are any user-defined operators, and disable hessians if necessary. + has_nl_objective::Bool + objective_function::Union{ + Nothing, + MOI.ScalarAffineFunction{Float64}, + MOI.ScalarQuadraticFunction{Float64}, + } # Additional initial data - is_obj_linear_orig :: Bool # Boolean parameter for type of objective + is_obj_linear_orig::Bool # Boolean parameter for type of objective # Local solution model (extra data for each iteration) - l_var :: Vector{Float64} # Updated variable lower bounds for local solve - u_var :: Vector{Float64} # Updated variable upper bounds for local solve + l_var::Vector{Float64} # Updated variable lower bounds for local solve + u_var::Vector{Float64} # Updated variable upper bounds for local solve # MIP bounding model - model_mip :: JuMP.Model # JuMP's convex-MIP model for bounding + model_mip::JuMP.Model # JuMP's convex-MIP model for bounding - num_var_linear_mip :: Int # Number of linear lifted variables required - num_var_nonlinear_mip :: Int # Number of lifted variables - num_var_disc_mip :: Int # Number of variables which are discretized - num_constr_convex :: Int # Number of convex constraints + num_var_linear_mip::Int # Number of linear lifted variables required + num_var_nonlinear_mip::Int # Number of lifted variables + num_var_disc_mip::Int # Number of variables which are discretized + num_constr_convex::Int # Number of convex constraints # Expression-related and structural property placeholder - linear_terms :: Dict{Any, Any} # Dictionary containing details of lifted linear terms - nonconvex_terms :: Dict{Any,Any} # Dictionary containing details of lifted non-linear terms - term_seq :: Dict{Int, Any} # Vector-Dictionary for NL terms detection - nonlinear_constrs :: Dict{Any,Any} # Dictionary containing details of special constraints - obj_structure :: Symbol # A symbolic indicator of the expression type of objective function - constr_structure :: Vector{Symbol} # A vector indicating whether a constraint is with the special structure - bounding_obj_expr_mip :: Union{Expr,Number} # Lifted objective expression; if linear, same as obj_expr_orig - bounding_constr_expr_mip :: Vector{Expr} # Lifted constraints; if linear, same as corresponding constr_expr_orig - bounding_obj_mip :: Dict{Any, Any} # Lifted objective expression in affine form - bounding_constr_mip :: Vector{Dict{Any, Any}} # Lifted constraint expressions in affine form + linear_terms::Dict{Any,Any} # Dictionary containing details of lifted linear terms + nonconvex_terms::Dict{Any,Any} # Dictionary containing details of lifted non-linear terms + term_seq::Dict{Int,Any} # Vector-Dictionary for NL terms detection + nonlinear_constrs::Dict{Any,Any} # Dictionary containing details of special constraints + obj_structure::Symbol # A symbolic indicator of the expression type of objective function + constr_structure::Vector{Symbol} # A vector indicating whether a constraint is with the special structure + bounding_obj_expr_mip::Union{Expr,Number} # Lifted objective expression; if linear, same as obj_expr_orig + bounding_constr_expr_mip::Vector{Expr} # Lifted constraints; if linear, same as corresponding constr_expr_orig + bounding_obj_mip::Dict{Any,Any} # Lifted objective expression in affine form + bounding_constr_mip::Vector{Dict{Any,Any}} # Lifted constraint expressions in affine form # Discretization Related options - candidate_disc_vars :: Vector{Int} # A vector of all original variable indices that is involved in the nonlinear terms - discretization :: Dict{Any,Any} # Discretization points with variable keys - disc_vars :: Vector{Int} # Variables chosen for discretization - int_vars :: Vector{Int} # Index vector of integer variables - bin_vars :: Vector{Int} # Index vector of binary variables + candidate_disc_vars::Vector{Int} # A vector of all original variable indices that is involved in the nonlinear terms + discretization::Dict{Any,Any} # Discretization points with variable keys + disc_vars::Vector{Int} # Variables chosen for discretization + int_vars::Vector{Int} # Index vector of integer variables + bin_vars::Vector{Int} # Index vector of binary variables # Reformulated problem options - l_var_tight :: Vector{Float64} # Post-presolve variable upper bounds - u_var_tight :: Vector{Float64} # Post-presolve variable lower bounds - var_type :: Vector{Symbol} # Updated variable type for local solve + l_var_tight::Vector{Float64} # Post-presolve variable upper bounds + u_var_tight::Vector{Float64} # Post-presolve variable lower bounds + var_type::Vector{Symbol} # Updated variable type for local solve # Solution information - presolve_infeasible :: Bool # Presolve infeasibility detection flag - best_bound :: Float64 # Best bound from MIP - best_obj :: Float64 # Best feasible objective value - initial_warmval :: Vector{Float64} # Warmstart values set to Alpine - best_sol :: Vector{Float64} # Best feasible solution - best_bound_sol :: Vector{Float64} # Best bound solution (arg-min) - presolve_best_rel_gap :: Float64 # Post-OBBT relative optimality gap = |best_obj - best_bound|/|best_obj|*100 - best_rel_gap :: Float64 # Relative optimality gap = |best_obj - best_bound|/|best_obj|*100 - best_abs_gap :: Float64 # Absolute gap = |best_obj - best_bound| - bound_sol_history :: Vector{Vector{Float64}} # History of bounding solutions limited by "parameter disc_consecutive_forbid" - bound_sol_pool :: Dict{Any, Any} # A pool of solutions from solving model_mip + presolve_infeasible::Bool # Presolve infeasibility detection flag + best_bound::Float64 # Best bound from MIP + best_obj::Float64 # Best feasible objective value + initial_warmval::Vector{Float64} # Warmstart values set to Alpine + best_sol::Vector{Float64} # Best feasible solution + best_bound_sol::Vector{Float64} # Best bound solution (arg-min) + presolve_best_rel_gap::Float64 # Post-OBBT relative optimality gap = |best_obj - best_bound|/|best_obj|*100 + best_rel_gap::Float64 # Relative optimality gap = |best_obj - best_bound|/|best_obj|*100 + best_abs_gap::Float64 # Absolute gap = |best_obj - best_bound| + bound_sol_history::Vector{Vector{Float64}} # History of bounding solutions limited by "parameter disc_consecutive_forbid" + bound_sol_pool::Dict{Any,Any} # A pool of solutions from solving model_mip # Logging information and status - logs :: Dict{Symbol,Any} # Logging information - detected_feasible_solution :: Bool - detected_bound :: Bool - status :: Dict{Symbol, MOI.TerminationStatusCode} # Detailed status of every iteration in the algorithm - alpine_status :: MOI.TerminationStatusCode # Current Alpine's status + logs::Dict{Symbol,Any} # Logging information + detected_feasible_solution::Bool + detected_bound::Bool + status::Dict{Symbol,MOI.TerminationStatusCode} # Detailed status of every iteration in the algorithm + alpine_status::MOI.TerminationStatusCode # Current Alpine's status # Constructor for Alpine.Optimizer function Optimizer() @@ -110,11 +113,11 @@ end struct NumberOfIterations <: MOI.AbstractModelAttribute end MOI.is_set_by_optimize(::NumberOfIterations) = true -MOI.get(m::Optimizer, ::NumberOfIterations) = m.logs[:n_iter] +MOI.get(m::Optimizer, ::NumberOfIterations) = m.logs[:n_iter] struct NumberOfPresolveIterations <: MOI.AbstractModelAttribute end MOI.is_set_by_optimize(::NumberOfPresolveIterations) = true -MOI.get(m::Optimizer, ::NumberOfPresolveIterations) = m.logs[:bt_iter] +MOI.get(m::Optimizer, ::NumberOfPresolveIterations) = m.logs[:bt_iter] struct TightenedLowerBound <: MOI.AbstractVariableAttribute end MOI.is_set_by_optimize(::TightenedLowerBound) = true @@ -153,14 +156,14 @@ end MOI.get(m::Optimizer, ::MOI.ObjectiveValue) = m.best_obj MOI.get(m::Optimizer, ::MOI.ObjectiveBound) = m.best_bound -MOI.get(m::Optimizer, ::MOI.SolveTimeSec) = m.logs[:total_time] +MOI.get(m::Optimizer, ::MOI.SolveTimeSec) = m.logs[:total_time] function get_option(m::Optimizer, s::Symbol) - getproperty(m.options, s) + return getproperty(m.options, s) end function set_option(m::Optimizer, s::Symbol, val) - setproperty!(m.options, s, val) + return setproperty!(m.options, s, val) end function MOI.is_empty(model::Optimizer) @@ -168,67 +171,68 @@ function MOI.is_empty(model::Optimizer) end function MOI.empty!(m::Optimizer) - m.nlp_solver_id = "" + m.nlp_solver_id = "" m.minlp_solver_id = "" - m.mip_solver_id = "" - - m.num_var_orig = 0 - m.num_cont_var_orig = 0 - m.num_int_var_orig = 0 - m.num_constr_orig = 0 - m.num_lconstr_orig = 0 - m.num_nlconstr_orig = 0 - m.var_type_orig = Symbol[] - m.var_start_orig = Float64[] - m.constr_type_orig = Symbol[] + m.mip_solver_id = "" + + m.num_var_orig = 0 + m.num_cont_var_orig = 0 + m.num_int_var_orig = 0 + m.num_constr_orig = 0 + m.num_lconstr_orig = 0 + m.num_nlconstr_orig = 0 + m.var_type_orig = Symbol[] + m.var_start_orig = Float64[] + m.constr_type_orig = Symbol[] m.lin_quad_constraints = Any[] - m.constr_expr_orig = Expr[] + m.constr_expr_orig = Expr[] # m.num_lconstr_updated = 0 # m.num_nlconstr_updated = 0 # m.indices_lconstr_updated = Int[] - m.l_var_orig = Float64[] - m.u_var_orig = Float64[] - m.constraint_bounds_orig = MOI.NLPBoundsPair[] + m.l_var_orig = Float64[] + m.u_var_orig = Float64[] + m.constraint_bounds_orig = MOI.NLPBoundsPair[] m.nl_constraint_bounds_orig = MOI.NLPBoundsPair[] - m.sense_orig = MOI.FEASIBILITY_SENSE + m.sense_orig = MOI.FEASIBILITY_SENSE - m.d_orig = nothing - m.has_nl_objective = false + m.d_orig = nothing + m.has_nl_objective = false m.objective_function = nothing - m.linear_terms = Dict() - m.nonconvex_terms = Dict() - m.term_seq = Dict() - m.nonlinear_constrs = Dict() - m.candidate_disc_vars = Int[] + m.linear_terms = Dict() + m.nonconvex_terms = Dict() + m.term_seq = Dict() + m.nonlinear_constrs = Dict() + m.candidate_disc_vars = Int[] m.bounding_constr_expr_mip = [] - m.bounding_constr_mip = [] - m.disc_vars = [] - m.int_vars = [] - m.bin_vars = [] - m.discretization = Dict() - m.num_var_linear_mip = 0 - m.num_var_nonlinear_mip = 0 - m.num_var_disc_mip = 0 - m.num_constr_convex = 0 - m.constr_structure = Symbol[] - m.best_bound_sol = [] - m.bound_sol_history = [] - m.presolve_infeasible = false - m.bound_sol_history = Vector{Vector{Float64}}(undef, m.options.disc_consecutive_forbid) - - m.best_obj = Inf - m.initial_warmval = Float64[] - m.best_sol = Float64[] - m.best_bound = -Inf + m.bounding_constr_mip = [] + m.disc_vars = [] + m.int_vars = [] + m.bin_vars = [] + m.discretization = Dict() + m.num_var_linear_mip = 0 + m.num_var_nonlinear_mip = 0 + m.num_var_disc_mip = 0 + m.num_constr_convex = 0 + m.constr_structure = Symbol[] + m.best_bound_sol = [] + m.bound_sol_history = [] + m.presolve_infeasible = false + m.bound_sol_history = + Vector{Vector{Float64}}(undef, m.options.disc_consecutive_forbid) + + m.best_obj = Inf + m.initial_warmval = Float64[] + m.best_sol = Float64[] + m.best_bound = -Inf m.presolve_best_rel_gap = Inf - m.best_rel_gap = Inf - m.best_abs_gap = Inf - m.alpine_status = MOI.OPTIMIZE_NOT_CALLED + m.best_rel_gap = Inf + m.best_abs_gap = Inf + m.alpine_status = MOI.OPTIMIZE_NOT_CALLED create_status!(m) - create_logs!(m) + return create_logs!(m) end MOI.supports_incremental_interface(::Optimizer) = true @@ -241,10 +245,10 @@ MOI.get(::Optimizer, ::MOI.SolverName) = "Alpine" MOI.get(::Optimizer, ::MOI.SolverVersion) = _ALPINE_VERSION function MOI.set(model::Optimizer, param::MOI.RawOptimizerAttribute, value) - Alp.set_option(model, Symbol(param.name), value) + return Alp.set_option(model, Symbol(param.name), value) end function MOI.get(model::Optimizer, param::MOI.RawOptimizerAttribute) - Alp.get_option(model, Symbol(param.name)) + return Alp.get_option(model, Symbol(param.name)) end function MOI.add_variables(model::Optimizer, n::Int) @@ -260,28 +264,42 @@ function MOI.add_variable(model::Optimizer) return MOI.VariableIndex(model.num_var_orig) end -function MOI.supports(::Optimizer, ::MOI.VariablePrimalStart, - ::Type{MOI.VariableIndex}) +function MOI.supports(::Optimizer, ::MOI.VariablePrimalStart, ::Type{MOI.VariableIndex}) return true end -function MOI.set(model::Optimizer, ::MOI.VariablePrimalStart, - vi::MOI.VariableIndex, value::Union{Real, Nothing}) +function MOI.set( + model::Optimizer, + ::MOI.VariablePrimalStart, + vi::MOI.VariableIndex, + value::Union{Real,Nothing}, +) model.best_sol[vi.value] = model.initial_warmval[vi.value] = something(value, 0.0) return end -const SCALAR_SET = Union{MOI.EqualTo{Float64}, MOI.LessThan{Float64}, MOI.GreaterThan{Float64}, MOI.Interval{Float64}} - -MOI.supports_constraint(::Optimizer, ::Type{MOI.VariableIndex}, ::Type{<:SCALAR_SET}) = true +const SCALAR_SET = Union{ + MOI.EqualTo{Float64}, + MOI.LessThan{Float64}, + MOI.GreaterThan{Float64}, + MOI.Interval{Float64}, +} + +function MOI.supports_constraint( + ::Optimizer, + ::Type{MOI.VariableIndex}, + ::Type{<:SCALAR_SET}, +) + return true +end -_lower(set::MOI.EqualTo) = set.value -_upper(set::MOI.EqualTo) = set.value -_lower(set::MOI.LessThan) = nothing -_upper(set::MOI.LessThan) = set.upper +_lower(set::MOI.EqualTo) = set.value +_upper(set::MOI.EqualTo) = set.value +_lower(set::MOI.LessThan) = nothing +_upper(set::MOI.LessThan) = set.upper _lower(set::MOI.GreaterThan) = set.lower _upper(set::MOI.GreaterThan) = nothing -_lower(set::MOI.Interval) = set.lower -_upper(set::MOI.Interval) = set.upper +_lower(set::MOI.Interval) = set.lower +_upper(set::MOI.Interval) = set.upper function MOI.add_constraint(model::Optimizer, vi::MOI.VariableIndex, set::SCALAR_SET) l = _lower(set) @@ -295,25 +313,54 @@ function MOI.add_constraint(model::Optimizer, vi::MOI.VariableIndex, set::SCALAR return MOI.ConstraintIndex{typeof(vi),typeof(set)}(vi.value) end -MOI.supports_constraint(::Optimizer, ::Type{MOI.VariableIndex}, ::Type{MOI.Integer}) = true +function MOI.supports_constraint( + ::Optimizer, + ::Type{MOI.VariableIndex}, + ::Type{MOI.Integer}, +) + return true +end function MOI.add_constraint(model::Optimizer, f::MOI.VariableIndex, set::MOI.Integer) model.var_type_orig[f.value] = :Int - return MOI.ConstraintIndex{typeof(f), typeof(set)}(f.value) + return MOI.ConstraintIndex{typeof(f),typeof(set)}(f.value) +end +function MOI.supports_constraint( + ::Optimizer, + ::Type{MOI.VariableIndex}, + ::Type{MOI.ZeroOne}, +) + return true end -MOI.supports_constraint(::Optimizer, ::Type{MOI.VariableIndex}, ::Type{MOI.ZeroOne}) = true function MOI.add_constraint(model::Optimizer, f::MOI.VariableIndex, set::MOI.ZeroOne) model.var_type_orig[f.value] = :Bin - return MOI.ConstraintIndex{typeof(f), typeof(set)}(f.value) + return MOI.ConstraintIndex{typeof(f),typeof(set)}(f.value) end -MOI.supports_constraint(model::Optimizer, ::Type{<:Union{MOI.ScalarAffineFunction{Float64}, MOI.ScalarQuadraticFunction{Float64}}}, ::Type{<:SCALAR_SET}) = true +function MOI.supports_constraint( + model::Optimizer, + ::Type{ + <:Union{MOI.ScalarAffineFunction{Float64},MOI.ScalarQuadraticFunction{Float64}}, + }, + ::Type{<:SCALAR_SET}, +) + return true +end -function MOI.add_constraint(model::Optimizer, f::Union{MOI.ScalarAffineFunction{Float64}, MOI.ScalarQuadraticFunction{Float64}}, set::SCALAR_SET) +function MOI.add_constraint( + model::Optimizer, + f::Union{MOI.ScalarAffineFunction{Float64},MOI.ScalarQuadraticFunction{Float64}}, + set::SCALAR_SET, +) model.num_constr_orig += 1 - push!(model.constraint_bounds_orig, MOI.NLPBoundsPair(something(_lower(set), -Inf), something(_upper(set), Inf))) - iszero(f.constant) || throw(MOI.ScalarFunctionConstantNotZero{Float64, typeof(f), typeof(set)}(f.constant)) + push!( + model.constraint_bounds_orig, + MOI.NLPBoundsPair(something(_lower(set), -Inf), something(_upper(set), Inf)), + ) + iszero(f.constant) || throw( + MOI.ScalarFunctionConstantNotZero{Float64,typeof(f),typeof(set)}(f.constant), + ) push!(model.lin_quad_constraints, (copy(f), copy(set))) push!(model.constr_expr_orig, _constraint_expr(_moi_function_to_expr(f), set)) if f isa MOI.ScalarAffineFunction @@ -324,10 +371,13 @@ function MOI.add_constraint(model::Optimizer, f::Union{MOI.ScalarAffineFunction{ push!(model.constr_structure, :generic_nonlinear) end - return MOI.ConstraintIndex{typeof(f), typeof(set)}(model.num_constr_orig) + return MOI.ConstraintIndex{typeof(f),typeof(set)}(model.num_constr_orig) end -function MOI.supports(model::Optimizer, ::Union{MOI.ObjectiveSense, MOI.ObjectiveFunction{F}}) where F<:Union{MOI.ScalarAffineFunction{Float64}, MOI.ScalarQuadraticFunction{Float64}} +function MOI.supports( + model::Optimizer, + ::Union{MOI.ObjectiveSense,MOI.ObjectiveFunction{F}}, +) where {F<:Union{MOI.ScalarAffineFunction{Float64},MOI.ScalarQuadraticFunction{Float64}}} return true end @@ -347,13 +397,16 @@ function MOI.set(model::Optimizer, ::MOI.ObjectiveSense, sense) end end -function MOI.set(model::Optimizer, ::MOI.ObjectiveFunction{F}, func::F) where F - model.objective_function = func +function MOI.set(model::Optimizer, ::MOI.ObjectiveFunction{F}, func::F) where {F} + return model.objective_function = func end function MOI.set(m::Optimizer, ::MOI.NLPBlock, block) m.d_orig = block.evaluator - m.disable_hessian = !((:Hess in MOI.features_available(block.evaluator)) && (:HessVec in MOI.features_available(block.evaluator))) + m.disable_hessian = !( + (:Hess in MOI.features_available(block.evaluator)) && + (:HessVec in MOI.features_available(block.evaluator)) + ) m.has_nl_objective = block.has_objective # We cache it to add it in `load!` as we cannot call `MOI.constraint_expr` yet @@ -361,13 +414,13 @@ function MOI.set(m::Optimizer, ::MOI.NLPBlock, block) # to add the bounds at the end too. # So we can consider that the nonlinear constraints are the # `length(m.nl_constraint_bounds_orig)` last ones. - m.nl_constraint_bounds_orig = block.constraint_bounds + return m.nl_constraint_bounds_orig = block.constraint_bounds end # In JuMP v0.18/MathProgBase, the 5th decision variable would be `:(x[5])`. # In JuMP v0.19/MathOptInterface, it is now `:(x[MOI.VariableIndex(5)])`. # To ease the transition, we simply transform it back to what it used to be. -_variable_index_to_index(expr::Union{Number, Symbol}) = expr +_variable_index_to_index(expr::Union{Number,Symbol}) = expr _variable_index_to_index(expr::MOI.VariableIndex) = expr.value function _variable_index_to_index(expr::Expr) for i in eachindex(expr.args) @@ -376,31 +429,36 @@ function _variable_index_to_index(expr::Expr) return expr end -_index_to_variable_ref(m::JuMP.Model, idx::Int64) = JuMP.VariableRef(m, MOI.VariableIndex(idx)) +function _index_to_variable_ref(m::JuMP.Model, idx::Int64) + return JuMP.VariableRef(m, MOI.VariableIndex(idx)) +end function MOI.get(model::Optimizer, attr::MOI.VariablePrimal, vi::MOI.VariableIndex) - MOI.check_result_index_bounds(model, attr) MOI.throw_if_not_valid(model, vi) return model.best_sol[vi.value] end -MOI.get(model::Optimizer, ::MOI.ResultCount) = model.alpine_status == MOI.OPTIMIZE_NOT_CALLED ? 0 : 1 +function MOI.get(model::Optimizer, ::MOI.ResultCount) + return model.alpine_status == MOI.OPTIMIZE_NOT_CALLED ? 0 : 1 +end -MOI.is_valid(model::Alpine.Optimizer, vi::MOI.VariableIndex) = 1 <= vi.value <= model.num_var_orig +function MOI.is_valid(model::Alpine.Optimizer, vi::MOI.VariableIndex) + return 1 <= vi.value <= model.num_var_orig +end # Taken from MatrixOptInterface.jl @enum ConstraintSense EQUAL_TO GREATER_THAN LESS_THAN INTERVAL -_sense(::Type{<:MOI.EqualTo}) = EQUAL_TO -_sense(::Type{<:MOI.LessThan}) = LESS_THAN +_sense(::Type{<:MOI.EqualTo}) = EQUAL_TO +_sense(::Type{<:MOI.LessThan}) = LESS_THAN _sense(::Type{<:MOI.GreaterThan}) = GREATER_THAN -_sense(::Type{<:MOI.Interval}) = INTERVAL +_sense(::Type{<:MOI.Interval}) = INTERVAL _no_upper(bound) = bound != typemax(bound) _no_lower(bound) = bound != typemin(bound) -function _bound_set(lb::T, ub::T) where T +function _bound_set(lb::T, ub::T) where {T} if _no_upper(ub) if _no_lower(lb) if ub == lb diff --git a/src/algorithm.jl b/src/algorithm.jl index 3e6093bd..2403d727 100644 --- a/src/algorithm.jl +++ b/src/algorithm.jl @@ -1,158 +1,180 @@ const STATUS_LIMIT = [ - MOI.ITERATION_LIMIT, MOI.TIME_LIMIT, MOI.NODE_LIMIT, - MOI.SOLUTION_LIMIT, MOI.MEMORY_LIMIT, MOI.OBJECTIVE_LIMIT, - MOI.NORM_LIMIT, MOI.OTHER_LIMIT -] -const STATUS_OPT = [ - MOI.OPTIMAL, MOI.LOCALLY_SOLVED, MOI.ALMOST_OPTIMAL, MOI.ALMOST_LOCALLY_SOLVED -] -const STATUS_INF = [ - MOI.INFEASIBLE, MOI.LOCALLY_INFEASIBLE + MOI.ITERATION_LIMIT, + MOI.TIME_LIMIT, + MOI.NODE_LIMIT, + MOI.SOLUTION_LIMIT, + MOI.MEMORY_LIMIT, + MOI.OBJECTIVE_LIMIT, + MOI.NORM_LIMIT, + MOI.OTHER_LIMIT, ] +const STATUS_OPT = + [MOI.OPTIMAL, MOI.LOCALLY_SOLVED, MOI.ALMOST_OPTIMAL, MOI.ALMOST_LOCALLY_SOLVED] +const STATUS_INF = [MOI.INFEASIBLE, MOI.LOCALLY_INFEASIBLE] function features_available(m::Optimizer) - features = [:Grad, :Jac, :JacVec, :ExprGraph] - if !m.disable_hessian - push!(features, :Hess) - push!(features, :HessVec) - end + features = [:Grad, :Jac, :JacVec, :ExprGraph] + if !m.disable_hessian + push!(features, :Hess) + push!(features, :HessVec) + end - return features + return features end function load!(m::Optimizer) - # Initialize NLP interface - requested_features = Alp.features_available(m) - if m.d_orig !== nothing - MOI.initialize(m.d_orig, requested_features::Vector{Symbol}) - end - for feat in requested_features - if !(feat in Alp.features_available(m)) - error("Unsupported feature $feat") - end - end - - # Collect objective & constraint expressions - if m.has_nl_objective - m.obj_expr_orig = Alp.expr_isolate_const(_variable_index_to_index(MOI.objective_expr(m.d_orig))) # see in nlexpr.jl if this expr isolation has any issue - elseif m.objective_function isa Nothing - m.obj_expr_orig = Expr(:call, :+) - else - m.obj_expr_orig = _moi_function_to_expr(m.objective_function) - end - - # Collect original variable type and build dynamic variable type space - m.var_type = copy(m.var_type_orig) - m.int_vars = [i for i in 1:m.num_var_orig if m.var_type[i] == :Int] - m.bin_vars = [i for i in 1:m.num_var_orig if m.var_type[i] == :Bin] - - if !isempty(m.int_vars) || !isempty(m.bin_vars) - (Alp.get_option(m, :minlp_solver) === nothing) && (error("No MINLP local solver specified; use option 'minlp_solver' to specify a MINLP local solver")) - end - - m.num_constr_orig += length(m.nl_constraint_bounds_orig) - m.num_nlconstr_orig += length(m.nl_constraint_bounds_orig) - append!(m.constraint_bounds_orig, m.nl_constraint_bounds_orig) - for i in eachindex(m.nl_constraint_bounds_orig) - push!(m.constr_expr_orig, _variable_index_to_index(MOI.constraint_expr(m.d_orig, i))) - push!(m.constr_structure, :generic_nonlinear) - end - - # Summarize constraints information in original model - m.constr_type_orig = Array{Symbol}(undef, m.num_constr_orig) - - for i in 1:m.num_constr_orig - if m.constraint_bounds_orig[i].lower > -Inf && m.constraint_bounds_orig[i].upper < Inf - m.constr_type_orig[i] = :(==) - elseif m.constraint_bounds_orig[i].lower > -Inf - m.constr_type_orig[i] = :(>=) - else - m.constr_type_orig[i] = :(<=) - end - end - - # Initialize recognizable structure properties with :none - m.obj_structure = :none - - @assert m.num_constr_orig == m.num_nlconstr_orig + m.num_lconstr_orig - m.is_obj_linear_orig = !m.has_nl_objective && m.objective_function isa MOI.ScalarAffineFunction{Float64} - m.is_obj_linear_orig ? (m.obj_structure = :generic_linear) : (m.obj_structure = :generic_nonlinear) - isa(m.obj_expr_orig, Number) && (m.obj_structure = :constant) - - # populate data to create the bounding model - Alp.recategorize_var(m) # Initial round of variable re-categorization - - :Int in m.var_type_orig && error("Alpine does not support MINLPs with generic integer (non-binary) variables yet! Try Juniper.jl for finding a local feasible solution") - :Int in m.var_type_orig ? Alp.set_option(m, :int_enable, true) : Alp.set_option(m, :int_enable, false) # Separator for safer runs - - # Conduct solver-dependent detection - Alp.fetch_mip_solver_identifier(m) - (Alp.get_option(m, :nlp_solver) !== nothing) && (Alp.fetch_nlp_solver_identifier(m)) - (Alp.get_option(m, :minlp_solver) !== nothing) && (Alp.fetch_minlp_solver_identifier(m)) - - # Solver Dependent Options - if m.mip_solver_id != :Gurobi - Alp.get_option(m, :convhull_warmstart) == false - Alp.get_option(m, :convhull_no_good_cuts) == false - end - - # Main Algorithmic Initialization - Alp.process_expr(m) # Compact process of every expression - Alp.init_tight_bound(m) # Initialize bounds for algorithmic processes - Alp.resolve_var_bounds(m) # resolve lifted var bounds - Alp.pick_disc_vars(m) # Picking variables to be discretized - Alp.init_disc(m) # Initialize discretization dictionaries - - # Turn-on bt presolve if variables are not discrete - if isempty(m.int_vars) && length(m.bin_vars) <= 50 && m.num_var_orig <= 10000 && length(m.candidate_disc_vars)<=300 && Alp.get_option(m, :presolve_bt) == nothing - Alp.set_option(m, :presolve_bt, true) - println("Automatically turning on bound-tightening presolve") - elseif Alp.get_option(m, :presolve_bt) == nothing # If no use indication - Alp.set_option(m, :presolve_bt, false) - end - - if length(m.bin_vars) > 200 || m.num_var_orig > 2000 - println("Automatically turning OFF 'disc_ratio_branch' due to the size of the problem") - Alp.set_option(m, :disc_ratio_branch, false) - end - - # Initialize the solution pool - m.bound_sol_pool = Alp.initialize_solution_pool(m, 0) # Initialize the solution pool - - # Check if any illegal term exist in the warm-solution - any(isnan, m.best_sol) && (m.best_sol = zeros(length(m.best_sol))) - - # Initialize log - Alp.logging_summary(m) - - return -end + # Initialize NLP interface + requested_features = Alp.features_available(m) + if m.d_orig !== nothing + MOI.initialize(m.d_orig, requested_features::Vector{Symbol}) + end + for feat in requested_features + if !(feat in Alp.features_available(m)) + error("Unsupported feature $feat") + end + end + + # Collect objective & constraint expressions + if m.has_nl_objective + m.obj_expr_orig = + Alp.expr_isolate_const(_variable_index_to_index(MOI.objective_expr(m.d_orig))) # see in nlexpr.jl if this expr isolation has any issue + elseif m.objective_function isa Nothing + m.obj_expr_orig = Expr(:call, :+) + else + m.obj_expr_orig = _moi_function_to_expr(m.objective_function) + end + + # Collect original variable type and build dynamic variable type space + m.var_type = copy(m.var_type_orig) + m.int_vars = [i for i in 1:m.num_var_orig if m.var_type[i] == :Int] + m.bin_vars = [i for i in 1:m.num_var_orig if m.var_type[i] == :Bin] + + if !isempty(m.int_vars) || !isempty(m.bin_vars) + (Alp.get_option(m, :minlp_solver) === nothing) && (error( + "No MINLP local solver specified; use option 'minlp_solver' to specify a MINLP local solver", + )) + end + + m.num_constr_orig += length(m.nl_constraint_bounds_orig) + m.num_nlconstr_orig += length(m.nl_constraint_bounds_orig) + append!(m.constraint_bounds_orig, m.nl_constraint_bounds_orig) + for i in eachindex(m.nl_constraint_bounds_orig) + push!( + m.constr_expr_orig, + _variable_index_to_index(MOI.constraint_expr(m.d_orig, i)), + ) + push!(m.constr_structure, :generic_nonlinear) + end + + # Summarize constraints information in original model + m.constr_type_orig = Array{Symbol}(undef, m.num_constr_orig) + + for i in 1:m.num_constr_orig + if m.constraint_bounds_orig[i].lower > -Inf && + m.constraint_bounds_orig[i].upper < Inf + m.constr_type_orig[i] = :(==) + elseif m.constraint_bounds_orig[i].lower > -Inf + m.constr_type_orig[i] = :(>=) + else + m.constr_type_orig[i] = :(<=) + end + end + + # Initialize recognizable structure properties with :none + m.obj_structure = :none + + @assert m.num_constr_orig == m.num_nlconstr_orig + m.num_lconstr_orig + m.is_obj_linear_orig = + !m.has_nl_objective && m.objective_function isa MOI.ScalarAffineFunction{Float64} + m.is_obj_linear_orig ? (m.obj_structure = :generic_linear) : + (m.obj_structure = :generic_nonlinear) + isa(m.obj_expr_orig, Number) && (m.obj_structure = :constant) + + # populate data to create the bounding model + Alp.recategorize_var(m) # Initial round of variable re-categorization + + :Int in m.var_type_orig && error( + "Alpine does not support MINLPs with generic integer (non-binary) variables yet! Try Juniper.jl for finding a local feasible solution", + ) + :Int in m.var_type_orig ? Alp.set_option(m, :int_enable, true) : + Alp.set_option(m, :int_enable, false) # Separator for safer runs + + # Conduct solver-dependent detection + Alp.fetch_mip_solver_identifier(m) + (Alp.get_option(m, :nlp_solver) !== nothing) && (Alp.fetch_nlp_solver_identifier(m)) + (Alp.get_option(m, :minlp_solver) !== nothing) && + (Alp.fetch_minlp_solver_identifier(m)) + + # Solver Dependent Options + if m.mip_solver_id != :Gurobi + Alp.get_option(m, :convhull_warmstart) == false + Alp.get_option(m, :convhull_no_good_cuts) == false + end + + # Main Algorithmic Initialization + Alp.process_expr(m) # Compact process of every expression + Alp.init_tight_bound(m) # Initialize bounds for algorithmic processes + Alp.resolve_var_bounds(m) # resolve lifted var bounds + Alp.pick_disc_vars(m) # Picking variables to be discretized + Alp.init_disc(m) # Initialize discretization dictionaries + + # Turn-on bt presolve if variables are not discrete + if isempty(m.int_vars) && + length(m.bin_vars) <= 50 && + m.num_var_orig <= 10000 && + length(m.candidate_disc_vars) <= 300 && + Alp.get_option(m, :presolve_bt) == nothing + Alp.set_option(m, :presolve_bt, true) + println("Automatically turning on bound-tightening presolve") + elseif Alp.get_option(m, :presolve_bt) == nothing # If no use indication + Alp.set_option(m, :presolve_bt, false) + end + if length(m.bin_vars) > 200 || m.num_var_orig > 2000 + println( + "Automatically turning OFF 'disc_ratio_branch' due to the size of the problem", + ) + Alp.set_option(m, :disc_ratio_branch, false) + end + + # Initialize the solution pool + m.bound_sol_pool = Alp.initialize_solution_pool(m, 0) # Initialize the solution pool + + # Check if any illegal term exist in the warm-solution + any(isnan, m.best_sol) && (m.best_sol = zeros(length(m.best_sol))) + + # Initialize log + Alp.logging_summary(m) + + return +end """ High-level Function """ function MOI.optimize!(m::Optimizer) - Alp.load!(m) - if getproperty(m, :presolve_infeasible) - Alp.summary_status(m) - return - end + Alp.load!(m) + if getproperty(m, :presolve_infeasible) + Alp.summary_status(m) + return + end - Alp.presolve(m) + Alp.presolve(m) - if !Alp.check_exit(m) && Alp.get_option(m, :apply_partitioning) - Alp.global_solve(m) - Alp.get_option(m, :log_level) > 0 && Alp.logging_row_entry(m, finish_entry=true) - println("====================================================================================================") - else - println(" Presolve terminated with a global optimal solution") - end + if !Alp.check_exit(m) && Alp.get_option(m, :apply_partitioning) + Alp.global_solve(m) + Alp.get_option(m, :log_level) > 0 && Alp.logging_row_entry(m, finish_entry = true) + println( + "====================================================================================================", + ) + else + println(" Presolve terminated with a global optimal solution") + end - Alp.summary_status(m) + Alp.summary_status(m) - return + return end """ @@ -165,87 +187,88 @@ Each [`local_solve`](@ref) provides an incumbent feasible solution. The algorith """ function global_solve(m::Optimizer) + Alp.get_option(m, :log_level) > 0 && Alp.logging_head(m) + Alp.get_option(m, :presolve_track_time) || Alp.reset_timer(m) + while !Alp.check_exit(m) + m.logs[:n_iter] += 1 + Alp.create_bounding_mip(m) # Build the relaxation model + Alp.bounding_solve(m) # Solve the relaxation model + Alp.update_opt_gap(m) # Update optimality gap + Alp.check_exit(m) && break # Feasibility check + Alp.get_option(m, :log_level) > 0 && Alp.logging_row_entry(m) # Logging + Alp.local_solve(m) # Solve local model for feasible solution + Alp.update_opt_gap(m) # Update optimality gap + Alp.check_exit(m) && break # Detect optimality termination + Alp.algorithm_automation(m) # Automated adjustments + Alp.add_partition(m) # Add extra discretizations + end - Alp.get_option(m, :log_level) > 0 && Alp.logging_head(m) - Alp.get_option(m, :presolve_track_time) || Alp.reset_timer(m) - while !Alp.check_exit(m) - m.logs[:n_iter] += 1 - Alp.create_bounding_mip(m) # Build the relaxation model - Alp.bounding_solve(m) # Solve the relaxation model - Alp.update_opt_gap(m) # Update optimality gap - Alp.check_exit(m) && break # Feasibility check - Alp.get_option(m, :log_level) > 0 && Alp.logging_row_entry(m) # Logging - Alp.local_solve(m) # Solve local model for feasible solution - Alp.update_opt_gap(m) # Update optimality gap - Alp.check_exit(m) && break # Detect optimality termination - Alp.algorithm_automation(m) # Automated adjustments - Alp.add_partition(m) # Add extra discretizations - end - - return + return end """ presolve(m::Optimizer) """ function presolve(m::Optimizer) - start_presolve = time() - Alp.get_option(m, :log_level) > 0 && printstyled("PRESOLVE \n", color=:cyan) - Alp.get_option(m, :log_level) > 0 && println(" Doing local search") - Alp.local_solve(m, presolve = true) - - # Solver status - if m.status[:local_solve] in STATUS_OPT || m.status[:local_solve] in STATUS_LIMIT - - Alp.get_option(m, :log_level) > 0 && println(" Local solver returns a feasible point with value $(round(m.best_obj, digits=4))") - Alp.bound_tightening(m, use_bound = true) # performs bound-tightening with the local solve objective value - Alp.get_option(m, :presolve_bt) && init_disc(m) # Re-initialize discretization dictionary on tight bounds - Alp.get_option(m, :disc_ratio_branch) && (Alp.set_option(m, :disc_ratio, Alp.update_disc_ratio(m, true))) - Alp.add_partition(m, use_solution=m.best_sol) # Setting up the initial discretization - - elseif m.status[:local_solve] in STATUS_INF - - (Alp.get_option(m, :log_level) > 0) && println(" Bound tightening without objective bounds (OBBT)") - Alp.bound_tightening(m, use_bound = false) # do bound tightening without objective value - (Alp.get_option(m, :disc_ratio_branch)) && (Alp.set_option(m, :disc_ratio, Alp.update_disc_ratio(m, true))) - Alp.get_option(m, :presolve_bt) && Alp.init_disc(m) - - elseif m.status[:local_solve] == MOI.INVALID_MODEL - - @warn " Warning: Presolve ends with local solver yielding $(m.status[:local_solve]). \n This may come from Ipopt's `:Not_Enough_Degrees_Of_Freedom`. \n Consider more replace equality constraints with >= and <= to resolve this." - - else - - @warn " Warning: Presolve ends with local solver yielding $(m.status[:local_solve])." - - end + start_presolve = time() + Alp.get_option(m, :log_level) > 0 && printstyled("PRESOLVE \n", color = :cyan) + Alp.get_option(m, :log_level) > 0 && println(" Doing local search") + Alp.local_solve(m, presolve = true) + + # Solver status + if m.status[:local_solve] in STATUS_OPT || m.status[:local_solve] in STATUS_LIMIT + Alp.get_option(m, :log_level) > 0 && println( + " Local solver returns a feasible point with value $(round(m.best_obj, digits=4))", + ) + Alp.bound_tightening(m, use_bound = true) # performs bound-tightening with the local solve objective value + Alp.get_option(m, :presolve_bt) && init_disc(m) # Re-initialize discretization dictionary on tight bounds + Alp.get_option(m, :disc_ratio_branch) && + (Alp.set_option(m, :disc_ratio, Alp.update_disc_ratio(m, true))) + Alp.add_partition(m, use_solution = m.best_sol) # Setting up the initial discretization + + elseif m.status[:local_solve] in STATUS_INF + (Alp.get_option(m, :log_level) > 0) && + println(" Bound tightening without objective bounds (OBBT)") + Alp.bound_tightening(m, use_bound = false) # do bound tightening without objective value + (Alp.get_option(m, :disc_ratio_branch)) && + (Alp.set_option(m, :disc_ratio, Alp.update_disc_ratio(m, true))) + Alp.get_option(m, :presolve_bt) && Alp.init_disc(m) + + elseif m.status[:local_solve] == MOI.INVALID_MODEL + @warn " Warning: Presolve ends with local solver yielding $(m.status[:local_solve]). \n This may come from Ipopt's `:Not_Enough_Degrees_Of_Freedom`. \n Consider more replace equality constraints with >= and <= to resolve this." + + else + @warn " Warning: Presolve ends with local solver yielding $(m.status[:local_solve])." + end - cputime_presolve = time() - start_presolve - m.logs[:presolve_time] += cputime_presolve - m.logs[:total_time] = m.logs[:presolve_time] - m.logs[:time_left] -= m.logs[:presolve_time] + cputime_presolve = time() - start_presolve + m.logs[:presolve_time] += cputime_presolve + m.logs[:total_time] = m.logs[:presolve_time] + m.logs[:time_left] -= m.logs[:presolve_time] - if Alp.get_option(m, :presolve_bt) - (Alp.get_option(m, :log_level) > 0) && println(" Post-presolve optimality gap: $(round(m.presolve_best_rel_gap; digits = 3))%") - end - (Alp.get_option(m, :log_level) > 0) && println(" Completed presolve in $(round.(m.logs[:total_time]; digits = 2))s") + if Alp.get_option(m, :presolve_bt) + (Alp.get_option(m, :log_level) > 0) && println( + " Post-presolve optimality gap: $(round(m.presolve_best_rel_gap; digits = 3))%", + ) + end + (Alp.get_option(m, :log_level) > 0) && + println(" Completed presolve in $(round.(m.logs[:total_time]; digits = 2))s") - return + return end """ A wrapper function that collects some automated solver adjustments within the main while loop. """ function algorithm_automation(m::Optimizer) + Alp.get_option(m, :disc_var_pick) == 3 && Alp.update_disc_cont_var(m) + Alp.get_option(m, :int_cumulative_disc) && Alp.update_disc_int_var(m) - Alp.get_option(m, :disc_var_pick) == 3 && Alp.update_disc_cont_var(m) - Alp.get_option(m, :int_cumulative_disc) && Alp.update_disc_int_var(m) - - if Alp.get_option(m, :disc_ratio_branch) - Alp.set_option(m, :disc_ratio, Alp.update_disc_ratio(m, true)) # Only perform for a maximum three times - end + if Alp.get_option(m, :disc_ratio_branch) + Alp.set_option(m, :disc_ratio, Alp.update_disc_ratio(m, true)) # Only perform for a maximum three times + end - return + return end """ @@ -253,36 +276,37 @@ end """ function check_exit(m::Optimizer) - # constant objective with feasible local solve check - if Alp.expr_isconst(m.obj_expr_orig) && (m.status[:local_solve] == MOI.OPTIMAL || m.status == MOI.LOCALLY_SOLVED) - # m.best_bound = eval(m.obj_expr_orig) - m.best_bound = m.obj_expr_orig - m.best_rel_gap = 0.0 - m.best_abs_gap = 0.0 - m.status[:bounding_solve] = MOI.OPTIMAL - m.alpine_status = :Optimal - m.detected_bound = true - return true - end - - # Infeasibility check - m.status[:bounding_solve] == MOI.INFEASIBLE && return true - - # Unbounded check - m.status[:bounding_solve] == MOI.DUAL_INFEASIBLE && return true - - # Optimality check - if m.best_rel_gap <= Alp.get_option(m, :rel_gap) - m.detected_bound = true - return true - end - m.logs[:n_iter] >= Alp.get_option(m, :max_iter) && return true - m.best_abs_gap <= Alp.get_option(m, :abs_gap) && return true - - # User-limits check - m.logs[:time_left] < Alp.get_option(m, :tol) && return true - - return false + # constant objective with feasible local solve check + if Alp.expr_isconst(m.obj_expr_orig) && + (m.status[:local_solve] == MOI.OPTIMAL || m.status == MOI.LOCALLY_SOLVED) + # m.best_bound = eval(m.obj_expr_orig) + m.best_bound = m.obj_expr_orig + m.best_rel_gap = 0.0 + m.best_abs_gap = 0.0 + m.status[:bounding_solve] = MOI.OPTIMAL + m.alpine_status = :Optimal + m.detected_bound = true + return true + end + + # Infeasibility check + m.status[:bounding_solve] == MOI.INFEASIBLE && return true + + # Unbounded check + m.status[:bounding_solve] == MOI.DUAL_INFEASIBLE && return true + + # Optimality check + if m.best_rel_gap <= Alp.get_option(m, :rel_gap) + m.detected_bound = true + return true + end + m.logs[:n_iter] >= Alp.get_option(m, :max_iter) && return true + m.best_abs_gap <= Alp.get_option(m, :abs_gap) && return true + + # User-limits check + m.logs[:time_left] < Alp.get_option(m, :tol) && return true + + return false end function load_nonlinear_model(m::Optimizer, model::MOI.ModelLike, l_var, u_var) @@ -298,7 +322,11 @@ function load_nonlinear_model(m::Optimizer, model::MOI.ModelLike, l_var, u_var) end MOI.set(model, MOI.ObjectiveSense(), m.sense_orig) if m.objective_function !== nothing - MOI.set(model, MOI.ObjectiveFunction{typeof(m.objective_function)}(), m.objective_function) + MOI.set( + model, + MOI.ObjectiveFunction{typeof(m.objective_function)}(), + m.objective_function, + ) end block = MOI.NLPBlockData(m.nl_constraint_bounds_orig, m.d_orig, m.has_nl_objective) MOI.set(model, MOI.NLPBlock(), block) @@ -327,188 +355,201 @@ Otherwise, the function is invoked from [`bounding_solve`](@ref). """ function local_solve(m::Optimizer; presolve = false) + convertor = Dict(MOI.MAX_SENSE => :>, MOI.MIN_SENSE => :<) + local_nlp_status = :Unknown + + var_type_screener = [i for i in m.var_type_orig if i in [:Bin, :Int]] + + if presolve + if !isempty(var_type_screener) && Alp.get_option(m, :minlp_solver) !== nothing + local_solve_model = MOI.instantiate( + Alp.get_option(m, :minlp_solver), + with_bridge_type = Float64, + ) + elseif !isempty(var_type_screener) + local_solve_model = MOI.instantiate( + Alp.get_option(m, :nlp_solver), + with_bridge_type = Float64, + ) + else + local_solve_model = MOI.instantiate( + Alp.get_option(m, :nlp_solver), + with_bridge_type = Float64, + ) + end + else + local_solve_model = + MOI.instantiate(Alp.get_option(m, :nlp_solver), with_bridge_type = Float64) + end - convertor = Dict(MOI.MAX_SENSE => :>, MOI.MIN_SENSE => :<) - local_nlp_status = :Unknown - - var_type_screener = [i for i in m.var_type_orig if i in [:Bin, :Int]] - - if presolve - if !isempty(var_type_screener) && Alp.get_option(m, :minlp_solver) !== nothing - local_solve_model = MOI.instantiate(Alp.get_option(m, :minlp_solver), with_bridge_type=Float64) - elseif !isempty(var_type_screener) - local_solve_model = MOI.instantiate(Alp.get_option(m, :nlp_solver), with_bridge_type=Float64) - else - local_solve_model = MOI.instantiate(Alp.get_option(m, :nlp_solver), with_bridge_type=Float64) - end - else - local_solve_model = MOI.instantiate(Alp.get_option(m, :nlp_solver), with_bridge_type=Float64) - end - - if presolve == false - l_var, u_var = Alp.fix_domains(m) - else - l_var, u_var = m.l_var_tight[1:m.num_var_orig], m.u_var_tight[1:m.num_var_orig] - end - - x = Alp.load_nonlinear_model(m, local_solve_model, l_var, u_var) - if m.d_orig !== nothing - MOI.initialize(m.d_orig, [:Grad, :Jac, :Hess, :HessVec, :ExprGraph]) # Safety scheme for sub-solvers re-initializing the NLPEvaluator - end - - if !presolve - warmval = m.best_sol[1:m.num_var_orig] - else - warmval = m.initial_warmval[1:m.num_var_orig] - end - MOI.set(local_solve_model, MOI.VariablePrimalStart(), x, warmval) - - # do_heuristic = false - - # The only case when MINLP solver is actually used - if presolve && !isempty(var_type_screener) - if Alp.get_option(m, :minlp_solver) === nothing - error("Provide a valid MINLP solver") - # do_heuristic = true - else - Alp.set_variable_type(local_solve_model, x, m.var_type_orig) - end - end - - start_local_solve = time() - MOI.optimize!(local_solve_model) - local_nlp_status = MOI.get(local_solve_model, MOI.TerminationStatus()) - - # if !do_heuristic - # local_nlp_status = MOI.get(local_solve_model, MOI.TerminationStatus()) - # end - - cputime_local_solve = time() - start_local_solve - m.logs[:total_time] += cputime_local_solve - m.logs[:time_left] = max(0.0, Alp.get_option(m, :time_limit) - m.logs[:total_time]) - - # if do_heuristic - # m.status[:local_solve] = heu_basic_rounding(m, MOI.get(local_solve_model, MOI.VariablePrimal(), x)) - # return - - if local_nlp_status in STATUS_OPT || local_nlp_status in STATUS_LIMIT - candidate_obj = MOI.get(local_solve_model, MOI.ObjectiveValue()) - sol_temp = MOI.get(local_solve_model, MOI.VariablePrimal(), x) - candidate_sol = Vector{Float64}() - - feas_tol = 1E-5 - - for i = 1:length(sol_temp) - if (sol_temp[i] >= m.l_var_orig[i] - feas_tol) && (sol_temp[i] <= m.l_var_orig[i] + feas_tol) - push!(candidate_sol, m.l_var_orig[i]) - elseif (sol_temp[i] >= m.u_var_orig[i] - feas_tol) && (sol_temp[i] <= m.u_var_orig[i] + feas_tol) - push!(candidate_sol, m.u_var_orig[i]) - else - push!(candidate_sol, round(sol_temp[i], digits = 7)) - end - end - - @assert length(candidate_sol) == length(sol_temp) - Alp.update_incumb_objective(m, candidate_obj, candidate_sol) - m.status[:local_solve] = local_nlp_status - return - - elseif local_nlp_status in STATUS_INF - Alp.heu_pool_multistart(m) == MOI.LOCALLY_SOLVED && return - push!(m.logs[:obj], "INF") - m.status[:local_solve] = MOI.LOCALLY_INFEASIBLE - return - - elseif local_nlp_status == MOI.DUAL_INFEASIBLE - push!(m.logs[:obj], "U") - m.status[:local_solve] = MOI.DUAL_INFEASIBLE - if presolve - @warn " Warning: NLP local solve is unbounded." - else - @warn " Warning: NLP local solve is unbounded." - end - return - - else - push!(m.logs[:obj], "E") - m.status[:local_solve] = MOI.OTHER_ERROR - if presolve - @warn " Warning: NLP solve failure $(local_nlp_status)." - else - @warn " Warning: NLP local solve failure." - end - return - end - - return -end - - -""" - Alp.bounding_solve(m::Optimizer; kwargs...) + if presolve == false + l_var, u_var = Alp.fix_domains(m) + else + l_var, u_var = m.l_var_tight[1:m.num_var_orig], m.u_var_tight[1:m.num_var_orig] + end -This step usually solves a convex MILP/MIQCP/MIQCQP problem for lower bounding the given minimization problem. -It solves the problem built upon a piecewise convexification based on the discretization sictionary of some variables. -See `create_bounding_mip` for more details of the problem solved here. -""" -function bounding_solve(m::Optimizer) + x = Alp.load_nonlinear_model(m, local_solve_model, l_var, u_var) + if m.d_orig !== nothing + MOI.initialize(m.d_orig, [:Grad, :Jac, :Hess, :HessVec, :ExprGraph]) # Safety scheme for sub-solvers re-initializing the NLPEvaluator + end - convertor = Dict(MOI.MAX_SENSE => :<, MOI.MIN_SENSE => :>) + if !presolve + warmval = m.best_sol[1:m.num_var_orig] + else + warmval = m.initial_warmval[1:m.num_var_orig] + end + MOI.set(local_solve_model, MOI.VariablePrimalStart(), x, warmval) - # Updates time metric and the termination bounds - Alp.set_mip_time_limit(m) - # update_boundstop_options(m) + # do_heuristic = false - # ================= Solve Start ================ # - start_bounding_solve = time() - JuMP.optimize!(m.model_mip) - status = JuMP.termination_status(m.model_mip) - m.logs[:total_time] += time() - start_bounding_solve - m.logs[:time_left] = max(0.0, Alp.get_option(m, :time_limit) - m.logs[:total_time]) - # ================= Solve End ================ # + # The only case when MINLP solver is actually used + if presolve && !isempty(var_type_screener) + if Alp.get_option(m, :minlp_solver) === nothing + error("Provide a valid MINLP solver") + # do_heuristic = true + else + Alp.set_variable_type(local_solve_model, x, m.var_type_orig) + end + end - if status in STATUS_OPT || status in STATUS_LIMIT + start_local_solve = time() + MOI.optimize!(local_solve_model) + local_nlp_status = MOI.get(local_solve_model, MOI.TerminationStatus()) + + # if !do_heuristic + # local_nlp_status = MOI.get(local_solve_model, MOI.TerminationStatus()) + # end + + cputime_local_solve = time() - start_local_solve + m.logs[:total_time] += cputime_local_solve + m.logs[:time_left] = max(0.0, Alp.get_option(m, :time_limit) - m.logs[:total_time]) + + # if do_heuristic + # m.status[:local_solve] = heu_basic_rounding(m, MOI.get(local_solve_model, MOI.VariablePrimal(), x)) + # return + + if local_nlp_status in STATUS_OPT || local_nlp_status in STATUS_LIMIT + candidate_obj = MOI.get(local_solve_model, MOI.ObjectiveValue()) + sol_temp = MOI.get(local_solve_model, MOI.VariablePrimal(), x) + candidate_sol = Vector{Float64}() + + feas_tol = 1E-5 + + for i in 1:length(sol_temp) + if (sol_temp[i] >= m.l_var_orig[i] - feas_tol) && + (sol_temp[i] <= m.l_var_orig[i] + feas_tol) + push!(candidate_sol, m.l_var_orig[i]) + elseif (sol_temp[i] >= m.u_var_orig[i] - feas_tol) && + (sol_temp[i] <= m.u_var_orig[i] + feas_tol) + push!(candidate_sol, m.u_var_orig[i]) + else + push!(candidate_sol, round(sol_temp[i], digits = 7)) + end + end - candidate_bound = (status == MOI.OPTIMAL) ? JuMP.objective_value(m.model_mip) : JuMP.objective_bound(m.model_mip) - candidate_bound_sol = [round.(JuMP.value(_index_to_variable_ref(m.model_mip, i)); digits = 7) - for i in 1:(m.num_var_orig + m.num_var_linear_mip + m.num_var_nonlinear_mip)] + @assert length(candidate_sol) == length(sol_temp) + Alp.update_incumb_objective(m, candidate_obj, candidate_sol) + m.status[:local_solve] = local_nlp_status + return + + elseif local_nlp_status in STATUS_INF + Alp.heu_pool_multistart(m) == MOI.LOCALLY_SOLVED && return + push!(m.logs[:obj], "INF") + m.status[:local_solve] = MOI.LOCALLY_INFEASIBLE + return + + elseif local_nlp_status == MOI.DUAL_INFEASIBLE + push!(m.logs[:obj], "U") + m.status[:local_solve] = MOI.DUAL_INFEASIBLE + if presolve + @warn " Warning: NLP local solve is unbounded." + else + @warn " Warning: NLP local solve is unbounded." + end + return - # Experimental code - Alp.measure_relaxed_deviation(m, sol=candidate_bound_sol) - if Alp.get_option(m, :disc_consecutive_forbid) > 0 - m.bound_sol_history[mod(m.logs[:n_iter]-1, Alp.get_option(m, :disc_consecutive_forbid))+1] = copy(candidate_bound_sol) # Requires proper offseting - end - push!(m.logs[:bound], candidate_bound) - if eval(convertor[m.sense_orig])(candidate_bound, m.best_bound) - m.best_bound = candidate_bound - m.best_bound_sol = copy(candidate_bound_sol) - m.status[:bounding_solve] = status - m.detected_bound = true - end + else + push!(m.logs[:obj], "E") + m.status[:local_solve] = MOI.OTHER_ERROR + if presolve + @warn " Warning: NLP solve failure $(local_nlp_status)." + else + @warn " Warning: NLP local solve failure." + end + return + end - # collect_lb_pool(m) # Collect a pool of sub-optimal solutions - currently implemented for Gurobi only + return +end - elseif status in STATUS_INF || status == MOI.INFEASIBLE_OR_UNBOUNDED +""" + Alp.bounding_solve(m::Optimizer; kwargs...) - push!(m.logs[:bound], "-") - m.status[:bounding_solve] = MOI.INFEASIBLE - @warn " Warning: Infeasibility detected in the MIP solver" +This step usually solves a convex MILP/MIQCP/MIQCQP problem for lower bounding the given minimization problem. +It solves the problem built upon a piecewise convexification based on the discretization sictionary of some variables. +See `create_bounding_mip` for more details of the problem solved here. +""" +function bounding_solve(m::Optimizer) + convertor = Dict(MOI.MAX_SENSE => :<, MOI.MIN_SENSE => :>) + + # Updates time metric and the termination bounds + Alp.set_mip_time_limit(m) + # update_boundstop_options(m) + + # ================= Solve Start ================ # + start_bounding_solve = time() + JuMP.optimize!(m.model_mip) + status = JuMP.termination_status(m.model_mip) + m.logs[:total_time] += time() - start_bounding_solve + m.logs[:time_left] = max(0.0, Alp.get_option(m, :time_limit) - m.logs[:total_time]) + # ================= Solve End ================ # + + if status in STATUS_OPT || status in STATUS_LIMIT + candidate_bound = + (status == MOI.OPTIMAL) ? JuMP.objective_value(m.model_mip) : + JuMP.objective_bound(m.model_mip) + candidate_bound_sol = [ + round.(JuMP.value(_index_to_variable_ref(m.model_mip, i)); digits = 7) + for + i in 1:(m.num_var_orig+m.num_var_linear_mip+m.num_var_nonlinear_mip) + ] + + # Experimental code + Alp.measure_relaxed_deviation(m, sol = candidate_bound_sol) + if Alp.get_option(m, :disc_consecutive_forbid) > 0 + m.bound_sol_history[mod( + m.logs[:n_iter] - 1, + Alp.get_option(m, :disc_consecutive_forbid), + )+1] = copy(candidate_bound_sol) # Requires proper offseting + end + push!(m.logs[:bound], candidate_bound) + if eval(convertor[m.sense_orig])(candidate_bound, m.best_bound) + m.best_bound = candidate_bound + m.best_bound_sol = copy(candidate_bound_sol) + m.status[:bounding_solve] = status + m.detected_bound = true + end - if ALPINE_DEBUG - @warn "Use Alpine.print_iis_gurobi(m.model_mip) function in src/utility.jl (commented out code) for further investigation, if your MIP solver is Gurobi" - end + # collect_lb_pool(m) # Collect a pool of sub-optimal solutions - currently implemented for Gurobi only - elseif status == :Unbounded + elseif status in STATUS_INF || status == MOI.INFEASIBLE_OR_UNBOUNDED + push!(m.logs[:bound], "-") + m.status[:bounding_solve] = MOI.INFEASIBLE + @warn " Warning: Infeasibility detected in the MIP solver" - m.status[:bounding_solve] = MOI.DUAL_INFEASIBLE - @warn " Warning: MIP solver returns unbounded" + if ALPINE_DEBUG + @warn "Use Alpine.print_iis_gurobi(m.model_mip) function in src/utility.jl (commented out code) for further investigation, if your MIP solver is Gurobi" + end - else + elseif status == :Unbounded + m.status[:bounding_solve] = MOI.DUAL_INFEASIBLE + @warn " Warning: MIP solver returns unbounded" - error(" Warning: MIP solver failure $(status)") - end + else + error(" Warning: MIP solver failure $(status)") + end - return + return end """ @@ -525,28 +566,37 @@ For advanced usage, `Alp.get_option(m, :disc_var_pick)` allows `::Function` inpu """ function pick_disc_vars(m::Optimizer) + disc_var_pick = Alp.get_option(m, :disc_var_pick) + + if isa(disc_var_pick, Function) + # eval(Alp.get_option(m, :disc_var_pick))(m) + disc_var_pick(m) + length(m.disc_vars) == 0 && + length(m.nonconvex_terms) > 0 && + error( + "[USER FUNCTION] must select at least one variable to perform discretization for convexificiation purpose", + ) + elseif isa(disc_var_pick, Int) + if disc_var_pick == 0 + Alp.get_candidate_disc_vars(m) + elseif disc_var_pick == 1 + Alp.min_vertex_cover(m) + elseif disc_var_pick == 2 + (length(m.candidate_disc_vars) > 15) ? Alp.min_vertex_cover(m) : + Alp.get_candidate_disc_vars(m) + elseif disc_var_pick == 3 # Initial + (length(m.candidate_disc_vars) > 15) ? Alp.min_vertex_cover(m) : + Alp.get_candidate_disc_vars(m) + else + error( + "Unsupported default indicator for picking variables for discretization", + ) + end + else + error( + "Input for parameter :disc_var_pick is illegal. Should be either a Int for default methods indexes or functional inputs.", + ) + end - disc_var_pick = Alp.get_option(m, :disc_var_pick) - - if isa(disc_var_pick, Function) - # eval(Alp.get_option(m, :disc_var_pick))(m) - disc_var_pick(m) - length(m.disc_vars) == 0 && length(m.nonconvex_terms) > 0 && error("[USER FUNCTION] must select at least one variable to perform discretization for convexificiation purpose") - elseif isa(disc_var_pick, Int) - if disc_var_pick == 0 - Alp.get_candidate_disc_vars(m) - elseif disc_var_pick == 1 - Alp.min_vertex_cover(m) - elseif disc_var_pick == 2 - (length(m.candidate_disc_vars) > 15) ? Alp.min_vertex_cover(m) : Alp.get_candidate_disc_vars(m) - elseif disc_var_pick == 3 # Initial - (length(m.candidate_disc_vars) > 15) ? Alp.min_vertex_cover(m) : Alp.get_candidate_disc_vars(m) - else - error("Unsupported default indicator for picking variables for discretization") - end - else - error("Input for parameter :disc_var_pick is illegal. Should be either a Int for default methods indexes or functional inputs.") - end - - return + return end diff --git a/src/amp.jl b/src/amp.jl index d863031a..3b02367b 100644 --- a/src/amp.jl +++ b/src/amp.jl @@ -15,8 +15,7 @@ This function is implemented in the following manner: * [`amp_post_lifted_obj`](@ref): post original or lifted objective function * [`amp_post_tmc_mccormick`](@ref): post Tighten McCormick variables and constraints base on `discretization` information """ -function create_bounding_mip(m::Optimizer; use_disc=nothing) - +function create_bounding_mip(m::Optimizer; use_disc = nothing) use_disc === nothing ? discretization = m.discretization : discretization = use_disc m.model_mip = Model(Alp.get_option(m, :mip_solver)) # Construct JuMP Model @@ -25,7 +24,7 @@ function create_bounding_mip(m::Optimizer; use_disc=nothing) Alp.amp_post_vars(m) # Post original and lifted variables Alp.amp_post_lifted_constraints(m) # Post lifted constraints Alp.amp_post_lifted_objective(m) # Post objective - Alp.amp_post_convexification(m, use_disc=discretization) # Convexify problem + Alp.amp_post_convexification(m, use_disc = discretization) # Convexify problem # --------------------------------- # cputime_build = time() - start_build m.logs[:total_time] += cputime_build @@ -40,8 +39,7 @@ end wrapper function to convexify the problem for a bounding model. This function talks to nonconvex_terms and convexification methods to finish the last step required during the construction of bounding model. """ -function amp_post_convexification(m::Optimizer; use_disc=nothing) - +function amp_post_convexification(m::Optimizer; use_disc = nothing) use_disc === nothing ? discretization = m.discretization : discretization = use_disc # for i in 1:length(Alp.get_option(m, :method_convexification)) # Additional user-defined convexification method @@ -49,8 +47,8 @@ function amp_post_convexification(m::Optimizer; use_disc=nothing) # Alp.get_option(m, :method_convexification)[i](m) # end - Alp.amp_post_mccormick(m, use_disc=discretization) # handles all bi-linear and monomial convexificaitons - Alp.amp_post_convhull(m, use_disc=discretization) # convex hull representation + Alp.amp_post_mccormick(m, use_disc = discretization) # handles all bi-linear and monomial convexificaitons + Alp.amp_post_convhull(m, use_disc = discretization) # convex hull representation Alp.is_fully_convexified(m) # Ensure if all the non-linear terms are convexified @@ -58,20 +56,28 @@ function amp_post_convexification(m::Optimizer; use_disc=nothing) end function amp_post_vars(m::Optimizer; kwargs...) - options = Dict(kwargs) if haskey(options, :use_disc) - l_var = [options[:use_disc][i][1] for i in 1:(m.num_var_orig + m.num_var_linear_mip + m.num_var_nonlinear_mip)] - u_var = [options[:use_disc][i][end] for i in 1:(m.num_var_orig + m.num_var_linear_mip + m.num_var_nonlinear_mip)] + l_var = [ + options[:use_disc][i][1] for + i in 1:(m.num_var_orig+m.num_var_linear_mip+m.num_var_nonlinear_mip) + ] + u_var = [ + options[:use_disc][i][end] for + i in 1:(m.num_var_orig+m.num_var_linear_mip+m.num_var_nonlinear_mip) + ] else l_var = m.l_var_tight u_var = m.u_var_tight end - JuMP.@variable(m.model_mip, x[i=1:(m.num_var_orig + m.num_var_linear_mip + m.num_var_nonlinear_mip)]) + JuMP.@variable( + m.model_mip, + x[i = 1:(m.num_var_orig+m.num_var_linear_mip+m.num_var_nonlinear_mip)] + ) - for i in 1:(m.num_var_orig + m.num_var_linear_mip + m.num_var_nonlinear_mip) + for i in 1:(m.num_var_orig+m.num_var_linear_mip+m.num_var_nonlinear_mip) # Interestingly, not enforcing category of lifted variables is able to improve performance if i <= m.num_var_orig if m.var_type_orig[i] == :Bin @@ -85,15 +91,15 @@ function amp_post_vars(m::Optimizer; kwargs...) # Changed to tight bound, if no bound tightening is performed, will be just .u_var_orig u_var[i] < Inf && JuMP.set_upper_bound(x[i], u_var[i]) - m.var_type[i] == :Int && error("Alpine does not support MINLPs with generic integer (non-binary) variables yet! Try Juniper.jl for finding a local feasible solution") + m.var_type[i] == :Int && error( + "Alpine does not support MINLPs with generic integer (non-binary) variables yet! Try Juniper.jl for finding a local feasible solution", + ) end return end - function amp_post_lifted_constraints(m::Optimizer) - for i in 1:m.num_constr_orig if m.constr_structure[i] == :affine Alp.amp_post_affine_constraint(m.model_mip, m.bounding_constr_mip[i]) @@ -112,16 +118,33 @@ function amp_post_lifted_constraints(m::Optimizer) end function amp_post_affine_constraint(model_mip::JuMP.Model, affine::Dict) - if affine[:sense] == :(>=) - JuMP.@constraint(model_mip, - sum(affine[:coefs][j]*_index_to_variable_ref(model_mip, affine[:vars][j].args[2]) for j in 1:affine[:cnt]) >= affine[:rhs]) + JuMP.@constraint( + model_mip, + sum( + affine[:coefs][j] * + _index_to_variable_ref(model_mip, affine[:vars][j].args[2]) for + j in 1:affine[:cnt] + ) >= affine[:rhs] + ) elseif affine[:sense] == :(<=) - JuMP.@constraint(model_mip, - sum(affine[:coefs][j]*_index_to_variable_ref(model_mip, affine[:vars][j].args[2]) for j in 1:affine[:cnt]) <= affine[:rhs]) + JuMP.@constraint( + model_mip, + sum( + affine[:coefs][j] * + _index_to_variable_ref(model_mip, affine[:vars][j].args[2]) for + j in 1:affine[:cnt] + ) <= affine[:rhs] + ) elseif affine[:sense] == :(==) - JuMP.@constraint(model_mip, - sum(affine[:coefs][j]*_index_to_variable_ref(model_mip, affine[:vars][j].args[2]) for j in 1:affine[:cnt]) == affine[:rhs]) + JuMP.@constraint( + model_mip, + sum( + affine[:coefs][j] * + _index_to_variable_ref(model_mip, affine[:vars][j].args[2]) for + j in 1:affine[:cnt] + ) == affine[:rhs] + ) else error("Unkown sense.") end @@ -130,40 +153,76 @@ function amp_post_affine_constraint(model_mip::JuMP.Model, affine::Dict) end function amp_post_convex_constraint(model_mip::JuMP.Model, convex::Dict) - - !prod([i == 2 for i in convex[:powers]]) && error("No relaxation implementation for convex constraints $(convex[:expr])") + !prod([i == 2 for i in convex[:powers]]) && + error("No relaxation implementation for convex constraints $(convex[:expr])") if convex[:sense] == :(<=) - JuMP.@constraint(model_mip, - sum(convex[:coefs][j]*_index_to_variable_ref(model_mip, convex[:vars][j].args[2])^2 for j in 1:convex[:cnt]) <= convex[:rhs]) + JuMP.@constraint( + model_mip, + sum( + convex[:coefs][j] * + _index_to_variable_ref(model_mip, convex[:vars][j].args[2])^2 for + j in 1:convex[:cnt] + ) <= convex[:rhs] + ) elseif convex[:sense] == :(>=) - JuMP.@constraint(model_mip, - sum(convex[:coefs][j]*_index_to_variable_ref(model_mip, convex[:vars][j].args[2])^2 for j in 1:convex[:cnt]) >= convex[:rhs]) + JuMP.@constraint( + model_mip, + sum( + convex[:coefs][j] * + _index_to_variable_ref(model_mip, convex[:vars][j].args[2])^2 for + j in 1:convex[:cnt] + ) >= convex[:rhs] + ) else - error("No equality constraints should be recognized as supported convex constriants") + error( + "No equality constraints should be recognized as supported convex constriants", + ) end return end function amp_post_linear_lift_constraints(model_mip::JuMP.Model, l::Dict) - @assert l[:ref][:sign] == :+ - JuMP.@constraint(model_mip, _index_to_variable_ref(model_mip, l[:y_idx]) == sum(i[1]*_index_to_variable_ref(model_mip, i[2]) for i in l[:ref][:coef_var]) + l[:ref][:scalar]) + JuMP.@constraint( + model_mip, + _index_to_variable_ref(model_mip, l[:y_idx]) == + sum(i[1] * _index_to_variable_ref(model_mip, i[2]) for i in l[:ref][:coef_var]) + + l[:ref][:scalar] + ) return end function amp_post_lifted_objective(m::Optimizer) -#if isa(m.obj_expr_orig, Number) -if expr_isconst(m.obj_expr_orig) - JuMP.@objective(m.model_mip, m.sense_orig, eval(m.obj_expr_orig)) - elseif m.obj_structure == :affine - JuMP.@objective(m.model_mip, m.sense_orig, m.bounding_obj_mip[:rhs] + sum(m.bounding_obj_mip[:coefs][i]*_index_to_variable_ref(m.model_mip, m.bounding_obj_mip[:vars][i].args[2]) for i in 1:m.bounding_obj_mip[:cnt])) + #if isa(m.obj_expr_orig, Number) + if expr_isconst(m.obj_expr_orig) + JuMP.@objective(m.model_mip, m.sense_orig, eval(m.obj_expr_orig)) + elseif m.obj_structure == :affine + JuMP.@objective( + m.model_mip, + m.sense_orig, + m.bounding_obj_mip[:rhs] + sum( + m.bounding_obj_mip[:coefs][i] * + _index_to_variable_ref(m.model_mip, m.bounding_obj_mip[:vars][i].args[2]) + for i in 1:m.bounding_obj_mip[:cnt] + ) + ) elseif m.obj_structure == :convex # This works only when the original objective is convex quadratic. # Higher-order convex monomials need implementation of outer-approximation (check resolve_convex_constr in operators.jl) - JuMP.@objective(m.model_mip, m.sense_orig, m.bounding_obj_mip[:rhs] + sum(m.bounding_obj_mip[:coefs][i]*_index_to_variable_ref(m.model_mip, m.bounding_obj_mip[:vars][i].args[2])^2 for i in 1:m.bounding_obj_mip[:cnt])) + JuMP.@objective( + m.model_mip, + m.sense_orig, + m.bounding_obj_mip[:rhs] + sum( + m.bounding_obj_mip[:coefs][i] * + _index_to_variable_ref( + m.model_mip, + m.bounding_obj_mip[:vars][i].args[2], + )^2 for i in 1:m.bounding_obj_mip[:cnt] + ) + ) else error("Unknown structural obj type $(m.obj_structure)") end @@ -171,18 +230,27 @@ if expr_isconst(m.obj_expr_orig) end function add_partition(m::Optimizer; kwargs...) - options = Dict(kwargs) - haskey(options, :use_disc) ? discretization = options[:use_disc] : discretization = m.discretization - haskey(options, :use_solution) ? point_vec = options[:use_solution] : point_vec = m.best_bound_sol + haskey(options, :use_disc) ? discretization = options[:use_disc] : + discretization = m.discretization + haskey(options, :use_solution) ? point_vec = options[:use_solution] : + point_vec = m.best_bound_sol if isa(Alp.get_option(m, :disc_add_partition_method), Function) # m.discretization = eval(Alp.get_option(m, :disc_add_partition_method))(m, use_disc=discretization, use_solution=point_vec) - m.discretization = Alp.get_option(m, :disc_add_partition_method)(m, use_disc=discretization, use_solution=point_vec) + m.discretization = Alp.get_option(m, :disc_add_partition_method)( + m, + use_disc = discretization, + use_solution = point_vec, + ) elseif Alp.get_option(m, :disc_add_partition_method) == "adaptive" - m.discretization = Alp.add_adaptive_partition(m, use_disc=discretization, use_solution=point_vec) + m.discretization = Alp.add_adaptive_partition( + m, + use_disc = discretization, + use_solution = point_vec, + ) elseif Alp.get_option(m, :disc_add_partition_method) == "uniform" - m.discretization = add_uniform_partition(m, use_disc=discretization) + m.discretization = add_uniform_partition(m, use_disc = discretization) else error("Unknown input on how to add partitions.") end @@ -209,19 +277,21 @@ There are two options for this function, This function can be accordingly modified by the user to change the behavior of the solver, and thus the convergence. """ -function add_adaptive_partition(m::Optimizer;kwargs...) - +function add_adaptive_partition(m::Optimizer; kwargs...) options = Dict(kwargs) - haskey(options, :use_disc) ? discretization = options[:use_disc] : discretization = m.discretization - haskey(options, :use_solution) ? point_vec = copy(options[:use_solution]) : point_vec = copy(m.best_bound_sol) - haskey(options, :use_ratio) ? ratio = options[:use_ratio] : ratio = Alp.get_option(m, :disc_ratio) + haskey(options, :use_disc) ? discretization = options[:use_disc] : + discretization = m.discretization + haskey(options, :use_solution) ? point_vec = copy(options[:use_solution]) : + point_vec = copy(m.best_bound_sol) + haskey(options, :use_ratio) ? ratio = options[:use_ratio] : + ratio = Alp.get_option(m, :disc_ratio) haskey(options, :branching) ? branching = options[:branching] : branching = false - + if length(point_vec) < m.num_var_orig + m.num_var_linear_mip + m.num_var_nonlinear_mip point_vec = Alp.resolve_lifted_var_value(m, point_vec) # Update the solution vector for lifted variable end - + if branching discretization = deepcopy(discretization) end @@ -249,7 +319,9 @@ function add_adaptive_partition(m::Optimizer;kwargs...) @warn " Warning: Binary variable in m.disc_vars. Check out what is wrong..." continue # No partition should be added to binary variable unless user specified elseif m.var_type[i] == :Int - error("Alpine does not support MINLPs with generic integer (non-binary) variables yet!") + error( + "Alpine does not support MINLPs with generic integer (non-binary) variables yet!", + ) else error("Unexpected variable types while inserting partitions") end @@ -262,22 +334,20 @@ end This function targets to address unexpected numerical issues when adding partitions in tight regions. """ function correct_point(m::Optimizer, partvec::Vector, point::Float64, var::Int) - tol = Alp.get_option(m, :tol) if point < partvec[1] - tol || point > partvec[end] + tol @warn " Warning: VAR$(var) SOL=$(point) out of discretization [$(partvec[1]),$(partvec[end])]. Hence, taking the middle point." - return 0.5*(partvec[1] + partvec[end]) # Should choose the longest range + return 0.5 * (partvec[1] + partvec[end]) # Should choose the longest range end - isapprox(point, partvec[1]; atol = tol) && return partvec[1] + isapprox(point, partvec[1]; atol = tol) && return partvec[1] isapprox(point, partvec[end]; atol = tol) && return partvec[end] return point end function calculate_radius(partvec::Vector, part::Int, ratio::Any) - lb_local = partvec[part] ub_local = partvec[part+1] @@ -293,27 +363,38 @@ function calculate_radius(partvec::Vector, part::Int, ratio::Any) return radius end -function insert_partition(m::Optimizer, var::Int, partidx::Int, point::Number, radius::Float64, partvec::Vector) - - abstol, reltol = Alp.get_option(m, :disc_abs_width_tol), Alp.get_option(m, :disc_rel_width_tol) +function insert_partition( + m::Optimizer, + var::Int, + partidx::Int, + point::Number, + radius::Float64, + partvec::Vector, +) + abstol, reltol = + Alp.get_option(m, :disc_abs_width_tol), Alp.get_option(m, :disc_rel_width_tol) lb_local, ub_local = partvec[partidx], partvec[partidx+1] ub_touch, lb_touch = true, true lb_new, ub_new = max(point - radius, lb_local), min(point + radius, ub_local) - if ub_new < ub_local && !isapprox(ub_new, ub_local; atol=abstol) && abs(ub_new-ub_local)/(1e-8+abs(ub_local)) > reltol # Insert new UB-based partition - insert!(partvec, partidx+1, ub_new) + if ub_new < ub_local && + !isapprox(ub_new, ub_local; atol = abstol) && + abs(ub_new - ub_local) / (1e-8 + abs(ub_local)) > reltol # Insert new UB-based partition + insert!(partvec, partidx + 1, ub_new) ub_touch = false end - if lb_new > lb_local && !isapprox(lb_new, lb_local; atol=abstol) && abs(lb_new-lb_local)/(1e-8+abs(lb_local)) > reltol # Insert new LB-based partition - insert!(partvec, partidx+1, lb_new) + if lb_new > lb_local && + !isapprox(lb_new, lb_local; atol = abstol) && + abs(lb_new - lb_local) / (1e-8 + abs(lb_local)) > reltol # Insert new LB-based partition + insert!(partvec, partidx + 1, lb_new) lb_touch = false end if (ub_touch && lb_touch) || Alp.check_solution_history(m, var) - distvec = [(j, partvec[j+1]-partvec[j]) for j in 1:length(partvec)-1] - sort!(distvec, by=x->x[2]) + distvec = [(j, partvec[j+1] - partvec[j]) for j in 1:length(partvec)-1] + sort!(distvec, by = x -> x[2]) point_orig = point pos = distvec[end][1] lb_local = partvec[pos] @@ -322,36 +403,48 @@ function insert_partition(m::Optimizer, var::Int, partidx::Int, point::Number, r chunk = (ub_local - lb_local) / Alp.get_option(m, :disc_divert_chunks) point = lb_local + (ub_local - lb_local) / Alp.get_option(m, :disc_divert_chunks) for i in 2:Alp.get_option(m, :disc_divert_chunks) - insert!(partvec, pos+1, lb_local + chunk * (Alp.get_option(m, :disc_divert_chunks)-(i-1))) + insert!( + partvec, + pos + 1, + lb_local + chunk * (Alp.get_option(m, :disc_divert_chunks) - (i - 1)), + ) end - (Alp.get_option(m, :log_level) > 199) && println("[DEBUG] !D! VAR$(var): SOL=$(round(point_orig; digits = 4))=>$(point) |$(round(lb_local; digits = 4)) | $(Alp.get_option(m, :disc_divert_chunks)) SEGMENTS | $(round(ub_local; digits = 4))|") + (Alp.get_option(m, :log_level) > 199) && println( + "[DEBUG] !D! VAR$(var): SOL=$(round(point_orig; digits = 4))=>$(point) |$(round(lb_local; digits = 4)) | $(Alp.get_option(m, :disc_divert_chunks)) SEGMENTS | $(round(ub_local; digits = 4))|", + ) else - (Alp.get_option(m, :log_level) > 199) && println("[DEBUG] VAR$(var): SOL=$(round(point; digits = 4)) RADIUS=$(radius), PARTITIONS=$(length(partvec)-1) |$(round(lb_local; digits = 4)) |$(round(lb_new; digits = 6)) <- * -> $(round(ub_new; digits = 6))| $(round(ub_local; digits = 4))|") + (Alp.get_option(m, :log_level) > 199) && println( + "[DEBUG] VAR$(var): SOL=$(round(point; digits = 4)) RADIUS=$(radius), PARTITIONS=$(length(partvec)-1) |$(round(lb_local; digits = 4)) |$(round(lb_new; digits = 6)) <- * -> $(round(ub_new; digits = 6))| $(round(ub_local; digits = 4))|", + ) end return end function add_uniform_partition(m::Optimizer; kwargs...) - options = Dict(kwargs) - haskey(options, :use_disc) ? discretization = options[:use_disc] : discretization = m.discretization + haskey(options, :use_disc) ? discretization = options[:use_disc] : + discretization = m.discretization for i in m.disc_vars # Only construct when discretized lb_local = discretization[i][1] ub_local = discretization[i][end] distance = ub_local - lb_local - chunk = distance / ((m.logs[:n_iter]+1)*Alp.get_option(m, :disc_uniform_rate)) - discretization[i] = [lb_local+chunk*(j-1) for j in 1:(m.logs[:n_iter]+1)*Alp.get_option(m, :disc_uniform_rate)] + chunk = distance / ((m.logs[:n_iter] + 1) * Alp.get_option(m, :disc_uniform_rate)) + discretization[i] = [ + lb_local + chunk * (j - 1) for + j in 1:(m.logs[:n_iter]+1)*Alp.get_option(m, :disc_uniform_rate) + ] push!(discretization[i], ub_local) # Safety Scheme - (Alp.get_option(m, :log_level) > 199) && println("[DEBUG] VAR$(i): RATE=$(Alp.get_option(m, :disc_uniform_rate)), PARTITIONS=$(length(discretization[i])) |$(round(lb_local; digits=4)) | $(Alp.get_option(m, :disc_uniform_rate)*(1+m.logs[:n_iter])) SEGMENTS | $(round(ub_local; digits=4))|") + (Alp.get_option(m, :log_level) > 199) && println( + "[DEBUG] VAR$(i): RATE=$(Alp.get_option(m, :disc_uniform_rate)), PARTITIONS=$(length(discretization[i])) |$(round(lb_local; digits=4)) | $(Alp.get_option(m, :disc_uniform_rate)*(1+m.logs[:n_iter])) SEGMENTS | $(round(ub_local; digits=4))|", + ) end return discretization end -function update_disc_ratio(m::Optimizer, presolve=false) - +function update_disc_ratio(m::Optimizer, presolve = false) m.logs[:n_iter] > 2 && return Alp.get_option(m, :disc_ratio) # Stop branching after the second iterations ratio_pool = [8:2:20;] # Built-in try range @@ -365,9 +458,20 @@ function update_disc_ratio(m::Optimizer, presolve=false) for r in ratio_pool st = time() if !isempty(m.best_sol) - branch_disc = Alp.add_adaptive_partition(m, use_disc = m.discretization, branching = true, use_ratio = r, use_solution = m.best_sol) + branch_disc = Alp.add_adaptive_partition( + m, + use_disc = m.discretization, + branching = true, + use_ratio = r, + use_solution = m.best_sol, + ) else - branch_disc = Alp.add_adaptive_partition(m, use_disc = m.discretization, branching = true, use_ratio = r) + branch_disc = Alp.add_adaptive_partition( + m, + use_disc = m.discretization, + branching = true, + use_ratio = r, + ) end Alp.create_bounding_mip(m, use_disc = branch_disc) res = Alp.disc_branch_solve(m) @@ -381,18 +485,31 @@ function update_disc_ratio(m::Optimizer, presolve=false) println("Expensive disc branching pass... Fixed at 8") return 8 end - Alp.get_option(m, :log_level) > 0 && println("BRANCH RATIO = $(r), METRIC = $(res) || TIME = $(time()-st)") + Alp.get_option(m, :log_level) > 0 && + println("BRANCH RATIO = $(r), METRIC = $(res) || TIME = $(time()-st)") end if Statistics.std(res_collector) >= 1e-2 # Detect if all solutions are similar to each other - Alp.get_option(m, :log_level) > 0 && println("RATIO BRANCHING OFF due to solution variance test passed.") + Alp.get_option(m, :log_level) > 0 && + println("RATIO BRANCHING OFF due to solution variance test passed.") Alp.set_option(m, :disc_ratio_branch, false) # If an incumbent ratio is selected, then stop the branching scheme end if !isempty(m.best_sol) - m.discretization = Alp.add_adaptive_partition(m, use_disc = m.discretization, branching = true, use_ratio = incumb_ratio, use_solution = m.best_sol) + m.discretization = Alp.add_adaptive_partition( + m, + use_disc = m.discretization, + branching = true, + use_ratio = incumb_ratio, + use_solution = m.best_sol, + ) else - m.discretization = Alp.add_adaptive_partition(m, use_disc = m.discretization, branching = true, use_ratio = incumb_ratio) + m.discretization = Alp.add_adaptive_partition( + m, + use_disc = m.discretization, + branching = true, + use_ratio = incumb_ratio, + ) end Alp.get_option(m, :log_level) > 0 && println("INCUMB_RATIO = $(incumb_ratio)") diff --git a/src/bounds.jl b/src/bounds.jl index adaae30e..df7bf7fe 100644 --- a/src/bounds.jl +++ b/src/bounds.jl @@ -5,8 +5,14 @@ Initialize internal bound vectors (placeholders) to be used in other places. In this case, we don't have to mess with the original bound information. """ function init_tight_bound(m::Optimizer) - m.l_var_tight = [m.l_var_orig; fill(-Inf, m.num_var_linear_mip + m.num_var_nonlinear_mip)] - m.u_var_tight = [m.u_var_orig; fill(Inf, m.num_var_linear_mip + m.num_var_nonlinear_mip)] + m.l_var_tight = [ + m.l_var_orig + fill(-Inf, m.num_var_linear_mip + m.num_var_nonlinear_mip) + ] + m.u_var_tight = [ + m.u_var_orig + fill(Inf, m.num_var_linear_mip + m.num_var_nonlinear_mip) + ] for i in 1:m.num_var_orig if m.var_type_orig[i] == :Bin m.l_var_tight[i] = 0.0 @@ -27,18 +33,21 @@ This function initialize the dynamic discretization used for any bounding models The output is a dictionary with MathProgBase variable indices keys attached to the :Optimizer.discretization. """ function init_disc(m::Optimizer) - - for var in 1:(m.num_var_orig + m.num_var_linear_mip + m.num_var_nonlinear_mip) + for var in 1:(m.num_var_orig+m.num_var_linear_mip+m.num_var_nonlinear_mip) if m.var_type[var] in [:Bin, :Cont] lb = m.l_var_tight[var] ub = m.u_var_tight[var] m.discretization[var] = [lb, ub] elseif m.var_type[var] in [:Int] - Alp.get_option(m, :int_enable) ? lb = floor(m.l_var_tight[var]) - 0.5 : lb = floor(m.l_var_tight[var]) - Alp.get_option(m, :int_enable) ? ub = ceil(m.u_var_tight[var]) + 0.5 : ub = floor(m.u_var_tight[var]) + Alp.get_option(m, :int_enable) ? lb = floor(m.l_var_tight[var]) - 0.5 : + lb = floor(m.l_var_tight[var]) + Alp.get_option(m, :int_enable) ? ub = ceil(m.u_var_tight[var]) + 0.5 : + ub = floor(m.u_var_tight[var]) m.discretization[var] = [lb, ub] else - error("[EXCEPTION] Unexpected variable type when initializing discretization dictionary.") + error( + "[EXCEPTION] Unexpected variable type when initializing discretization dictionary.", + ) end end @@ -54,7 +63,6 @@ partition operations. """ function to_discretization(m::Optimizer, lbs::Vector{Float64}, ubs::Vector{Float64}) - @assert length(lbs) == length(ubs) var_discretization = Dict() for var in 1:m.num_var_orig @@ -90,16 +98,14 @@ Utility functions to eliminate all partition on discretizing variable and keep t """ function flatten_discretization(discretization::Dict; kwargs...) - flatten_discretization = Dict() for var in keys(discretization) - flatten_discretization[var] = [discretization[var][1],discretization[var][end]] + flatten_discretization[var] = [discretization[var][1], discretization[var][end]] end return flatten_discretization end - """ detect_bound_from_aff(m::Optimizer) @@ -108,7 +114,6 @@ x >= 5, x <= 5 or x == 5 and fetch the information to m.l_var_tight and m.u_var_ This function can potential grow to be smarter. """ function bound_propagation(m::Optimizer) - exhausted = false infeasible = false tol = Alp.get_option(m, :tol) @@ -125,21 +130,41 @@ function bound_propagation(m::Optimizer) eval_l_bound = aff[:rhs] / var_coef eval_u_bound = aff[:rhs] / var_coef for j in 1:length(aff[:vars]) - if j != i && aff[:coefs][j]*var_coef > 0.0 # same sign - (eval_l_bound != -Inf) && (eval_l_bound -= abs(aff[:coefs][j]/var_coef)*m.u_var_tight[aff[:vars][j].args[2]]) - (eval_u_bound != Inf) && (eval_u_bound -= abs(aff[:coefs][j]/var_coef)*m.l_var_tight[aff[:vars][j].args[2]]) - elseif j!= i && aff[:coefs][j]*var_coef < 0.0 # different sign - (eval_l_bound != -Inf) && (eval_l_bound += abs(aff[:coefs][j]/var_coef)*m.l_var_tight[aff[:vars][j].args[2]]) - (eval_u_bound != Inf) && (eval_u_bound += abs(aff[:coefs][j]/var_coef)*m.u_var_tight[aff[:vars][j].args[2]]) + if j != i && aff[:coefs][j] * var_coef > 0.0 # same sign + (eval_l_bound != -Inf) && ( + eval_l_bound -= + abs(aff[:coefs][j] / var_coef) * + m.u_var_tight[aff[:vars][j].args[2]] + ) + (eval_u_bound != Inf) && ( + eval_u_bound -= + abs(aff[:coefs][j] / var_coef) * + m.l_var_tight[aff[:vars][j].args[2]] + ) + elseif j != i && aff[:coefs][j] * var_coef < 0.0 # different sign + (eval_l_bound != -Inf) && ( + eval_l_bound += + abs(aff[:coefs][j] / var_coef) * + m.l_var_tight[aff[:vars][j].args[2]] + ) + (eval_u_bound != Inf) && ( + eval_u_bound += + abs(aff[:coefs][j] / var_coef) * + m.u_var_tight[aff[:vars][j].args[2]] + ) end end if eval_l_bound > m.l_var_tight[var_idx] + tol exhausted = false m.l_var_tight[var_idx] = eval_l_bound - (Alp.get_option(m, :log_level) > 199) && println("[VAR$(var_idx)] LB $(m.l_var_tight[var_idx]) evaluated from constraint") + (Alp.get_option(m, :log_level) > 199) && println( + "[VAR$(var_idx)] LB $(m.l_var_tight[var_idx]) evaluated from constraint", + ) elseif eval_l_bound > m.u_var_tight[var_idx] + tol - (Alp.get_option(m, :log_level) > 199) && println("[VAR$(var_idx)] Infeasibility detection during bound propagation") + (Alp.get_option(m, :log_level) > 199) && println( + "[VAR$(var_idx)] Infeasibility detection during bound propagation", + ) infeasible = true break end @@ -147,21 +172,29 @@ function bound_propagation(m::Optimizer) if eval_u_bound < m.u_var_tight[var_idx] - tol exhausted = false m.u_var_tight[var_idx] = eval_u_bound - (Alp.get_option(m, :log_level) > 199) && println("[VAR$(var_idx)] UB $(m.u_var_tight[var_idx]) evaluated from constraints") + (Alp.get_option(m, :log_level) > 199) && println( + "[VAR$(var_idx)] UB $(m.u_var_tight[var_idx]) evaluated from constraints", + ) elseif eval_u_bound < m.l_var_tight[var_idx] - tol - (Alp.get_option(m, :log_level) > 199) && println("[VAR$(var_idx)] Infeasibility detection during bound propagation") + (Alp.get_option(m, :log_level) > 199) && println( + "[VAR$(var_idx)] Infeasibility detection during bound propagation", + ) infeasible = true break end elseif aff[:sense] == :(>=) && var_coef > 0.0 # a($) - by + cz >= 100, y∈[1,10], z∈[2,50], a,b,c > 0 - eval_bound = aff[:rhs] / var_coef for j in 1:length(aff[:vars]) if j != i && aff[:coefs][j] > 0.0 - eval_bound -= abs(aff[:coefs][j]/var_coef) * m.u_var_tight[aff[:vars][j].args[2]] - elseif j !=i aff[:coefs][j] < 0.0 - eval_bound += abs(aff[:coefs][j]/var_coef) * m.l_var_tight[aff[:vars][j].args[2]] + eval_bound -= + abs(aff[:coefs][j] / var_coef) * + m.u_var_tight[aff[:vars][j].args[2]] + elseif j != i + aff[:coefs][j] < 0.0 + eval_bound += + abs(aff[:coefs][j] / var_coef) * + m.l_var_tight[aff[:vars][j].args[2]] end (eval_bound == -Inf) && break end @@ -169,9 +202,13 @@ function bound_propagation(m::Optimizer) if eval_bound > m.l_var_tight[var_idx] + tol exhausted = false m.l_var_tight[var_idx] = eval_bound - (Alp.get_option(m, :log_level) > 199) && println("[VAR$(var_idx)] LB $(m.l_var_tight[var_idx]) evaluated from constraints") + (Alp.get_option(m, :log_level) > 199) && println( + "[VAR$(var_idx)] LB $(m.l_var_tight[var_idx]) evaluated from constraints", + ) elseif eval_bound > m.u_var_tight[var_idx] + tol - (Alp.get_option(m, :log_level) > 199) && println("[VAR$(var_idx)] Infeasibility detection during bound propagation") + (Alp.get_option(m, :log_level) > 199) && println( + "[VAR$(var_idx)] Infeasibility detection during bound propagation", + ) infeasible = true break end @@ -180,9 +217,13 @@ function bound_propagation(m::Optimizer) eval_bound = aff[:rhs] / var_coef for j in 1:length(aff[:vars]) if j != i && aff[:coefs][j] > 0.0 - eval_bound += abs(aff[:coefs][j]/var_coef) * m.u_var_tight[aff[:vars][j].args[2]] + eval_bound += + abs(aff[:coefs][j] / var_coef) * + m.u_var_tight[aff[:vars][j].args[2]] elseif j != i && aff[:coefs][j] < 0.0 - eval_bound -= abs(aff[:coefs][j]/var_coef) * m.l_var_tight[aff[:vars][j].args[2]] + eval_bound -= + abs(aff[:coefs][j] / var_coef) * + m.l_var_tight[aff[:vars][j].args[2]] end (eval_bound == Inf) && break end @@ -190,9 +231,13 @@ function bound_propagation(m::Optimizer) if eval_bound < m.u_var_tight[var_idx] - tol exhausted = false m.u_var_tight[var_idx] = eval_bound - (Alp.get_option(m, :log_level) > 199) && println("[VAR$(var_idx)] UB $(m.u_var_tight[var_idx]) evaluated from constraints") + (Alp.get_option(m, :log_level) > 199) && println( + "[VAR$(var_idx)] UB $(m.u_var_tight[var_idx]) evaluated from constraints", + ) elseif eval_bound < m.l_var_tight[var_idx] - tol - (Alp.get_option(m, :log_level) > 199) && println("[VAR$(var_idx)] Infeasibility detection during bound propagation") + (Alp.get_option(m, :log_level) > 199) && println( + "[VAR$(var_idx)] Infeasibility detection during bound propagation", + ) infeasible = true break end @@ -201,9 +246,13 @@ function bound_propagation(m::Optimizer) eval_bound = aff[:rhs] / var_coef for j in 1:length(aff[:vars]) if j != i && aff[:coefs][j] > 0.0 - eval_bound -= abs(aff[:coefs][j]/var_coef) * m.l_var_tight[aff[:vars][j].args[2]] + eval_bound -= + abs(aff[:coefs][j] / var_coef) * + m.l_var_tight[aff[:vars][j].args[2]] elseif j != i && aff[:coefs][j] < 0.0 - eval_bound += abs(aff[:coefs][j]/var_coef) * m.u_var_tight[aff[:vars][j].args[2]] + eval_bound += + abs(aff[:coefs][j] / var_coef) * + m.u_var_tight[aff[:vars][j].args[2]] end (eval_bound == Inf) && break end @@ -211,9 +260,13 @@ function bound_propagation(m::Optimizer) if eval_bound < m.u_var_tight[var_idx] - tol exhausted = false m.u_var_tight[var_idx] = eval_bound - (Alp.get_option(m, :log_level) > 199) && println("[VAR$(var_idx)] UB $(m.u_var_tight[var_idx]) evaluated from constraints") + (Alp.get_option(m, :log_level) > 199) && println( + "[VAR$(var_idx)] UB $(m.u_var_tight[var_idx]) evaluated from constraints", + ) elseif eval_bound < m.l_var_tight[var_idx] - tol - (Alp.get_option(m, :log_level) > 199) && println("[VAR$(var_idx)] Infeasibility detection during bound propagation") + (Alp.get_option(m, :log_level) > 199) && println( + "[VAR$(var_idx)] Infeasibility detection during bound propagation", + ) infeasible = true break end @@ -221,9 +274,13 @@ function bound_propagation(m::Optimizer) eval_bound = aff[:rhs] / var_coef for j in 1:length(aff[:vars]) if j != i && aff[:coefs][j] > 0.0 - eval_bound += abs(aff[:coefs][j]/var_coef) * m.l_var_tight[aff[:vars][j].args[2]] + eval_bound += + abs(aff[:coefs][j] / var_coef) * + m.l_var_tight[aff[:vars][j].args[2]] elseif j != i && aff[:coefs][j] < 0.0 - eval_bound -= abs(aff[:coefs][j]/var_coef) * m.u_var_tight[aff[:vars][j].args[2]] + eval_bound -= + abs(aff[:coefs][j] / var_coef) * + m.u_var_tight[aff[:vars][j].args[2]] end (eval_bound == -Inf) && break end @@ -231,17 +288,21 @@ function bound_propagation(m::Optimizer) if eval_bound > m.l_var_tight[var_idx] + tol exhausted = false m.l_var_tight[var_idx] = eval_bound - (Alp.get_option(m, :log_level) > 199) && println("[VAR$(var_idx)] LB $(m.l_var_tight[var_idx]) evaluated from constraints") + (Alp.get_option(m, :log_level) > 199) && println( + "[VAR$(var_idx)] LB $(m.l_var_tight[var_idx]) evaluated from constraints", + ) elseif eval_bound > m.u_var_tight[var_idx] + tol - (Alp.get_option(m, :log_level) > 199) && println("[VAR$(var_idx)] Infeasibility detection during bound propagation") + (Alp.get_option(m, :log_level) > 199) && println( + "[VAR$(var_idx)] Infeasibility detection during bound propagation", + ) infeasible = true break end - end end end - (exhausted == true && Alp.get_option(m, :log_level) > 99) && println("Initial constraint-based bound evaluation exhausted...") + (exhausted == true && Alp.get_option(m, :log_level) > 99) && + println("Initial constraint-based bound evaluation exhausted...") end if infeasible @@ -256,7 +317,6 @@ end Recategorize :Int variables to :Bin variables if variable bounds are [0,1] """ function recategorize_var(m::Optimizer) - for i in 1:m.num_var_orig if m.var_type_orig[i] == :Int && m.l_var_orig[i] == 0.0 && m.u_var_orig[i] == 1.0 m.var_type_orig[i] = :Bin @@ -309,7 +369,7 @@ function resolve_inf_bounds(m::Optimizer) infcount_u = 0 # Only specify necessary bounds - for i = 1:length(m.l_var_orig) + for i in 1:length(m.l_var_orig) if m.l_var_tight[i] == -Inf warnuser = true m.l_var_tight[i] = -Alp.get_option(m, :large_bound) @@ -318,14 +378,18 @@ function resolve_inf_bounds(m::Optimizer) if m.u_var_tight[i] == Inf warnuser = true m.u_var_tight[i] = Alp.get_option(m, :large_bound) - infcount_u +=1 + infcount_u += 1 end end infcount = min(infcount_l, infcount_u) if infcount == 1 - warnuser && println("Warning: -/+Inf bounds detected on at least $infcount variable. Initializing with values -/+$(Alp.get_option(m, :large_bound)). This may affect global optimal values and run times.") + warnuser && println( + "Warning: -/+Inf bounds detected on at least $infcount variable. Initializing with values -/+$(Alp.get_option(m, :large_bound)). This may affect global optimal values and run times.", + ) elseif infcount > 1 - warnuser && println("Warning: -/+Inf bounds detected on at least $infcount variables. Initializing with values -/+$(Alp.get_option(m, :large_bound)). This may affect global optimal values and run times.") + warnuser && println( + "Warning: -/+Inf bounds detected on at least $infcount variables. Initializing with values -/+$(Alp.get_option(m, :large_bound)). This may affect global optimal values and run times.", + ) end return @@ -353,21 +417,23 @@ function resolve_var_bounds(m::Optimizer, d::Dict; kwargs...) d = Alp.basic_binint_bounds(m, nlk, d) elseif m.nonconvex_terms[nlk][:nonlinear_type] in [:BINPROD] d = Alp.basic_binprod_bounds(m, nlk, d) - # elseif m.nonconvex_terms[nlk][:nonlinear_type] in ALPINE_C_TRIGONOMETRIC - # d = basic_sincos_bounds(m, nlk, d) + # elseif m.nonconvex_terms[nlk][:nonlinear_type] in ALPINE_C_TRIGONOMETRIC + # d = basic_sincos_bounds(m, nlk, d) elseif m.nonconvex_terms[nlk][:nonlinear_type] in [:BINLIN] d = Alp.basic_binlin_bounds(m, nlk, d) - # elseif m.nonconvex_terms[nlk][:nonlinear_type] in [:INTLIN] - # d = basic_intlin_bounds(m, nlk, d) - # elseif m.nonconvex_terms[nlk][:nonlinear_type] in [:INTPROD] - # d = basic_intprod_bounds(m, nlk, d) + # elseif m.nonconvex_terms[nlk][:nonlinear_type] in [:INTLIN] + # d = basic_intlin_bounds(m, nlk, d) + # elseif m.nonconvex_terms[nlk][:nonlinear_type] in [:INTPROD] + # d = basic_intprod_bounds(m, nlk, d) else error("EXPECTED ERROR : NEED IMPLEMENTATION") end elseif haskey(m.linear_terms, k) d = Alp.basic_linear_bounds(m, k, d) else - error("Found a homeless term key $(k) during bound resolution im resolve_var_bounds.") + error( + "Found a homeless term key $(k) during bound resolution im resolve_var_bounds.", + ) end end @@ -383,9 +449,9 @@ and the .discretization will be cleared with the tight bounds for basic McCormic """ function resolve_closed_var_bounds(m::Optimizer; kwargs...) - for var in m.candidate_disc_vars - if abs(m.l_var_tight[var] - m.u_var_tight[var]) < Alp.get_option(m, :presolve_bt_width_tol) # Closed Bound Criteria + if abs(m.l_var_tight[var] - m.u_var_tight[var]) < + Alp.get_option(m, :presolve_bt_width_tol) # Closed Bound Criteria deleteat!(m.disc_vars, findfirst(m.disc_vars, var)) # Clean nonconvex_terms by deleting the info m.discretization[var] = [m.l_var_tight[var], m.u_var_tight[var]] # Clean up the discretization for basic McCormick if necessary end @@ -404,7 +470,6 @@ Output:: l_var::Vector{Float64}, u_var::Vector{Float64} """ function update_var_bounds(discretization; kwargs...) - options = Dict(kwargs) haskey(options, :len) ? len = options[:len] : len = length(keys(discretization)) diff --git a/src/const.jl b/src/const.jl index db601322..d45a0112 100644 --- a/src/const.jl +++ b/src/const.jl @@ -1,3 +1,14 @@ -const ALPINE_C_NLTERMS = [:BILINEAR, :MONOMIAL, :MULTILINEAR, :BININT, :BINLIN, :INTLIN, :BINPROD, :INTPROD, :cos, :sin] +const ALPINE_C_NLTERMS = [ + :BILINEAR, + :MONOMIAL, + :MULTILINEAR, + :BININT, + :BINLIN, + :INTLIN, + :BINPROD, + :INTPROD, + :cos, + :sin, +] const ALPINE_C_MONOMIAL = [:BILINEAR, :MONOMIAL, :MULTILINEAR] const ALPINE_C_TRIGONOMETRIC = [:sin, :cos] diff --git a/src/embedding.jl b/src/embedding.jl index f5e4eeeb..3fe0e79c 100644 --- a/src/embedding.jl +++ b/src/embedding.jl @@ -2,145 +2,180 @@ This function creates a mapping dictionary to link the right λ to the right bineary variables based on how many partitions are required and a given encoding method. """ -function embedding_map(λCnt::Int, encoding::Any=ebd_gray, ibs::Bool=false) - - map = Dict() - - encoding = Alp.resolve_encoding_key(encoding) - L = Int(ceil(log(2, λCnt-1))) - for i in 1:L*2 map[i]=Set() end - H = [encoding(i, L) for i in 0:max(1,(2^L-1))] - map[:H_orig] = H - map[:H] = [Alp.ebd_support_binary_vec(H[i]) for i in 1:length(H)] # Store the map - map[:L] = L - - !is_compatible_encoding(H) && error("Encodign method is not SOS-2 compatible...") - - # Mapping SOS-2 :: Aλ <= x && A'λ <= 1-x - # |x| = L : Flip 1 -> bCnt : bCnt + 1 -> bCnt + bCnt - J = Set(collect(1:(2^L+1))) - J_s = Set(collect(1:λCnt)) - for l in 1:L - if ibs - L_constr = Set() - R_constr = Set() - for j in 0:2^L - prod([(l in ebd_σ(H[i])) for i in ebd_I(j, 2^L+1)]) && push!(L_constr, j+1) - prod([!(l in ebd_σ(H[i])) for i in ebd_I(j, 2^L+1)]) && push!(R_constr, j+1) - end - L_branch = intersect(J_s, setdiff(J, L_constr)) - R_branch = intersect(J_s, setdiff(J, R_constr)) - map[l] = setdiff(J_s, L_branch) - map[l+L] = setdiff(J_s, R_branch) - else - for j in 0:(λCnt-1) - prod([(l in ebd_σ(H[i])) for i in ebd_I(j, λCnt)]) && push!(map[l], j+1) - prod([!(l in ebd_σ(H[i])) for i in ebd_I(j, λCnt)]) && push!(map[l+L], j+1) - end - end - end - - return map +function embedding_map(λCnt::Int, encoding::Any = ebd_gray, ibs::Bool = false) + map = Dict() + + encoding = Alp.resolve_encoding_key(encoding) + L = Int(ceil(log(2, λCnt - 1))) + for i in 1:L*2 + map[i] = Set() + end + H = [encoding(i, L) for i in 0:max(1, (2^L - 1))] + map[:H_orig] = H + map[:H] = [Alp.ebd_support_binary_vec(H[i]) for i in 1:length(H)] # Store the map + map[:L] = L + + !is_compatible_encoding(H) && error("Encodign method is not SOS-2 compatible...") + + # Mapping SOS-2 :: Aλ <= x && A'λ <= 1-x + # |x| = L : Flip 1 -> bCnt : bCnt + 1 -> bCnt + bCnt + J = Set(collect(1:(2^L+1))) + J_s = Set(collect(1:λCnt)) + for l in 1:L + if ibs + L_constr = Set() + R_constr = Set() + for j in 0:2^L + prod([(l in ebd_σ(H[i])) for i in ebd_I(j, 2^L + 1)]) && + push!(L_constr, j + 1) + prod([!(l in ebd_σ(H[i])) for i in ebd_I(j, 2^L + 1)]) && + push!(R_constr, j + 1) + end + L_branch = intersect(J_s, setdiff(J, L_constr)) + R_branch = intersect(J_s, setdiff(J, R_constr)) + map[l] = setdiff(J_s, L_branch) + map[l+L] = setdiff(J_s, R_branch) + else + for j in 0:(λCnt-1) + prod([(l in ebd_σ(H[i])) for i in ebd_I(j, λCnt)]) && push!(map[l], j + 1) + prod([!(l in ebd_σ(H[i])) for i in ebd_I(j, λCnt)]) && + push!(map[l+L], j + 1) + end + end + end + + return map end """ This function parse the encoding key string and return the built-in encoding function. """ function resolve_encoding_key(encoding::Any) - isa(encoding, Function) && return encoding - encoding == "default" && return ebd_gray - error("Must specify a encoding method when using convhull_ebd formulation") + isa(encoding, Function) && return encoding + encoding == "default" && return ebd_gray + return error("Must specify a encoding method when using convhull_ebd formulation") end """ This function is the same σ() function described in Vielma and Nemhauser 2011. """ function ebd_σ(b::String) - sv = Alp.ebd_support_bool_vec(b) - return [i for i in 1:length(sv) if sv[i]] + sv = Alp.ebd_support_bool_vec(b) + return [i for i in 1:length(sv) if sv[i]] end """ This function is the same I() function described in Vielma and Nemhauser 2011. """ function ebd_I(j, λCnt) - return [i for i in collect(1:Int((λCnt-1))) if j in [i-1, i]] #Page 52 + return [i for i in collect(1:Int((λCnt - 1))) if j in [i - 1, i]] #Page 52 end """ This function is the same S() function described in Vielma and Nemhauser 2011. """ function ebd_S(i) - (i <= 0) && error("Embedding utility S_[i] doesn't take i<=0") - return [i, i-1] + (i <= 0) && error("Embedding utility S_[i] doesn't take i<=0") + return [i, i - 1] end """ This function checks whether the encoding method is compatible or not to obtain a valid mapping. """ function is_compatible_encoding(code_seq::Vector) - for i in 1:(length(code_seq)-1) - sum(abs.(Alp.ebd_support_bool_vec(code_seq[i])-Alp.ebd_support_bool_vec(code_seq[i+1]))) != 1 && return false - end - return true + for i in 1:(length(code_seq)-1) + sum( + abs.( + Alp.ebd_support_bool_vec(code_seq[i]) - + Alp.ebd_support_bool_vec(code_seq[i+1]) + ), + ) != 1 && return false + end + return true end """ This is a utility function that convert the binary string into bool vector """ function ebd_support_bool_vec(s::String) - v = Vector{Bool}(undef, length(s)) - for i in 1:length(s) - s[i] == '1' ? v[i]=true : v[i]=false - end - return v + v = Vector{Bool}(undef, length(s)) + for i in 1:length(s) + s[i] == '1' ? v[i] = true : v[i] = false + end + return v end """ This is a utility function that convert the binary string into 0/1 vector """ function ebd_support_binary_vec(s::String) - v = Vector{Int}(undef, length(s)) - for i in 1:length(s) - s[i] == '1' ? v[i]=1 : v[i]=0 - end - return v + v = Vector{Int}(undef, length(s)) + for i in 1:length(s) + s[i] == '1' ? v[i] = 1 : v[i] = 0 + end + return v end """ This is the function that translate the bounding constraints (α¹b⁰+α²b¹ <= x <= α¹b¹+α²b²) with log # of binary variables, i.e., generate these constraints using log # of binary variables. """ -function ebd_link_xα(m::Optimizer, α::Vector, λCnt::Int, disc_vec::Vector, code_seq::Vector, var_idx::Int) - - lifters = Dict() - exprs = Dict() - L = Int(ceil(log(2, λCnt-1))) - P = length(disc_vec) - 1 - - # Expression expansion - for i in 1:P - code_vec = Alp.ebd_support_bool_vec(code_seq[i]) - lifters, exprs = Alp.ebd_link_expression(code_vec, lifters, exprs, i) - end - - # Construct Variable Vector - α_A = JuMP.@variable(m.model_mip, [1:length(keys(lifters))], lower_bound=0.0, upper_bound=1.0, base_name="αA$(var_idx)") - for i in keys(lifters) # Build first-level evaluation - Alp.binprod_relax(m.model_mip, α_A[lifters[i]-L], [α[j] for j in i]) - end +function ebd_link_xα( + m::Optimizer, + α::Vector, + λCnt::Int, + disc_vec::Vector, + code_seq::Vector, + var_idx::Int, +) + lifters = Dict() + exprs = Dict() + L = Int(ceil(log(2, λCnt - 1))) + P = length(disc_vec) - 1 + + # Expression expansion + for i in 1:P + code_vec = Alp.ebd_support_bool_vec(code_seq[i]) + lifters, exprs = Alp.ebd_link_expression(code_vec, lifters, exprs, i) + end - α_R = [α; α_A] # Initialize/re-arrgange the variable sequence + # Construct Variable Vector + α_A = JuMP.@variable( + m.model_mip, + [1:length(keys(lifters))], + lower_bound = 0.0, + upper_bound = 1.0, + base_name = "αA$(var_idx)" + ) + for i in keys(lifters) # Build first-level evaluation + Alp.binprod_relax(m.model_mip, α_A[lifters[i]-L], [α[j] for j in i]) + end - for i in 1:P # Start populating sub-expressions - exprs[i][:expr] = JuMP.@expression(m.model_mip, sum(exprs[i][:coefs][j]*α_R[exprs[i][:vars][j]] for j in 1:exprs[i][:length] if exprs[i][:vars][j] != 0) + exprs[i][:vals]) - end + α_R = [α; α_A] # Initialize/re-arrgange the variable sequence - # Contructing final constraints - JuMP.@constraint(m.model_mip, _index_to_variable_ref(m.model_mip, var_idx) >= sum(exprs[j][:expr]*disc_vec[j] for j in 1:P)) - JuMP.@constraint(m.model_mip, _index_to_variable_ref(m.model_mip, var_idx) <= sum(exprs[j-1][:expr]*disc_vec[j] for j in 2:(P+1))) + for i in 1:P # Start populating sub-expressions + exprs[i][:expr] = JuMP.@expression( + m.model_mip, + sum( + exprs[i][:coefs][j] * α_R[exprs[i][:vars][j]] for + j in 1:exprs[i][:length] if exprs[i][:vars][j] != 0 + ) + exprs[i][:vals] + ) + end - return + # Contructing final constraints + JuMP.@constraint( + m.model_mip, + _index_to_variable_ref(m.model_mip, var_idx) >= + sum(exprs[j][:expr] * disc_vec[j] for j in 1:P) + ) + JuMP.@constraint( + m.model_mip, + _index_to_variable_ref(m.model_mip, var_idx) <= + sum(exprs[j-1][:expr] * disc_vec[j] for j in 2:(P+1)) + ) + + return end """ @@ -148,8 +183,7 @@ end combinations of binary variables. """ function ebd_link_expression(code::Vector, lift_dict::Dict, link_dict::Dict, p_idx::Int) - - L = length(code) + L = length(code) # Strickly mapping p_idx -> x code[1] ? coefs = Any[1] : coefs = Any[1, -1] @@ -158,7 +192,7 @@ function ebd_link_expression(code::Vector, lift_dict::Dict, link_dict::Dict, p_i for i in 2:L if code[i] - for j in 1:length(coefs) + for j in 1:length(coefs) (vars[j] == 0) ? vars[j] = i : vars[j] = [vars[j]; i] # Update vars @assert length(vars) == length(coefs) end @@ -174,13 +208,20 @@ function ebd_link_expression(code::Vector, lift_dict::Dict, link_dict::Dict, p_i # Maintaining the dictionary of lifted variables and swp for i in 1:length(vars) if isa(vars[i], Vector) - !haskey(lift_dict, vars[i]) && (lift_dict[vars[i]] = L + length(keys(lift_dict)) + 1) + !haskey(lift_dict, vars[i]) && + (lift_dict[vars[i]] = L + length(keys(lift_dict)) + 1) vars[i] = lift_dict[vars[i]] end end # Maintain the expression dictionary - link_dict[p_idx] = Dict(:p_idx=>p_idx, :coefs=>coefs, :vars=>vars, :vals=>vals, :length=>length(coefs)) + link_dict[p_idx] = Dict( + :p_idx => p_idx, + :coefs => coefs, + :vars => vars, + :vals => vals, + :length => length(coefs), + ) return lift_dict, link_dict end @@ -189,13 +230,13 @@ end Built-in Encoding methods: binary encoding This is a compatible encoding """ -ebd_binary(n, idx) = string(n, base=2, pad=idx) +ebd_binary(n, idx) = string(n, base = 2, pad = idx) """ Built-in Encoding methods: gray encoding This is a compatible encoding """ function ebd_gray(n, idx) - code_decimal = xor(n, n >> 1) - return string(code_decimal, base=2, pad=idx) + code_decimal = xor(n, n >> 1) + return string(code_decimal, base = 2, pad = idx) end diff --git a/src/heuristics.jl b/src/heuristics.jl index 33515abc..9713c049 100644 --- a/src/heuristics.jl +++ b/src/heuristics.jl @@ -4,7 +4,6 @@ Currently doesn't support recursive convexification """ function update_disc_cont_var(m::Optimizer) - length(m.candidate_disc_vars) <= 15 && return # Algorithm Separation Point # If no feasible solution is found, do NOT update @@ -13,8 +12,11 @@ function update_disc_cont_var(m::Optimizer) return end - var_idxs = copy(m.candidate_disc_vars) - var_diffs = Vector{Float64}(undef, m.num_var_orig+length(keys(m.linear_terms))+length(keys(m.nonconvex_terms))) + var_idxs = copy(m.candidate_disc_vars) + var_diffs = Vector{Float64}( + undef, + m.num_var_orig + length(keys(m.linear_terms)) + length(keys(m.nonconvex_terms)), + ) for i in 1:m.num_var_orig # Original Variables var_diffs[i] = abs(m.best_sol[i] - m.best_bound_sol[i]) @@ -23,7 +25,8 @@ function update_disc_cont_var(m::Optimizer) for i in 1:length(keys(m.linear_terms)) for j in keys(m.linear_terms) # sequential evaluation to avoid dependency issue if m.linear_terms[j][:id] == i - var_diffs[m.linear_terms[j][:lifted_var_ref].args[2]] = m.linear_terms[j][:evaluator](m.linear_terms[j], var_diffs) + var_diffs[m.linear_terms[j][:lifted_var_ref].args[2]] = + m.linear_terms[j][:evaluator](m.linear_terms[j], var_diffs) end end end @@ -31,24 +34,27 @@ function update_disc_cont_var(m::Optimizer) for i in 1:length(keys(m.nonconvex_terms)) for j in keys(m.nonconvex_terms) # sequential evaluation to avoid dependency issue if m.nonconvex_terms[j][:id] == i - var_diffs[m.nonconvex_terms[j][:lifted_var_ref].args[2]] = m.nonconvex_terms[j][:evaluator](m.nonconvex_terms[j], var_diffs) + var_diffs[m.nonconvex_terms[j][:lifted_var_ref].args[2]] = + m.nonconvex_terms[j][:evaluator](m.nonconvex_terms[j], var_diffs) end end end - distance = Dict(zip(var_idxs,var_diffs)) + distance = Dict(zip(var_idxs, var_diffs)) Alp.weighted_min_vertex_cover(m, distance) - (Alp.get_option(m, :log_level) > 100) && println("updated partition var selection => $(m.disc_vars)") + (Alp.get_option(m, :log_level) > 100) && + println("updated partition var selection => $(m.disc_vars)") return end function update_disc_int_var(m::Optimizer) - length(m.candidate_disc_vars) <= 15 && return # Algorithm Separation Point # Additional error checking scheme - :Int in m.var_type && error("Alpine does not support MINLPs with geenric integer (non-binary) variables yet! Try Juniper.jl for finding a local feasible solution") + :Int in m.var_type && error( + "Alpine does not support MINLPs with geenric integer (non-binary) variables yet! Try Juniper.jl for finding a local feasible solution", + ) return end @@ -57,7 +63,6 @@ end Use solutions from the MIP solution pool as starting points """ function heu_pool_multistart(m::Optimizer) - convertor = Dict(MOI.MAX_SENSE => :>, MOI.MIN_SENSE => :<) Alp.is_min_sense(m) ? incumb_obj = Inf : incumb_obj = -Inf incumb_sol = [] @@ -65,25 +70,33 @@ function heu_pool_multistart(m::Optimizer) for i in 1:m.bound_sol_pool[:cnt] if !m.bound_sol_pool[:ubstart][i] - rounded_sol = Alp.round_sol(m, m.bound_sol_pool[:sol][i]) - l_var, u_var = Alp.fix_domains(m, discrete_sol=rounded_sol, use_orig=true) - heuristic_model = MOI.instantiate(Alp.get_option(m, :nlp_solver), with_bridge_type=Float64) + l_var, u_var = Alp.fix_domains(m, discrete_sol = rounded_sol, use_orig = true) + heuristic_model = MOI.instantiate( + Alp.get_option(m, :nlp_solver), + with_bridge_type = Float64, + ) x = Alp.load_nonlinear_model(m, heuristic_model, l_var, u_var) - + MOI.optimize!(heuristic_model) heuristic_model_status = MOI.get(heuristic_model, MOI.TerminationStatus()) - if heuristic_model_status in STATUS_OPT || heuristic_model_status in STATUS_LIMIT + if heuristic_model_status in STATUS_OPT || + heuristic_model_status in STATUS_LIMIT candidate_obj = MOI.get(heuristic_model, MOI.ObjectiveValue()) if eval(convertor[m.sense_orig])(candidate_obj, incumb_obj) incumb_obj = candidate_obj - incumb_sol = round.(MOI.get(heuristic_model, MOI.VariablePrimal(), x), 5) - Alp.get_option(m, :log_level) > 0 && println("Feasible solution obtained using lower bound solution pool [SOL:$(i)] [OBJ=$(incumb_obj)]") + incumb_sol = + round.(MOI.get(heuristic_model, MOI.VariablePrimal(), x), 5) + Alp.get_option(m, :log_level) > 0 && println( + "Feasible solution obtained using lower bound solution pool [SOL:$(i)] [OBJ=$(incumb_obj)]", + ) end found_feasible = true else - Alp.get_option(m, :log_level) > 99 && println("Multi-start heuristic returns $(heuristic_model_status) [SOL:$(i)]") + Alp.get_option(m, :log_level) > 99 && println( + "Multi-start heuristic returns $(heuristic_model_status) [SOL:$(i)]", + ) end m.bound_sol_pool[:ubstart][i] = true end @@ -97,7 +110,6 @@ function heu_pool_multistart(m::Optimizer) return MOI.LOCALLY_INFEASIBLE end - #-----------------------------------------------------------------# # UNSUPPORTED FUNCTIONS # #-----------------------------------------------------------------# @@ -135,4 +147,4 @@ end # end # return -# end \ No newline at end of file +# end diff --git a/src/linking.jl b/src/linking.jl index ef680ac9..3928956e 100644 --- a/src/linking.jl +++ b/src/linking.jl @@ -5,7 +5,7 @@ function add_linking_constraints(m::Optimizer, λ::Dict) Reference information: Jongeun Kim, Jean-Philippe P. Richard, Mohit Tawarmalani, Piecewise Polyhedral Relaxations of Multilinear Optimization, http://www.optimization-online.org/DB_HTML/2022/07/8974.html - + For example, suppose we have λ[i], λ[j], and λ[k] where i=(1,2,3), j=(1,2,4), and k=(1,2,5). λ[i] contains all multipliers for the extreme points in the space of (x1,x2,x3). λ[j] contains all multipliers for the extreme points in the space of (x1,x2,x4). @@ -31,22 +31,26 @@ function add_linking_constraints(m::Optimizer, λ::Dict) maxdeg = maximum([length(k) for k in keys(λ)]) # Compute maximum degree of multilinear terms if maxdeg <= 2 # @info "no linking constraint is added because the maximum degree of multilinear term is $(maxdeg)." - return + return end all_vars_idx = sort(collect(union(collect(keys(λ))...))) # Collect all variable indices used in multilinear terms - link_info = Dict(link_var_idx=>filter(r->issubset(link_var_idx, r), keys(λ)) - for deg in 2:maxdeg-1 for link_var_idx in Combinatorics.combinations(all_vars_idx, deg)) + link_info = Dict( + link_var_idx => filter(r -> issubset(link_var_idx, r), keys(λ)) for + deg in 2:maxdeg-1 for + link_var_idx in Combinatorics.combinations(all_vars_idx, deg) + ) filter!(r -> length(r.second) >= 2, link_info) if isempty(link_info) # @info "no linking constraint is added because there is no multilinear terms that shaer more than two variables." return - end + end # (Step 2) Add linking (decision) variables to the mip model link_vars = @variable(m.model_mip, [collect(keys(link_info))]) - + # (Step 3) Add linking constraints to the mip model - for (link_var_idx, list_multi_idx) in link_info, (i, multi_idx) in enumerate(list_multi_idx) + for (link_var_idx, list_multi_idx) in link_info, + (i, multi_idx) in enumerate(list_multi_idx) # Define `linkidx2multiidx` to know where `link_var_idx` and `list_multi_idx` have the same value. # `linkidx2multiidx` satisfies that link_var_idx[i] = list_multi_idx[linkidx2multiidx[i]] for all i. # By the definition of `link_info`, it always holds that issubset(link_var_idx, list_multi_idx). @@ -56,13 +60,16 @@ function add_linking_constraints(m::Optimizer, λ::Dict) expr = 0 for idx in Iterators.product([1:d for d in λ[multi_idx][:dim]]...) var = λ[multi_idx][:vars][λ[multi_idx][:indices][idx...]] - func_value = prod(m.discretization[i][idx[j]] for (i,j) in zip(link_var_idx, linkidx2multiidx)) + func_value = prod( + m.discretization[i][idx[j]] for + (i, j) in zip(link_var_idx, linkidx2multiidx) + ) expr += func_value * var - end + end @constraint(m.model_mip, link_vars[link_var_idx] == expr) num_added_constraints += 1 end # @info "$num_added_constraints linking constraints are added in $(time() - t_begin) seconds." -end \ No newline at end of file +end diff --git a/src/log.jl b/src/log.jl index 1630167c..f7a68df0 100644 --- a/src/log.jl +++ b/src/log.jl @@ -1,171 +1,224 @@ # Create dictionary of logs for timing and iteration counts function create_logs!(m) + logs = Dict{Symbol,Any}() - logs = Dict{Symbol,Any}() + # Timers + logs[:presolve_time] = 0.0 # Total presolve-time of the algorithm + logs[:total_time] = 0.0 # Total run-time of the algorithm + logs[:time_left] = Alp.get_option(m, :time_limit) # Total remaining time of the algorithm if time-out is specified - # Timers - logs[:presolve_time] = 0. # Total presolve-time of the algorithm - logs[:total_time] = 0. # Total run-time of the algorithm - logs[:time_left] = Alp.get_option(m, :time_limit) # Total remaining time of the algorithm if time-out is specified + # Values + logs[:obj] = [] # Iteration-based objective + logs[:bound] = [] # Iteration-based objective bound - # Values - logs[:obj] = [] # Iteration-based objective - logs[:bound] = [] # Iteration-based objective bound + # Counters + logs[:n_iter] = 0 # Number of iterations + logs[:n_feas] = 0 # Number of times a new feasible solution is obtained + logs[:ub_incumb_cnt] = 0 # Number of incumbents detected in the upper bound + logs[:lb_incumb_cnt] = 0 # Number of incumebnts detected in the lower bound + logs[:bt_iter] = 0 - # Counters - logs[:n_iter] = 0 # Number of iterations - logs[:n_feas] = 0 # Number of times a new feasible solution is obtained - logs[:ub_incumb_cnt] = 0 # Number of incumbents detected in the upper bound - logs[:lb_incumb_cnt] = 0 # Number of incumebnts detected in the lower bound - logs[:bt_iter] = 0 - - m.logs = logs + return m.logs = logs end function reset_timer(m::Optimizer) - m.logs[:total_time] = 0. - m.logs[:time_left] = Alp.get_option(m, :time_limit) - return m + m.logs[:total_time] = 0.0 + m.logs[:time_left] = Alp.get_option(m, :time_limit) + return m end function logging_summary(m::Optimizer) - if Alp.get_option(m, :log_level) > 0 - printstyled("\nPROBLEM STATISTICS\n", color=:cyan) - Alp.is_min_sense(m) && (println(" Objective sense = Min", )) - Alp.is_max_sense(m) && (println(" Objective sense = Max", )) - println(" # Variables = ", length([i for i in 1:m.num_var_orig if m.var_type[i] == :Cont]) + length([i for i in 1:m.num_var_orig if m.var_type[i] == :Bin]) + length([i for i in 1:m.num_var_orig if m.var_type[i] == :Int])) - println(" # Bin-Int Variables = ", length([i for i in 1:m.num_var_orig if m.var_type[i] == :Bin]) + length([i for i in 1:m.num_var_orig if m.var_type[i] == :Int])) - println(" # Constraints = ", m.num_constr_orig) - println(" # NL Constraints = ", m.num_nlconstr_orig) - println(" # Linear Constraints = ", m.num_lconstr_orig) - Alp.get_option(m, :recognize_convex) && println(" # Detected convex constraints = $(length([i for i in m.constr_structure if i == :convex]))") - println(" # Detected nonlinear terms = ", length(m.nonconvex_terms)) - println(" # Variables involved in nonlinear terms = ", length(m.candidate_disc_vars)) - println(" # Potential variables for partitioning = ", length(m.disc_vars)) - - printstyled("SUB-SOLVERS USED BY ALPINE\n", color=:cyan) - if Alp.get_option(m, :minlp_solver) === nothing - println(" NLP local solver = ", m.nlp_solver_id) - else - println(" MINLP local solver = ", m.minlp_solver_id) - end - println(" MIP solver = ", m.mip_solver_id) - - printstyled("ALPINE CONFIGURATION\n", color=:cyan) - if Alp.is_min_sense(m) - println(" Maximum iterations (lower-bounding MIPs) = ", Alp.get_option(m, :max_iter)) - elseif Alp.is_max_sense(m) - println(" Maximum iterations (upper-bounding MIPs) = ", Alp.get_option(m, :max_iter)) - else - println(" Maximum iterations (bounding MIPs) = ", Alp.get_option(m, :max_iter)) - end - - println(" Relative global optimality gap = ", Alp.get_option(m, :rel_gap)*100, "%") - - if Alp.get_option(m, :disc_var_pick) == 0 - println(" Potential variables chosen for partitioning = All") - elseif Alp.get_option(m, :disc_var_pick) == 1 - println(" Potential variables chosen for partitioning = Minimum vertex cover") - end - - - if Alp.get_option(m, :disc_ratio_branch) - println(" Discretization ratio branch activated") - else - println(" Discretization ratio = ", Alp.get_option(m, :disc_ratio)) - end - (Alp.get_option(m, :convhull_ebd)) && println(" Using convhull_ebd formulation") - (Alp.get_option(m, :convhull_ebd)) && println(" Encoding method = $(Alp.get_option(m, :convhull_ebd_encode))") - (Alp.get_option(m, :convhull_ebd)) && println(" Independent branching scheme = $(Alp.get_option(m, :convhull_ebd_ibs))") - println(" Bound-tightening presolve = ", Alp.get_option(m, :presolve_bt)) - Alp.get_option(m, :presolve_bt) && println(" Maximum iterations (OBBT) = ", Alp.get_option(m, :presolve_bt_max_iter)) - end - + printstyled("\nPROBLEM STATISTICS\n", color = :cyan) + Alp.is_min_sense(m) && (println(" Objective sense = Min")) + Alp.is_max_sense(m) && (println(" Objective sense = Max")) + println( + " # Variables = ", + length([i for i in 1:m.num_var_orig if m.var_type[i] == :Cont]) + + length([i for i in 1:m.num_var_orig if m.var_type[i] == :Bin]) + + length([i for i in 1:m.num_var_orig if m.var_type[i] == :Int]), + ) + println( + " # Bin-Int Variables = ", + length([i for i in 1:m.num_var_orig if m.var_type[i] == :Bin]) + + length([i for i in 1:m.num_var_orig if m.var_type[i] == :Int]), + ) + println(" # Constraints = ", m.num_constr_orig) + println(" # NL Constraints = ", m.num_nlconstr_orig) + println(" # Linear Constraints = ", m.num_lconstr_orig) + Alp.get_option(m, :recognize_convex) && println( + " # Detected convex constraints = $(length([i for i in m.constr_structure if i == :convex]))", + ) + println(" # Detected nonlinear terms = ", length(m.nonconvex_terms)) + println( + " # Variables involved in nonlinear terms = ", + length(m.candidate_disc_vars), + ) + println(" # Potential variables for partitioning = ", length(m.disc_vars)) + + printstyled("SUB-SOLVERS USED BY ALPINE\n", color = :cyan) + if Alp.get_option(m, :minlp_solver) === nothing + println(" NLP local solver = ", m.nlp_solver_id) + else + println(" MINLP local solver = ", m.minlp_solver_id) + end + println(" MIP solver = ", m.mip_solver_id) + + printstyled("ALPINE CONFIGURATION\n", color = :cyan) + if Alp.is_min_sense(m) + println( + " Maximum iterations (lower-bounding MIPs) = ", + Alp.get_option(m, :max_iter), + ) + elseif Alp.is_max_sense(m) + println( + " Maximum iterations (upper-bounding MIPs) = ", + Alp.get_option(m, :max_iter), + ) + else + println( + " Maximum iterations (bounding MIPs) = ", + Alp.get_option(m, :max_iter), + ) + end + + println( + " Relative global optimality gap = ", + Alp.get_option(m, :rel_gap) * 100, + "%", + ) + + if Alp.get_option(m, :disc_var_pick) == 0 + println(" Potential variables chosen for partitioning = All") + elseif Alp.get_option(m, :disc_var_pick) == 1 + println( + " Potential variables chosen for partitioning = Minimum vertex cover", + ) + end + + if Alp.get_option(m, :disc_ratio_branch) + println(" Discretization ratio branch activated") + else + println(" Discretization ratio = ", Alp.get_option(m, :disc_ratio)) + end + (Alp.get_option(m, :convhull_ebd)) && println(" Using convhull_ebd formulation") + (Alp.get_option(m, :convhull_ebd)) && + println(" Encoding method = $(Alp.get_option(m, :convhull_ebd_encode))") + (Alp.get_option(m, :convhull_ebd)) && println( + " Independent branching scheme = $(Alp.get_option(m, :convhull_ebd_ibs))", + ) + println(" Bound-tightening presolve = ", Alp.get_option(m, :presolve_bt)) + Alp.get_option(m, :presolve_bt) && println( + " Maximum iterations (OBBT) = ", + Alp.get_option(m, :presolve_bt_max_iter), + ) + end end function logging_head(m::Optimizer) - if Alp.is_min_sense(m) - printstyled("LOWER-BOUNDING ITERATIONS", color=:cyan) - UB_iter = "Incumbent" - UB = "Best Incumbent" - LB = "Lower Bound" - elseif Alp.is_max_sense(m) - printstyled("UPPER-BOUNDING ITERATIONS", color=:cyan) - UB_iter = "Incumbent" - UB = "Best Incumbent" - LB = "Upper Bound" - end - println("\n====================================================================================================") - if m.logs[:time_left] < Inf - printstyled(bold=true, "| Iter | $UB_iter | $UB | $LB | Gap (%) | Time \n") - end + if Alp.is_min_sense(m) + printstyled("LOWER-BOUNDING ITERATIONS", color = :cyan) + UB_iter = "Incumbent" + UB = "Best Incumbent" + LB = "Lower Bound" + elseif Alp.is_max_sense(m) + printstyled("UPPER-BOUNDING ITERATIONS", color = :cyan) + UB_iter = "Incumbent" + UB = "Best Incumbent" + LB = "Upper Bound" + end + println( + "\n====================================================================================================", + ) + if m.logs[:time_left] < Inf + printstyled( + bold = true, + "| Iter | $UB_iter | $UB | $LB | Gap (%) | Time \n", + ) + end end function logging_row_entry(m::Optimizer; kwargs...) - - options = Dict(kwargs) - - b_len = 16 - if !isempty(m.logs[:obj]) && isa(m.logs[:obj][end], Float64) - objstr = string(round(m.logs[:obj][end]; digits=4)) - spc = max(0, b_len - length(objstr)) - else - objstr = string("-") - spc = max(0, b_len - length(objstr)) - end - UB_block = string(" ", objstr, " " ^ spc) - - if expr_isconst(m.obj_expr_orig) - bdstr = eval(m.obj_expr_orig) - spc = b_len - length(bdstr) - elseif isa(m.logs[:bound][end], Float64) - bdstr = string(round(m.logs[:bound][end]; digits=4)) - spc = max(0, b_len - length(bdstr)) - else - bdstr = string(m.logs[:bound][end]) - spc = b_len - length(bdstr) - end - LB_block = string(" ", bdstr, " " ^ spc) - - bobjstr = string(round(m.best_obj; digits=4)) - spc = max(0, b_len+4 - length(bobjstr)) - incumb_UB_block = string(" ", bobjstr, " " ^ spc) - - bbdstr = string(round(m.best_bound; digits=4)) - spc = max(0, b_len+3 - length(bbdstr)) - incumb_LB_block = string(" ", bbdstr , " " ^ spc) - - rel_gap = round(m.best_rel_gap*100, digits=3) - rel_gap > 999 ? rel_gap = "LARGE" : rel_gap = string(rel_gap) - GAP_block = string(" ", rel_gap, " " ^ (b_len - length(rel_gap))) - - UTIME_block = string(" ", round(m.logs[:total_time]; digits=2), "s", " " ^ (b_len - 1 - length(string(round(m.logs[:total_time]; digits=2))))) - - if m.logs[:time_left] < Inf - LTIME_block = " " - end - - haskey(options, :finish_entry) ? (ITER_block = string(" ", "finish ")) : (ITER_block = string(" ", m.logs[:n_iter]," " ^ (7 - length(string(m.logs[:n_iter]))))) - - println("|",ITER_block,"|",UB_block,"|",incumb_UB_block,"|",incumb_LB_block,"|",GAP_block,"|",UTIME_block,LTIME_block) - return + options = Dict(kwargs) + + b_len = 16 + if !isempty(m.logs[:obj]) && isa(m.logs[:obj][end], Float64) + objstr = string(round(m.logs[:obj][end]; digits = 4)) + spc = max(0, b_len - length(objstr)) + else + objstr = string("-") + spc = max(0, b_len - length(objstr)) + end + UB_block = string(" ", objstr, " "^spc) + + if expr_isconst(m.obj_expr_orig) + bdstr = eval(m.obj_expr_orig) + spc = b_len - length(bdstr) + elseif isa(m.logs[:bound][end], Float64) + bdstr = string(round(m.logs[:bound][end]; digits = 4)) + spc = max(0, b_len - length(bdstr)) + else + bdstr = string(m.logs[:bound][end]) + spc = b_len - length(bdstr) + end + LB_block = string(" ", bdstr, " "^spc) + + bobjstr = string(round(m.best_obj; digits = 4)) + spc = max(0, b_len + 4 - length(bobjstr)) + incumb_UB_block = string(" ", bobjstr, " "^spc) + + bbdstr = string(round(m.best_bound; digits = 4)) + spc = max(0, b_len + 3 - length(bbdstr)) + incumb_LB_block = string(" ", bbdstr, " "^spc) + + rel_gap = round(m.best_rel_gap * 100, digits = 3) + rel_gap > 999 ? rel_gap = "LARGE" : rel_gap = string(rel_gap) + GAP_block = string(" ", rel_gap, " "^(b_len - length(rel_gap))) + + UTIME_block = string( + " ", + round(m.logs[:total_time]; digits = 2), + "s", + " "^(b_len - 1 - length(string(round(m.logs[:total_time]; digits = 2)))), + ) + + if m.logs[:time_left] < Inf + LTIME_block = " " + end + + haskey(options, :finish_entry) ? (ITER_block = string(" ", "finish ")) : + (ITER_block = string(" ", m.logs[:n_iter], " "^(7 - length(string(m.logs[:n_iter]))))) + + println( + "|", + ITER_block, + "|", + UB_block, + "|", + incumb_UB_block, + "|", + incumb_LB_block, + "|", + GAP_block, + "|", + UTIME_block, + LTIME_block, + ) + return end - #Logging and printing functions # Create dictionary of statuses for Alpine algorithm function create_status!(m) + status = Dict{Symbol,MOI.TerminationStatusCode}() - status = Dict{Symbol,MOI.TerminationStatusCode}() - - status[:local_solve] = MOI.OPTIMIZE_NOT_CALLED # Status of local solve - status[:bounding_solve] = MOI.OPTIMIZE_NOT_CALLED # Status of bounding solve - m.detected_feasible_solution = false - m.detected_bound = false + status[:local_solve] = MOI.OPTIMIZE_NOT_CALLED # Status of local solve + status[:bounding_solve] = MOI.OPTIMIZE_NOT_CALLED # Status of bounding solve + m.detected_feasible_solution = false + m.detected_bound = false - m.status = status + return m.status = status end """ @@ -175,43 +228,44 @@ read our documentation to understand the details behind every status symbols. """ function summary_status(m::Optimizer) - # Alpine Solver Status Definition - # :Optimal : normal termination with optimality gap closed within time limits - # :UserLimits : any non-optimal termination related to user-defined parameters - # :Infeasible : termination with relaxation proven infeasible or detection of - # variable bound conflicts - # :Heuristic : termination with feasible solution found but not bounds detected - # happens when lower bound problem is extremely hard to solve - # :Unknown : termination with no exception recorded - - if m.detected_bound && m.detected_feasible_solution - m.alpine_status = m.best_rel_gap > Alp.get_option(m, :rel_gap) ? MOI.OTHER_LIMIT : MOI.OPTIMAL - elseif m.status[:bounding_solve] == MOI.INFEASIBLE - m.alpine_status = MOI.INFEASIBLE - elseif m.detected_bound && !m.detected_feasible_solution - m.alpine_status = MOI.OTHER_LIMIT - elseif !m.detected_bound && m.detected_feasible_solution - m.alpine_status = MOI.LOCALLY_SOLVED - else - @warn " [EXCEPTION] Indefinite Alpine status. Please report your instance (& solver configuration) as an issue (https://github.com/lanl-ansi/Alpine.jl/issues) to help us make Alpine better." - end - - printstyled("\n*** Alpine ended with status $(m.alpine_status) ***\n") - - return + # Alpine Solver Status Definition + # :Optimal : normal termination with optimality gap closed within time limits + # :UserLimits : any non-optimal termination related to user-defined parameters + # :Infeasible : termination with relaxation proven infeasible or detection of + # variable bound conflicts + # :Heuristic : termination with feasible solution found but not bounds detected + # happens when lower bound problem is extremely hard to solve + # :Unknown : termination with no exception recorded + + if m.detected_bound && m.detected_feasible_solution + m.alpine_status = + m.best_rel_gap > Alp.get_option(m, :rel_gap) ? MOI.OTHER_LIMIT : MOI.OPTIMAL + elseif m.status[:bounding_solve] == MOI.INFEASIBLE + m.alpine_status = MOI.INFEASIBLE + elseif m.detected_bound && !m.detected_feasible_solution + m.alpine_status = MOI.OTHER_LIMIT + elseif !m.detected_bound && m.detected_feasible_solution + m.alpine_status = MOI.LOCALLY_SOLVED + else + @warn " [EXCEPTION] Indefinite Alpine status. Please report your instance (& solver configuration) as an issue (https://github.com/lanl-ansi/Alpine.jl/issues) to help us make Alpine better." + end + + printstyled("\n*** Alpine ended with status $(m.alpine_status) ***\n") + + return end # Some useful logging details: - # for i in ALPINE_C_NLTERMS - # cnt = length([1 for j in keys(m.nonconvex_terms) if m.nonconvex_terms[j][:nonlinear_type] == i]) - # cnt > 0 && println("\tTerm $(i) Count = $(cnt) ") - # end - # println(" Maximum solution time = ", Alp.get_option(m, :time_limit)) - # println(" Basic bound propagation = ", Alp.get_option(m, :presolve_bp)) - # println(" Conseuctive solution rejection = after ", Alp.get_option(m, :disc_consecutive_forbid), " times") - # Alp.get_option(m, :presolve_bt) && println("bound tightening presolve algorithm = ", Alp.get_option(m, :presolve_bt)_algo) - # Alp.get_option(m, :presolve_bt) && println("bound tightening presolve width tolerance = ", Alp.get_option(m, :presolve_bt)_width_tol) - # Alp.get_option(m, :presolve_bt) && println("bound tightening presolve output tolerance = ", Alp.get_option(m, :presolve_bt)_output_tol) - # Alp.get_option(m, :presolve_bt) && println("bound tightening presolve relaxation = ", Alp.get_option(m, :presolve_bt)_relax) - # Alp.get_option(m, :presolve_bt) && println("bound tightening presolve mip regulation time = ", Alp.get_option(m, :presolve_bt)_mip_time_limit) +# for i in ALPINE_C_NLTERMS +# cnt = length([1 for j in keys(m.nonconvex_terms) if m.nonconvex_terms[j][:nonlinear_type] == i]) +# cnt > 0 && println("\tTerm $(i) Count = $(cnt) ") +# end +# println(" Maximum solution time = ", Alp.get_option(m, :time_limit)) +# println(" Basic bound propagation = ", Alp.get_option(m, :presolve_bp)) +# println(" Conseuctive solution rejection = after ", Alp.get_option(m, :disc_consecutive_forbid), " times") +# Alp.get_option(m, :presolve_bt) && println("bound tightening presolve algorithm = ", Alp.get_option(m, :presolve_bt)_algo) +# Alp.get_option(m, :presolve_bt) && println("bound tightening presolve width tolerance = ", Alp.get_option(m, :presolve_bt)_width_tol) +# Alp.get_option(m, :presolve_bt) && println("bound tightening presolve output tolerance = ", Alp.get_option(m, :presolve_bt)_output_tol) +# Alp.get_option(m, :presolve_bt) && println("bound tightening presolve relaxation = ", Alp.get_option(m, :presolve_bt)_relax) +# Alp.get_option(m, :presolve_bt) && println("bound tightening presolve mip regulation time = ", Alp.get_option(m, :presolve_bt)_mip_time_limit) diff --git a/src/multi.jl b/src/multi.jl index ff598888..a4550bc3 100644 --- a/src/multi.jl +++ b/src/multi.jl @@ -1,5 +1,4 @@ function amp_post_convhull(m::Optimizer; kwargs...) - options = Dict(kwargs) haskey(options, :use_disc) ? d = options[:use_disc] : d = m.discretization @@ -11,7 +10,8 @@ function amp_post_convhull(m::Optimizer; kwargs...) # Convexification Treatment for Complex Non-Convex Terms for k in keys(m.nonconvex_terms) nl_type = m.nonconvex_terms[k][:nonlinear_type] - if ((nl_type == :MULTILINEAR) || (nl_type == :BILINEAR)) && (m.nonconvex_terms[k][:convexified] == false) + if ((nl_type == :MULTILINEAR) || (nl_type == :BILINEAR)) && + (m.nonconvex_terms[k][:convexified] == false) λ, α = Alp.amp_convexify_multilinear(m, k, λ, α, d) elseif nl_type == :MONOMIAL && !m.nonconvex_terms[k][:convexified] λ, α = Alp.amp_convexify_monomial(m, k, λ, α, d) @@ -36,29 +36,57 @@ function amp_post_convhull(m::Optimizer; kwargs...) end # Experimental code for Warm starting - Alp.get_option(m, :convhull_warmstart) && !isempty(m.best_bound_sol) && Alp.amp_warmstart_α(m, α) + Alp.get_option(m, :convhull_warmstart) && + !isempty(m.best_bound_sol) && + Alp.amp_warmstart_α(m, α) return end -function amp_convexify_multilinear(m::Optimizer, k::Any, λ::Dict, α::Dict, discretization::Dict) - +function amp_convexify_multilinear( + m::Optimizer, + k::Any, + λ::Dict, + α::Dict, + discretization::Dict, +) m.nonconvex_terms[k][:convexified] = true # Bookeeping the convexified terms ml_indices, dim, extreme_point_cnt = Alp.amp_convhull_prepare(m, discretization, k) # convert key to easy read mode λ = Alp.amp_convhull_λ(m, k, ml_indices, λ, extreme_point_cnt, dim) - λ = Alp.populate_convhull_extreme_values(m, discretization, ml_indices, λ, dim, ones(Int,length(dim))) + λ = Alp.populate_convhull_extreme_values( + m, + discretization, + ml_indices, + λ, + dim, + ones(Int, length(dim)), + ) α = Alp.amp_convhull_α(m, ml_indices, α, dim, discretization) - Alp.amp_post_convhull_constrs(m, λ, α, ml_indices, dim, extreme_point_cnt, discretization) + Alp.amp_post_convhull_constrs( + m, + λ, + α, + ml_indices, + dim, + extreme_point_cnt, + discretization, + ) return λ, α end -function amp_convexify_monomial(m::Optimizer, k::Any, λ::Dict, α::Dict, discretization::Dict) - +function amp_convexify_monomial( + m::Optimizer, + k::Any, + λ::Dict, + α::Dict, + discretization::Dict, +) m.nonconvex_terms[k][:convexified] = true # Bookeeping the convexified terms - monomial_index, dim, extreme_point_cnt = Alp.amp_convhull_prepare(m, discretization, k, monomial=true) + monomial_index, dim, extreme_point_cnt = + Alp.amp_convhull_prepare(m, discretization, k, monomial = true) λ = Alp.amp_convhull_λ(m, k, monomial_index, λ, extreme_point_cnt, dim) λ = Alp.populate_convhull_extreme_values(m, discretization, monomial_index, λ, 2) α = Alp.amp_convhull_α(m, [monomial_index], α, dim, discretization) @@ -68,7 +96,6 @@ function amp_convexify_monomial(m::Optimizer, k::Any, λ::Dict, α::Dict, discre end function amp_convexify_binlin(m::Optimizer, k::Any, β::Dict) - m.nonconvex_terms[k][:convexified] = true # Bookeeping the convexified terms @assert length(m.nonconvex_terms[k][:var_idxs]) == 2 @@ -89,17 +116,23 @@ function amp_convexify_binlin(m::Optimizer, k::Any, β::Dict) bin_idx = bin_idx[1] cont_idx = cont_idx[1] - Alp.mccormick_binlin(m.model_mip, _index_to_variable_ref(m.model_mip, lift_idx), - _index_to_variable_ref(m.model_mip, bin_idx), _index_to_variable_ref(m.model_mip, cont_idx), - m.l_var_tight[cont_idx], m.u_var_tight[cont_idx]) + Alp.mccormick_binlin( + m.model_mip, + _index_to_variable_ref(m.model_mip, lift_idx), + _index_to_variable_ref(m.model_mip, bin_idx), + _index_to_variable_ref(m.model_mip, cont_idx), + m.l_var_tight[cont_idx], + m.u_var_tight[cont_idx], + ) return β end -amp_convexify_binint(m::Optimizer, k::Any, β::Dict) = amp_convexify_binlin(m, k, β) +function amp_convexify_binint(m::Optimizer, k::Any, β::Dict) + return amp_convexify_binlin(m, k, β) +end function amp_convexify_binprod(m::Optimizer, k::Any, β::Dict) - m.nonconvex_terms[k][:convexified] = true # Bookeeping the convexified terms lift_idx = m.nonconvex_terms[k][:y_idx] @@ -114,7 +147,7 @@ function amp_convexify_binprod(m::Optimizer, k::Any, β::Dict) for i in x JuMP.@constraint(m.model_mip, z <= i) end - JuMP.@constraint(m.model_mip, z >= sum(x) - (length(x)-1)) + JuMP.@constraint(m.model_mip, z >= sum(x) - (length(x) - 1)) return β end @@ -122,8 +155,7 @@ end """ Method for general nonlinear terms """ -function amp_convhull_prepare(m::Optimizer, d::Dict, nonlinear_key::Any; monomial=false) - +function amp_convhull_prepare(m::Optimizer, d::Dict, nonlinear_key::Any; monomial = false) counted_var = [] # Keep both vector and set for collection sake id = Set() # Coverting the nonlinear indices into a set @@ -164,16 +196,29 @@ end """ Method for general nonlinear terms """ -function amp_convhull_λ(m::Optimizer, nonlinear_key::Any, indices::Any, λ::Dict, ext_cnt::Int, dim::Tuple) - +function amp_convhull_λ( + m::Optimizer, + nonlinear_key::Any, + indices::Any, + λ::Dict, + ext_cnt::Int, + dim::Tuple, +) y_idx = m.nonconvex_terms[nonlinear_key][:y_idx] @assert !(y_idx in keys(λ)) - λ[indices] = Dict(:dim=>dim, - :lifted_var_idx=>y_idx, - :indices=>reshape([1:ext_cnt;], dim), - :vars=>JuMP.@variable(m.model_mip, [1:ext_cnt], lower_bound=0, base_name="L$(y_idx)"), - :vals=>ones(dim)) + λ[indices] = Dict( + :dim => dim, + :lifted_var_idx => y_idx, + :indices => reshape([1:ext_cnt;], dim), + :vars => JuMP.@variable( + m.model_mip, + [1:ext_cnt], + lower_bound = 0, + base_name = "L$(y_idx)" + ), + :vals => ones(dim), + ) return λ end @@ -181,7 +226,13 @@ end """ Method for power terms """ -function populate_convhull_extreme_values(m::Optimizer, d::Dict, mono_idx::Int, λ::Dict, p::Int) +function populate_convhull_extreme_values( + m::Optimizer, + d::Dict, + mono_idx::Int, + λ::Dict, + p::Int, +) λ[mono_idx][:vals] = [d[mono_idx][i]^p for i in 1:length(d[mono_idx])] return λ end @@ -189,8 +240,15 @@ end """ Method for regular muiltilinear terms """ -function populate_convhull_extreme_values(m::Optimizer, discretization::Dict, indices::Any, λ::Dict, dim::Tuple, locator::Array, level::Int=1) - +function populate_convhull_extreme_values( + m::Optimizer, + discretization::Dict, + indices::Any, + λ::Dict, + dim::Tuple, + locator::Array, + level::Int = 1, +) if level > length(dim) @assert length(indices) == length(dim) @assert length(indices) == length(locator) @@ -205,7 +263,15 @@ function populate_convhull_extreme_values(m::Optimizer, discretization::Dict, in else for i in 1:dim[level] locator[level] = i - λ = Alp.populate_convhull_extreme_values(m, discretization, indices, λ, dim, locator, level+1) + λ = Alp.populate_convhull_extreme_values( + m, + discretization, + indices, + λ, + dim, + locator, + level + 1, + ) end end @@ -215,20 +281,43 @@ end """ General Method for all term """ -function amp_convhull_α(m::Optimizer, indices::Any, α::Dict, dim::Tuple, discretization::Dict) - +function amp_convhull_α( + m::Optimizer, + indices::Any, + α::Dict, + dim::Tuple, + discretization::Dict, +) for i in indices if !(i in keys(α)) lambda_cnt = length(discretization[i]) partition_cnt = length(discretization[i]) - 1 if Alp.get_option(m, :convhull_ebd) && partition_cnt > 2 - αCnt = Int(ceil(log(2,partition_cnt))) - α[i] = JuMP.@variable(m.model_mip, [1:αCnt], Bin, base_name=string("YL",i)) + αCnt = Int(ceil(log(2, partition_cnt))) + α[i] = JuMP.@variable( + m.model_mip, + [1:αCnt], + Bin, + base_name = string("YL", i) + ) else - α[i] = JuMP.@variable(m.model_mip, [1:partition_cnt], Bin, base_name="A$(i)") + α[i] = JuMP.@variable( + m.model_mip, + [1:partition_cnt], + Bin, + base_name = "A$(i)" + ) JuMP.@constraint(m.model_mip, sum(α[i]) == 1) - JuMP.@constraint(m.model_mip, _index_to_variable_ref(m.model_mip, i) >= sum(α[i][j]*discretization[i][j] for j in 1:lambda_cnt-1)) # Add x = f(α) for regulating the domains - JuMP.@constraint(m.model_mip, _index_to_variable_ref(m.model_mip, i) <= sum(α[i][j-1]*discretization[i][j] for j in 2:lambda_cnt)) + JuMP.@constraint( + m.model_mip, + _index_to_variable_ref(m.model_mip, i) >= + sum(α[i][j] * discretization[i][j] for j in 1:lambda_cnt-1) + ) # Add x = f(α) for regulating the domains + JuMP.@constraint( + m.model_mip, + _index_to_variable_ref(m.model_mip, i) <= + sum(α[i][j-1] * discretization[i][j] for j in 2:lambda_cnt) + ) end end end @@ -236,10 +325,11 @@ function amp_convhull_α(m::Optimizer, indices::Any, α::Dict, dim::Tuple, discr return α end -amp_convhull_α(m::Optimizer, idx::Int, α::Dict, dim, d::Dict) = amp_convhull_α(m, [idx], α, dim, d) +function amp_convhull_α(m::Optimizer, idx::Int, α::Dict, dim, d::Dict) + return amp_convhull_α(m, [idx], α, dim, d) +end function amp_no_good_cut_α(m::Optimizer, α::Dict) - println("Global Incumbent solution objective = $(m.best_obj)") for i in 1:m.bound_sol_pool[:cnt] @@ -247,8 +337,14 @@ function amp_no_good_cut_α(m::Optimizer, α::Dict) if m.best_obj < m.bound_sol_pool[:obj][i] && m.bound_sol_pool[:stat][i] == :Alive no_good_idxs = keys(m.bound_sol_pool[:disc][i]) no_good_size = length(no_good_idxs) - 1 - JuMP.@constraint(m.model_mip, sum(α[v][m.bound_sol_pool[:disc][i][v]] for v in no_good_idxs) <= no_good_size) - Alp.get_option(m, :log_level) > 0 && println("!! GLOBAL cuts off POOL_SOL-$(i) POOL_OBJ=$(m.bound_sol_pool[:obj][i])!") + JuMP.@constraint( + m.model_mip, + sum(α[v][m.bound_sol_pool[:disc][i][v]] for v in no_good_idxs) <= + no_good_size + ) + Alp.get_option(m, :log_level) > 0 && println( + "!! GLOBAL cuts off POOL_SOL-$(i) POOL_OBJ=$(m.bound_sol_pool[:obj][i])!", + ) m.bound_sol_pool[:stat][i] = :Cutoff end end @@ -257,7 +353,6 @@ function amp_no_good_cut_α(m::Optimizer, α::Dict) end function amp_warmstart_α(m::Optimizer, α::Dict) - d = m.discretization if m.bound_sol_pool[:cnt] >= 2 # can only warm-start the problem when pool is large enough @@ -267,8 +362,10 @@ function amp_warmstart_α(m::Optimizer, α::Dict) # Search for the pool for incumbent warm starter for i in 1:m.bound_sol_pool[:cnt] - m.bound_sol_pool[:stat][i] == :Warmstarter && (m.bound_sol_pool[:stat][i] = :Alive) # reset the status if not dead - if m.bound_sol_pool[:stat][i] != :Dead && eval(comp_opr[m.sense_orig])(m.bound_sol_pool[:obj][i], ws_obj) + m.bound_sol_pool[:stat][i] == :Warmstarter && + (m.bound_sol_pool[:stat][i] = :Alive) # reset the status if not dead + if m.bound_sol_pool[:stat][i] != :Dead && + eval(comp_opr[m.sense_orig])(m.bound_sol_pool[:obj][i], ws_obj) ws_idx = i ws_obj = m.bound_sol_pool[:obj][i] end @@ -276,14 +373,18 @@ function amp_warmstart_α(m::Optimizer, α::Dict) if ws_idx > 0 # If a warm starter is found for v in m.bound_sol_pool[:vars] - partition_cnt = length(d[v])-1 - active_j = Alp.get_active_partition_idx(d, m.bound_sol_pool[:sol][ws_idx][v], v) - for j = 1:partition_cnt - j == active_j ? set_start_value(α[v][j], 1.0) : set_start_value(α[v][j], 0.0) + partition_cnt = length(d[v]) - 1 + active_j = + Alp.get_active_partition_idx(d, m.bound_sol_pool[:sol][ws_idx][v], v) + for j in 1:partition_cnt + j == active_j ? set_start_value(α[v][j], 1.0) : + set_start_value(α[v][j], 0.0) end end m.bound_sol_pool[:stat][ws_idx] = :Warmstarter - Alp.get_option(m, :log_level) > 0 && println("!! WARM START bounding MIP using POOL SOL $(ws_idx) OBJ=$(m.bound_sol_pool[:obj][ws_idx])") + Alp.get_option(m, :log_level) > 0 && println( + "!! WARM START bounding MIP using POOL SOL $(ws_idx) OBJ=$(m.bound_sol_pool[:obj][ws_idx])", + ) end end @@ -293,11 +394,23 @@ end """ Method for general multilinear terms with/without integer variables """ -function amp_post_convhull_constrs(m::Optimizer, λ::Dict, α::Dict, indices::Any, dim::Tuple, ext_cnt::Int, d::Dict) +function amp_post_convhull_constrs( + m::Optimizer, + λ::Dict, + α::Dict, + indices::Any, + dim::Tuple, + ext_cnt::Int, + d::Dict, +) # Adding λ constraints JuMP.@constraint(m.model_mip, sum(λ[indices][:vars]) == 1) - JuMP.@constraint(m.model_mip, _index_to_variable_ref(m.model_mip, λ[indices][:lifted_var_idx]) == dot(λ[indices][:vars], reshape(λ[indices][:vals], ext_cnt))) + JuMP.@constraint( + m.model_mip, + _index_to_variable_ref(m.model_mip, λ[indices][:lifted_var_idx]) == + dot(λ[indices][:vars], reshape(λ[indices][:vals], ext_cnt)) + ) # Add links on each dimension for (cnt, i) in enumerate(indices) @@ -307,8 +420,17 @@ function amp_post_convhull_constrs(m::Optimizer, λ::Dict, α::Dict, indices::An else error("EXCEPTION: unexpected variable type during integer related realxation") end - sliced_indices = [collect_indices(λ[indices][:indices], cnt, [k], dim) for k in 1:l_cnt] # Add x = f(λ) for convex representation of x value - JuMP.@constraint(m.model_mip, _index_to_variable_ref(m.model_mip, i) == sum(dot(repeat([d[i][k]],length(sliced_indices[k])), λ[indices][:vars][sliced_indices[k]]) for k in 1:l_cnt)) + sliced_indices = + [collect_indices(λ[indices][:indices], cnt, [k], dim) for k in 1:l_cnt] # Add x = f(λ) for convex representation of x value + JuMP.@constraint( + m.model_mip, + _index_to_variable_ref(m.model_mip, i) == sum( + dot( + repeat([d[i][k]], length(sliced_indices[k])), + λ[indices][:vars][sliced_indices[k]], + ) for k in 1:l_cnt + ) + ) end return @@ -317,42 +439,93 @@ end """ Method for power-2 term """ -function amp_post_convhull_constrs(m::Optimizer, λ::Dict, α::Dict, monomial_idx::Int, dim::Tuple, discretization::Dict) - - partition_cnt = length(discretization[monomial_idx])-1 +function amp_post_convhull_constrs( + m::Optimizer, + λ::Dict, + α::Dict, + monomial_idx::Int, + dim::Tuple, + discretization::Dict, +) + partition_cnt = length(discretization[monomial_idx]) - 1 lambda_cnt = length(discretization[monomial_idx]) # Adding λ constraints JuMP.@constraint(m.model_mip, sum(λ[monomial_idx][:vars]) == 1) - JuMP.@constraint(m.model_mip, _index_to_variable_ref(m.model_mip, λ[monomial_idx][:lifted_var_idx]) <= dot(λ[monomial_idx][:vars], λ[monomial_idx][:vals])) - JuMP.@constraint(m.model_mip, _index_to_variable_ref(m.model_mip, λ[monomial_idx][:lifted_var_idx]) >= _index_to_variable_ref(m.model_mip, monomial_idx)^2) + JuMP.@constraint( + m.model_mip, + _index_to_variable_ref(m.model_mip, λ[monomial_idx][:lifted_var_idx]) <= + dot(λ[monomial_idx][:vars], λ[monomial_idx][:vals]) + ) + JuMP.@constraint( + m.model_mip, + _index_to_variable_ref(m.model_mip, λ[monomial_idx][:lifted_var_idx]) >= + _index_to_variable_ref(m.model_mip, monomial_idx)^2 + ) # Add SOS-2 Constraints with basic encoding if Alp.get_option(m, :convhull_ebd) && partition_cnt > 2 - ebd_map = embedding_map(lambda_cnt, Alp.get_option(m, :convhull_ebd_encode), Alp.get_option(m, :convhull_ebd_ibs)) + ebd_map = embedding_map( + lambda_cnt, + Alp.get_option(m, :convhull_ebd_encode), + Alp.get_option(m, :convhull_ebd_ibs), + ) YCnt = Int(ebd_map[:L]) @assert YCnt == length(α[monomial_idx]) for i in 1:YCnt - JuMP.@constraint(m.model_mip, sum(λ[monomial_idx][:vars][collect(ebd_map[i])]) <= α[monomial_idx][i]) - JuMP.@constraint(m.model_mip, sum(λ[monomial_idx][:vars][collect(ebd_map[i+YCnt])]) <= 1-α[monomial_idx][i]) + JuMP.@constraint( + m.model_mip, + sum(λ[monomial_idx][:vars][collect(ebd_map[i])]) <= α[monomial_idx][i] + ) + JuMP.@constraint( + m.model_mip, + sum(λ[monomial_idx][:vars][collect(ebd_map[i+YCnt])]) <= + 1 - α[monomial_idx][i] + ) end else for i in 1:lambda_cnt if i == 1 - JuMP.@constraint(m.model_mip, λ[monomial_idx][:vars][i] <= α[monomial_idx][i]) + JuMP.@constraint( + m.model_mip, + λ[monomial_idx][:vars][i] <= α[monomial_idx][i] + ) elseif i == lambda_cnt - JuMP.@constraint(m.model_mip, λ[monomial_idx][:vars][i] <= α[monomial_idx][i-1]) + JuMP.@constraint( + m.model_mip, + λ[monomial_idx][:vars][i] <= α[monomial_idx][i-1] + ) else - JuMP.@constraint(m.model_mip, λ[monomial_idx][:vars][i] <= α[monomial_idx][i-1] + α[monomial_idx][i]) + JuMP.@constraint( + m.model_mip, + λ[monomial_idx][:vars][i] <= + α[monomial_idx][i-1] + α[monomial_idx][i] + ) end end # Add x = f(α) for regulating the domains - JuMP.@constraint(m.model_mip, _index_to_variable_ref(m.model_mip, monomial_idx) >= sum(α[monomial_idx][j]*discretization[monomial_idx][j] for j in 1:lambda_cnt-1)) - JuMP.@constraint(m.model_mip, _index_to_variable_ref(m.model_mip, monomial_idx) <= sum(α[monomial_idx][j-1]*discretization[monomial_idx][j] for j in 2:lambda_cnt)) + JuMP.@constraint( + m.model_mip, + _index_to_variable_ref(m.model_mip, monomial_idx) >= sum( + α[monomial_idx][j] * discretization[monomial_idx][j] for + j in 1:lambda_cnt-1 + ) + ) + JuMP.@constraint( + m.model_mip, + _index_to_variable_ref(m.model_mip, monomial_idx) <= sum( + α[monomial_idx][j-1] * discretization[monomial_idx][j] for + j in 2:lambda_cnt + ) + ) end # Add x = f(λ) for convex representation - JuMP.@constraint(m.model_mip, _index_to_variable_ref(m.model_mip, monomial_idx) == dot(λ[monomial_idx][:vars], discretization[monomial_idx])) + JuMP.@constraint( + m.model_mip, + _index_to_variable_ref(m.model_mip, monomial_idx) == + dot(λ[monomial_idx][:vars], discretization[monomial_idx]) + ) return end @@ -360,23 +533,60 @@ end """ Method for regular multilinear terms (terms that only has continuous variables) """ -function amp_post_inequalities_cont(m::Optimizer, discretization::Dict, λ::Dict, α::Dict, ml_indices::Any, dim::Tuple, var_ind::Int, cnt::Int) - +function amp_post_inequalities_cont( + m::Optimizer, + discretization::Dict, + λ::Dict, + α::Dict, + ml_indices::Any, + dim::Tuple, + var_ind::Int, + cnt::Int, +) lambda_cnt = length(discretization[var_ind]) partition_cnt = lambda_cnt - 1 # Embedding formulation - if Alp.get_option(m, :convhull_formulation) == "sos2" && Alp.get_option(m, :convhull_ebd) && partition_cnt > 2 - ebd_map = embedding_map(lambda_cnt, Alp.get_option(m, :convhull_ebd_encode), Alp.get_option(m, :convhull_ebd_ibs)) + if Alp.get_option(m, :convhull_formulation) == "sos2" && + Alp.get_option(m, :convhull_ebd) && + partition_cnt > 2 + ebd_map = embedding_map( + lambda_cnt, + Alp.get_option(m, :convhull_ebd_encode), + Alp.get_option(m, :convhull_ebd_ibs), + ) YCnt = Int(ebd_map[:L]) @assert YCnt == length(α[var_ind]) for i in 1:YCnt - p_sliced_indices = Alp.collect_indices(λ[ml_indices][:indices], cnt, collect(ebd_map[i]), dim) - n_sliced_indices = Alp.collect_indices(λ[ml_indices][:indices], cnt, collect(ebd_map[i+YCnt]), dim) - JuMP.@constraint(m.model_mip, sum(λ[ml_indices][:vars][p_sliced_indices]) <= α[var_ind][i]) - JuMP.@constraint(m.model_mip, sum(λ[ml_indices][:vars][n_sliced_indices]) <= 1-α[var_ind][i]) + p_sliced_indices = Alp.collect_indices( + λ[ml_indices][:indices], + cnt, + collect(ebd_map[i]), + dim, + ) + n_sliced_indices = Alp.collect_indices( + λ[ml_indices][:indices], + cnt, + collect(ebd_map[i+YCnt]), + dim, + ) + JuMP.@constraint( + m.model_mip, + sum(λ[ml_indices][:vars][p_sliced_indices]) <= α[var_ind][i] + ) + JuMP.@constraint( + m.model_mip, + sum(λ[ml_indices][:vars][n_sliced_indices]) <= 1 - α[var_ind][i] + ) end - Alp.get_option(m, :convhull_ebd_link) && Alp.ebd_link_xα(m, α[var_ind], lambda_cnt, discretization[var_ind], ebd_map[:H_orig], var_ind) + Alp.get_option(m, :convhull_ebd_link) && Alp.ebd_link_xα( + m, + α[var_ind], + lambda_cnt, + discretization[var_ind], + ebd_map[:H_orig], + var_ind, + ) return end @@ -385,22 +595,39 @@ function amp_post_inequalities_cont(m::Optimizer, discretization::Dict, λ::Dict for j in 1:lambda_cnt sliced_indices = collect_indices(λ[ml_indices][:indices], cnt, [j], dim) if (j == 1) - JuMP.@constraint(m.model_mip, sum(λ[ml_indices][:vars][sliced_indices]) <= α[var_ind][j]) + JuMP.@constraint( + m.model_mip, + sum(λ[ml_indices][:vars][sliced_indices]) <= α[var_ind][j] + ) elseif (j == lambda_cnt) - JuMP.@constraint(m.model_mip, sum(λ[ml_indices][:vars][sliced_indices]) <= α[var_ind][partition_cnt]) + JuMP.@constraint( + m.model_mip, + sum(λ[ml_indices][:vars][sliced_indices]) <= + α[var_ind][partition_cnt] + ) else - JuMP.@constraint(m.model_mip, sum(λ[ml_indices][:vars][sliced_indices]) <= sum(α[var_ind][(j-1):j])) + JuMP.@constraint( + m.model_mip, + sum(λ[ml_indices][:vars][sliced_indices]) <= sum(α[var_ind][(j-1):j]) + ) end end return elseif Alp.get_option(m, :convhull_formulation) == "facet" for j in 1:(partition_cnt-1) # Constraint cluster of α >= f(λ) sliced_indices = collect_indices(λ[ml_indices][:indices], cnt, [1:j;], dim) - JuMP.@constraint(m.model_mip, sum(α[var_ind][1:j]) >= sum(λ[ml_indices][:vars][sliced_indices])) + JuMP.@constraint( + m.model_mip, + sum(α[var_ind][1:j]) >= sum(λ[ml_indices][:vars][sliced_indices]) + ) end for j in 1:(partition_cnt-1) # Constraint cluster of α <= f(λ) - sliced_indices = collect_indices(λ[ml_indices][:indices], cnt, [1:(j+1);], dim) - JuMP.@constraint(m.model_mip, sum(α[var_ind][1:j]) <= sum(λ[ml_indices][:vars][sliced_indices])) + sliced_indices = + collect_indices(λ[ml_indices][:indices], cnt, [1:(j+1);], dim) + JuMP.@constraint( + m.model_mip, + sum(α[var_ind][1:j]) <= sum(λ[ml_indices][:vars][sliced_indices]) + ) end return else @@ -410,23 +637,35 @@ function amp_post_inequalities_cont(m::Optimizer, discretization::Dict, λ::Dict return end -function amp_post_λ_upperbound(m::Optimizer, λ::Dict, indices::Any, dim::Tuple, d::Dict, tregions::Vector, reg=[], level=0) - +function amp_post_λ_upperbound( + m::Optimizer, + λ::Dict, + indices::Any, + dim::Tuple, + d::Dict, + tregions::Vector, + reg = [], + level = 0, +) if level == length(indices) isempty(tregions[level]) && return - sliced_indices = Set(collect_indices(λ[indices][:indices], 1, [reg[1]; reg[1]+1], dim)) + sliced_indices = + Set(collect_indices(λ[indices][:indices], 1, [reg[1]; reg[1] + 1], dim)) for i in 2:length(reg) - sliced_indices = intersect(sliced_indices, Set(collect_indices(λ[indices][:indices], i, [reg[i],reg[i]+1], dim))) + sliced_indices = intersect( + sliced_indices, + Set(collect_indices(λ[indices][:indices], i, [reg[i], reg[i] + 1], dim)), + ) end for i in sliced_indices - JuMP.set_upper_bound(λ[indices][:vars][i], (1/2)^level) + JuMP.set_upper_bound(λ[indices][:vars][i], (1 / 2)^level) end return end for i in 1:length(tregions[level+1]) push!(reg, tregions[level+1][i]) - Alp.amp_post_λ_upperbound(m, λ, indices, dim, d, tregions, reg, level+1) + Alp.amp_post_λ_upperbound(m, λ, indices, dim, d, tregions, reg, level + 1) length(reg) < level && error("Something is wrong") length(reg) > level && pop!(reg) end @@ -435,25 +674,26 @@ function amp_post_λ_upperbound(m::Optimizer, λ::Dict, indices::Any, dim::Tuple end function amp_post_λ_upperbound(m::Optimizer, λ::Dict, indices::Any, ub::Float64) - - for i in λ[indices][:vars] JuMP.set_upper_bound(i, ub) end + for i in λ[indices][:vars] + JuMP.set_upper_bound(i, ub) + end return end function collect_indices(l::Array, fixed_dim::Int, fixed_partition::Array, dim::Tuple) + k = 0 + indices = + Vector{Int}(undef, Int(prod(dim) / dim[fixed_dim] * length(fixed_partition))) + for i in 1:prod(dim) + ind = Tuple(CartesianIndices(l)[i]) + if ind[fixed_dim] in fixed_partition + k += 1 + indices[k] = i + end + end - k = 0 - indices = Vector{Int}(undef, Int(prod(dim)/dim[fixed_dim]*length(fixed_partition))) - for i in 1:prod(dim) - ind = Tuple(CartesianIndices(l)[i]) - if ind[fixed_dim] in fixed_partition - k += 1 - indices[k] = i - end - end - - return indices + return indices end #= @@ -554,4 +794,4 @@ function amp_collect_tight_regions(partvec::Vector) return tight_regions end -=# \ No newline at end of file +=# diff --git a/src/nlexpr.jl b/src/nlexpr.jl index 15f05d1e..414248a0 100644 --- a/src/nlexpr.jl +++ b/src/nlexpr.jl @@ -4,14 +4,13 @@ process_expr(expr; kwargs...) High-level wrapper for processing expression with sub-tree operators """ function process_expr(m::Optimizer) + Alp.expr_initialization(m) # S0 : initialize the space for parsing and analyzing + Alp.expr_preprocess(m) # S1 : pre-process the negative sign in expressions + Alp.expr_parsing(m) # S2 : parsing the expressions for nonlinear information + Alp.expr_conversion(m) # S3 : convert lifted(linear) expressions into affine function + Alp.expr_finalized(m) # S4 : finalize process by extracting some measurements - Alp.expr_initialization(m) # S0 : initialize the space for parsing and analyzing - Alp.expr_preprocess(m) # S1 : pre-process the negative sign in expressions - Alp.expr_parsing(m) # S2 : parsing the expressions for nonlinear information - Alp.expr_conversion(m) # S3 : convert lifted(linear) expressions into affine function - Alp.expr_finalized(m) # S4 : finalize process by extracting some measurements - - return + return end """ @@ -19,33 +18,32 @@ STEP 1: initialize the expression/ space """ function expr_initialization(m::Optimizer) - # 0 : deepcopy data into mip lifted expr place holders - m.bounding_obj_expr_mip = deepcopy(m.obj_expr_orig) - m.bounding_obj_mip = Dict() + # 0 : deepcopy data into mip lifted expr place holders + m.bounding_obj_expr_mip = deepcopy(m.obj_expr_orig) + m.bounding_obj_mip = Dict() - for i in 1:m.num_constr_orig - push!(m.bounding_constr_expr_mip, deepcopy(m.constr_expr_orig[i])) - push!(m.bounding_constr_mip, Dict()) - end + for i in 1:m.num_constr_orig + push!(m.bounding_constr_expr_mip, deepcopy(m.constr_expr_orig[i])) + push!(m.bounding_constr_mip, Dict()) + end - return + return end """ STEP 2: preprocess expression for trivial sub-trees and nasty pieces for easier later process """ function expr_preprocess(m::Optimizer) - - Alp.expr_resolve_const(m.bounding_obj_expr_mip) - Alp.expr_resolve_sign(m.bounding_obj_expr_mip) - Alp.expr_flatten(m.bounding_obj_expr_mip) - for i in 1:m.num_constr_orig - Alp.expr_resolve_const(m.bounding_constr_expr_mip[i]) - Alp.expr_resolve_sign(m.bounding_constr_expr_mip[i]) - Alp.expr_flatten(m.bounding_constr_expr_mip[i].args[2]) - end - - return + Alp.expr_resolve_const(m.bounding_obj_expr_mip) + Alp.expr_resolve_sign(m.bounding_obj_expr_mip) + Alp.expr_flatten(m.bounding_obj_expr_mip) + for i in 1:m.num_constr_orig + Alp.expr_resolve_const(m.bounding_constr_expr_mip[i]) + Alp.expr_resolve_sign(m.bounding_constr_expr_mip[i]) + Alp.expr_flatten(m.bounding_constr_expr_mip[i].args[2]) + end + + return end """ @@ -53,119 +51,133 @@ STEP 3: parse expression for patterns on either the generic level or term level """ function expr_parsing(m::Optimizer) - # Throw an error if obj. expression has non-integer exponents - Alp.expr_isfracexp(m.bounding_obj_expr_mip) - - is_strucural = Alp.expr_constr_parsing(m.bounding_obj_expr_mip, m) - if !is_strucural - m.bounding_obj_expr_mip = Alp.expr_term_parsing(m.bounding_obj_expr_mip, 0, m) - m.obj_structure = :generic_linear - end - (Alp.get_option(m, :log_level) > 199) && println("[OBJ] $(m.obj_expr_orig)") - - for i in 1:m.num_constr_orig - is_strucural = Alp.expr_constr_parsing(m.bounding_constr_expr_mip[i], m, i) - if !is_strucural - m.bounding_constr_expr_mip[i] = Alp.expr_term_parsing(m.bounding_constr_expr_mip[i], i, m) - m.constr_structure[i] = :generic_linear - end - (Alp.get_option(m, :log_level) > 199) && println("[CONSTR] $(m.constr_expr_orig[i])") - end - - return + # Throw an error if obj. expression has non-integer exponents + Alp.expr_isfracexp(m.bounding_obj_expr_mip) + + is_strucural = Alp.expr_constr_parsing(m.bounding_obj_expr_mip, m) + if !is_strucural + m.bounding_obj_expr_mip = Alp.expr_term_parsing(m.bounding_obj_expr_mip, 0, m) + m.obj_structure = :generic_linear + end + (Alp.get_option(m, :log_level) > 199) && println("[OBJ] $(m.obj_expr_orig)") + + for i in 1:m.num_constr_orig + is_strucural = Alp.expr_constr_parsing(m.bounding_constr_expr_mip[i], m, i) + if !is_strucural + m.bounding_constr_expr_mip[i] = + Alp.expr_term_parsing(m.bounding_constr_expr_mip[i], i, m) + m.constr_structure[i] = :generic_linear + end + (Alp.get_option(m, :log_level) > 199) && + println("[CONSTR] $(m.constr_expr_orig[i])") + end + + return end """ STEP 4: convert the parsed expressions into affine-based function that can be used for adding JuMP constraints """ function expr_conversion(m::Optimizer) - - if m.obj_structure == :generic_linear - m.bounding_obj_mip = Alp.expr_linear_to_affine(m.bounding_obj_expr_mip) - m.obj_structure = :affine - end - Alp.get_option(m, :log_level) > 199 && println("type :: ", m.obj_structure) - Alp.get_option(m, :log_level) > 199 && println("lifted ::", m.bounding_obj_expr_mip) - Alp.get_option(m, :log_level) > 199 && println("coeffs ::", m.bounding_obj_mip[:coefs]) - Alp.get_option(m, :log_level) > 199 && println("vars ::", m.bounding_obj_mip[:vars]) - Alp.get_option(m, :log_level) > 199 && println("sense ::", m.bounding_obj_mip[:sense]) - Alp.get_option(m, :log_level) > 199 && println("rhs ::", m.bounding_obj_mip[:rhs]) - Alp.get_option(m, :log_level) > 199 && println("----------------") - - - for i in 1:m.num_constr_orig - if m.constr_structure[i] == :generic_linear - m.bounding_constr_mip[i] = Alp.expr_linear_to_affine(m.bounding_constr_expr_mip[i]) - m.constr_structure[i] = :affine - end - Alp.get_option(m, :log_level) > 199 && println("type :: ", m.constr_structure[i]) - Alp.get_option(m, :log_level) > 199 && println("lifted ::", m.bounding_constr_expr_mip[i]) - Alp.get_option(m, :log_level) > 199 && println("coeffs ::", m.bounding_constr_mip[i][:coefs]) - Alp.get_option(m, :log_level) > 199 && println("vars ::", m.bounding_constr_mip[i][:vars]) - Alp.get_option(m, :log_level) > 199 && println("sense ::", m.bounding_constr_mip[i][:sense]) - Alp.get_option(m, :log_level) > 199 && println("rhs ::", m.bounding_constr_mip[i][:rhs]) - Alp.get_option(m, :log_level) > 199 && println("----------------") - end - - return + if m.obj_structure == :generic_linear + m.bounding_obj_mip = Alp.expr_linear_to_affine(m.bounding_obj_expr_mip) + m.obj_structure = :affine + end + Alp.get_option(m, :log_level) > 199 && println("type :: ", m.obj_structure) + Alp.get_option(m, :log_level) > 199 && println("lifted ::", m.bounding_obj_expr_mip) + Alp.get_option(m, :log_level) > 199 && + println("coeffs ::", m.bounding_obj_mip[:coefs]) + Alp.get_option(m, :log_level) > 199 && println("vars ::", m.bounding_obj_mip[:vars]) + Alp.get_option(m, :log_level) > 199 && println("sense ::", m.bounding_obj_mip[:sense]) + Alp.get_option(m, :log_level) > 199 && println("rhs ::", m.bounding_obj_mip[:rhs]) + Alp.get_option(m, :log_level) > 199 && println("----------------") + + for i in 1:m.num_constr_orig + if m.constr_structure[i] == :generic_linear + m.bounding_constr_mip[i] = + Alp.expr_linear_to_affine(m.bounding_constr_expr_mip[i]) + m.constr_structure[i] = :affine + end + Alp.get_option(m, :log_level) > 199 && println("type :: ", m.constr_structure[i]) + Alp.get_option(m, :log_level) > 199 && + println("lifted ::", m.bounding_constr_expr_mip[i]) + Alp.get_option(m, :log_level) > 199 && + println("coeffs ::", m.bounding_constr_mip[i][:coefs]) + Alp.get_option(m, :log_level) > 199 && + println("vars ::", m.bounding_constr_mip[i][:vars]) + Alp.get_option(m, :log_level) > 199 && + println("sense ::", m.bounding_constr_mip[i][:sense]) + Alp.get_option(m, :log_level) > 199 && + println("rhs ::", m.bounding_constr_mip[i][:rhs]) + Alp.get_option(m, :log_level) > 199 && println("----------------") + end + + return end - """ STEP 5: collect measurements and information as needed for handy operations in the algorithm section """ function expr_finalized(m::Optimizer) + Alp.collect_nonconvex_vars(m) + m.candidate_disc_vars = sort(m.candidate_disc_vars) + m.num_var_linear_mip = length(m.linear_terms) + m.num_var_nonlinear_mip = length(m.nonconvex_terms) + m.num_constr_convex = length([i for i in m.constr_structure if i == :convex]) - Alp.collect_nonconvex_vars(m) - m.candidate_disc_vars = sort(m.candidate_disc_vars) - m.num_var_linear_mip = length(m.linear_terms) - m.num_var_nonlinear_mip = length(m.nonconvex_terms) - m.num_constr_convex = length([i for i in m.constr_structure if i == :convex]) - - return m + return m end function collect_nonconvex_vars(m::Optimizer) - # Walk through all nonconvex terms - for i in keys(m.nonconvex_terms) - m.nonconvex_terms[i][:discvar_collector](m, i) - end + # Walk through all nonconvex terms + for i in keys(m.nonconvex_terms) + m.nonconvex_terms[i][:discvar_collector](m, i) + end - # TODO : reconsider how to structure this - # NOTE : Walk through all integer variables that didn't appear in any nonconvex terms - for i in 1:m.num_var_orig - if !(i in m.candidate_disc_vars) && m.var_type[i] == :Int - push!(m.candidate_disc_vars, i) - end - end + # TODO : reconsider how to structure this + # NOTE : Walk through all integer variables that didn't appear in any nonconvex terms + for i in 1:m.num_var_orig + if !(i in m.candidate_disc_vars) && m.var_type[i] == :Int + push!(m.candidate_disc_vars, i) + end + end - return + return end -isa_variable_index(expr::Expr) = length(expr.args == 2) && expr.args[2] == :(MathOptInterface.VariableIndex) +function isa_variable_index(expr::Expr) + return length(expr.args == 2) && expr.args[2] == :(MathOptInterface.VariableIndex) +end get_index(expr::Expr) = expr.args[2] -function expr_strip_const(expr, subs=[], rhs=0.0) - - exhaust_const = [!(expr.args[1] in [:+, :-]) || !(isa(expr.args[i], Float64) || isa(expr.args[i], Int)) for i in 2:length(expr.args)] - if prod(exhaust_const) - push!(subs, expr) - return subs, rhs - end - - for i in 2:length(expr.args) - if (isa(expr.args[i], Float64) || isa(expr.args[i], Int) || isa(expr.args[i], Symbol)) - (expr.args[1] == :+) && (rhs -= expr.args[i]) - (expr.args[1] == :-) && ((i == 2) ? rhs -= expr.args[i] : rhs += expr.args[i]) - elseif expr.args[i].head == :ref - continue - elseif expr.args[i].head == :call - subs, rhs = Alp.expr_strip_const(expr.args[i], subs, rhs) - end - end - - return subs, rhs +function expr_strip_const(expr, subs = [], rhs = 0.0) + exhaust_const = [ + !(expr.args[1] in [:+, :-]) || + !(isa(expr.args[i], Float64) || isa(expr.args[i], Int)) for + i in 2:length(expr.args) + ] + if prod(exhaust_const) + push!(subs, expr) + return subs, rhs + end + + for i in 2:length(expr.args) + if ( + isa(expr.args[i], Float64) || + isa(expr.args[i], Int) || + isa(expr.args[i], Symbol) + ) + (expr.args[1] == :+) && (rhs -= expr.args[i]) + (expr.args[1] == :-) && ((i == 2) ? rhs -= expr.args[i] : rhs += expr.args[i]) + elseif expr.args[i].head == :ref + continue + elseif expr.args[i].head == :call + subs, rhs = Alp.expr_strip_const(expr.args[i], subs, rhs) + end + end + + return subs, rhs end """ @@ -176,15 +188,14 @@ input => y, x[1,2,3], :+ output => (y = x[1] + x[2] + x[3])::Expr """ function build_constr_block(y_idx::Int, var_idxs::Vector, operator::Symbol) - - expr_l_block = Expr(:call, :(==), Meta.parse("x[$(y_idx)]")) - expr_r_block = Expr(:call, operator) - for j in 1:length(var_idxs) - push!(expr_r_block.args, Meta.parse("x[$(var_idxs[j])]")) - end - push!(expr_l_block.args, expr_r_block) - - return expr_l_block + expr_l_block = Expr(:call, :(==), Meta.parse("x[$(y_idx)]")) + expr_r_block = Expr(:call, operator) + for j in 1:length(var_idxs) + push!(expr_r_block.args, Meta.parse("x[$(var_idxs[j])]")) + end + push!(expr_l_block.args, expr_r_block) + + return expr_l_block end """ @@ -192,63 +203,66 @@ Alp.expr_constr_parsing(expr, m::Optimizer) Recognize structural constraints. """ -function expr_constr_parsing(expr, m::Optimizer, idx::Int=0) +function expr_constr_parsing(expr, m::Optimizer, idx::Int = 0) - # First process user-defined structures in-cases of over-ride - # for i in 1:length(Alp.get_option(m, :constr_patterns)) - # is_strucural = eval(Alp.get_option(m, :constr_patterns)[i])(expr, m, idx) - # return - # end + # First process user-defined structures in-cases of over-ride + # for i in 1:length(Alp.get_option(m, :constr_patterns)) + # is_strucural = eval(Alp.get_option(m, :constr_patterns)[i])(expr, m, idx) + # return + # end - isa(expr, Number) && return false - # Recognize built-in special structural pattern - if Alp.get_option(m, :recognize_convex) - is_convex = Alp.resolve_convex_constr(expr, m, idx) - is_convex && return true - end + isa(expr, Number) && return false + # Recognize built-in special structural pattern + if Alp.get_option(m, :recognize_convex) + is_convex = Alp.resolve_convex_constr(expr, m, idx) + is_convex && return true + end - # More patterns goes here + # More patterns goes here - return false + return false end -function expr_is_axn(expr, scalar=1.0, var_idxs=[], power=[]; N=nothing) - - expr.args[1] in [:*,:^] || return nothing, nothing, nothing # Limited Area - - if expr.args[1] == :* - for i in 2:length(expr.args) - if isa(expr.args[i], Float64) || isa(expr.args[i], Int) - scalar *= expr.args[i] - elseif (expr.args[i].head == :ref) - @assert isa(expr.args[i].args[2], Int) - push!(var_idxs, expr.args[i]) - push!(power, 1) - elseif (expr.args[i].head == :call) - scalar, var_idxs, power = Alp.expr_is_axn(expr.args[i], scalar, var_idxs, power) - scalar === nothing && return nothing, nothing, nothing - end - end - elseif expr.args[1] == :^ - for i in 2:length(expr.args) - if isa(expr.args[i], Float64) || isa(expr.args[i], Int) - push!(power, expr.args[i]) - continue - elseif (expr.args[i].head == :ref) - push!(var_idxs, expr.args[i]) - continue - elseif (expr.args[i].head == :call) - return nothing, nothing, nothing - end - end - end - - # If the user wants a specific N - !(N === nothing) && !(length(var_idxs) == N) && return nothing, nothing, nothing - (var_idxs === nothing) && (scalar === nothing) && (power === nothing) && return nothing, nothing, nothing # Unrecognized sub-structure - - @assert length(var_idxs) == length(power) - return scalar, var_idxs, power +function expr_is_axn(expr, scalar = 1.0, var_idxs = [], power = []; N = nothing) + expr.args[1] in [:*, :^] || return nothing, nothing, nothing # Limited Area + + if expr.args[1] == :* + for i in 2:length(expr.args) + if isa(expr.args[i], Float64) || isa(expr.args[i], Int) + scalar *= expr.args[i] + elseif (expr.args[i].head == :ref) + @assert isa(expr.args[i].args[2], Int) + push!(var_idxs, expr.args[i]) + push!(power, 1) + elseif (expr.args[i].head == :call) + scalar, var_idxs, power = + Alp.expr_is_axn(expr.args[i], scalar, var_idxs, power) + scalar === nothing && return nothing, nothing, nothing + end + end + elseif expr.args[1] == :^ + for i in 2:length(expr.args) + if isa(expr.args[i], Float64) || isa(expr.args[i], Int) + push!(power, expr.args[i]) + continue + elseif (expr.args[i].head == :ref) + push!(var_idxs, expr.args[i]) + continue + elseif (expr.args[i].head == :call) + return nothing, nothing, nothing + end + end + end + + # If the user wants a specific N + !(N === nothing) && !(length(var_idxs) == N) && return nothing, nothing, nothing + (var_idxs === nothing) && + (scalar === nothing) && + (power === nothing) && + return nothing, nothing, nothing # Unrecognized sub-structure + + @assert length(var_idxs) == length(power) + return scalar, var_idxs, power end """ @@ -257,36 +271,37 @@ Use the function to traverse linear expressions traverse_expr_linear_to_affine() """ function expr_linear_to_affine(expr) - # The input should follow :(<=, LHS, RHS) - affdict = Dict() - isa(expr, Number) && return affdict - - if expr.args[1] in [:(==), :(>=), :(<=)] # For a constraint expression - @assert isa(expr.args[3], Float64) || isa(expr.args[3], Int) - @assert isa(expr.args[2], Expr) - # non are buffer spaces, not used anywhere - lhscoeff, lhsvars, rhs, non, non = Alp.traverse_expr_linear_to_affine(expr.args[2]) - rhs = -rhs + expr.args[3] - affdict[:sense] = expr.args[1] - - elseif expr.head == :ref # For single variable objective expression - lhscoeff = [1.0] - lhsvars = [expr] - rhs = 0 - affdict[:sense] = nothing - - else # For an objective expression - lhscoeff, lhsvars, rhs, non, non = Alp.traverse_expr_linear_to_affine(expr) - affdict[:sense] = nothing - end - - affdict[:coefs] = lhscoeff - affdict[:vars] = lhsvars - affdict[:rhs] = rhs - @assert length(affdict[:coefs]) == length(affdict[:vars]) - affdict[:cnt] = length(affdict[:coefs]) - - return affdict + # The input should follow :(<=, LHS, RHS) + affdict = Dict() + isa(expr, Number) && return affdict + + if expr.args[1] in [:(==), :(>=), :(<=)] # For a constraint expression + @assert isa(expr.args[3], Float64) || isa(expr.args[3], Int) + @assert isa(expr.args[2], Expr) + # non are buffer spaces, not used anywhere + lhscoeff, lhsvars, rhs, non, non = + Alp.traverse_expr_linear_to_affine(expr.args[2]) + rhs = -rhs + expr.args[3] + affdict[:sense] = expr.args[1] + + elseif expr.head == :ref # For single variable objective expression + lhscoeff = [1.0] + lhsvars = [expr] + rhs = 0 + affdict[:sense] = nothing + + else # For an objective expression + lhscoeff, lhsvars, rhs, non, non = Alp.traverse_expr_linear_to_affine(expr) + affdict[:sense] = nothing + end + + affdict[:coefs] = lhscoeff + affdict[:vars] = lhsvars + affdict[:rhs] = rhs + @assert length(affdict[:coefs]) == length(affdict[:vars]) + affdict[:cnt] = length(affdict[:coefs]) + + return affdict end """ @@ -296,89 +311,109 @@ traverse_expr_linear_to_affine(expr, lhscoeffs=[], lhsvars=[], rhs=0.0, bufferVa This function traverses the left hand side tree to collect affine terms. Updated status : possible to handle (x-(x+y(t-z))) cases where signs are handled properly """ -function traverse_expr_linear_to_affine(expr, lhscoeffs=[], lhsvars=[], rhs=0.0, bufferVal=nothing, bufferVar=nothing, sign=1.0, coef=1.0, level=0) - - # reversor = Dict(true => -1.0, false => 1.0) - function sign_convertor(subexpr, pos) - if length(subexpr.args) == 2 && subexpr.args[1] == :- - return -1.0 - elseif length(subexpr.args) > 2 && subexpr.args[1] == :- && pos > 2 - return -1.0 - end - return 1.0 - end - - if isa(expr, Number) # Capture any coefficients or right hand side - (bufferVal !== nothing) ? bufferVal *= expr : bufferVal = expr * coef - return lhscoeffs, lhsvars, rhs, bufferVal, bufferVar - elseif expr in [:+, :-] # TODO: what is this condition? - if bufferVal !== nothing && bufferVar !== nothing - push!(lhscoeffs, bufferVal) - push!(lhsvars, bufferVar) - bufferVal = 0.0 - bufferVar = nothing - end - return lhscoeffs, lhsvars, rhs, bufferVal, bufferVar - elseif expr in [:*] - return lhscoeffs, lhsvars, rhs, bufferVal, bufferVar - elseif expr in [:(<=), :(==), :(>=)] - return lhscoeffs, lhsvars, rhs, bufferVal, bufferVar - elseif expr.head == :ref - bufferVar = expr - return lhscoeffs, lhsvars, rhs, bufferVal, bufferVar - end - - # HOT-PATCH : Special Structure Recognition - start_pos = 1 - if (expr.args[1] == :*) && (length(expr.args) == 3) - if (isa(expr.args[2], Float64) || isa(expr.args[2], Int)) && (expr.args[3].head == :call) - (coef != 0.0) ? coef = expr.args[2] * coef : coef = expr.args[2] # Patch - # coef = expr.args[2] - start_pos = 3 - @warn "Special expression structure detected [*, coef, :call, ...]. Currently using a beta fix..." - end - end - - for i in start_pos:length(expr.args) - lhscoeff, lhsvars, rhs, bufferVal, bufferVar = traverse_expr_linear_to_affine(expr.args[i], lhscoeffs, lhsvars, rhs, bufferVal, bufferVar, sign*sign_convertor(expr, i), coef, level+1) - if expr.args[1] in [:+, :-] # Term segmentation [:-, :+], see this and wrap-up the current (linear) term - if bufferVal !== nothing && bufferVar !== nothing # (sign) * (coef) * (var) => linear term - push!(lhscoeffs, sign*sign_convertor(expr, i)*bufferVal) +function traverse_expr_linear_to_affine( + expr, + lhscoeffs = [], + lhsvars = [], + rhs = 0.0, + bufferVal = nothing, + bufferVar = nothing, + sign = 1.0, + coef = 1.0, + level = 0, +) + + # reversor = Dict(true => -1.0, false => 1.0) + function sign_convertor(subexpr, pos) + if length(subexpr.args) == 2 && subexpr.args[1] == :- + return -1.0 + elseif length(subexpr.args) > 2 && subexpr.args[1] == :- && pos > 2 + return -1.0 + end + return 1.0 + end + + if isa(expr, Number) # Capture any coefficients or right hand side + (bufferVal !== nothing) ? bufferVal *= expr : bufferVal = expr * coef + return lhscoeffs, lhsvars, rhs, bufferVal, bufferVar + elseif expr in [:+, :-] # TODO: what is this condition? + if bufferVal !== nothing && bufferVar !== nothing + push!(lhscoeffs, bufferVal) push!(lhsvars, bufferVar) - bufferVal = nothing + bufferVal = 0.0 bufferVar = nothing - end - if bufferVal !== nothing && bufferVar === nothing # (sign) * (coef) => right-hand-side term - rhs += sign*sign_convertor(expr, i)*bufferVal - bufferVal = nothing - end - if bufferVal === nothing && bufferVar !== nothing && expr.args[1] == :+ - push!(lhscoeffs, sign*1.0*coef) - push!(lhsvars, bufferVar) - bufferVar = nothing - end - if bufferVal === nothing && bufferVar !== nothing && expr.args[1] == :- - push!(lhscoeffs, sign*sign_convertor(expr, i)*coef) + end + return lhscoeffs, lhsvars, rhs, bufferVal, bufferVar + elseif expr in [:*] + return lhscoeffs, lhsvars, rhs, bufferVal, bufferVar + elseif expr in [:(<=), :(==), :(>=)] + return lhscoeffs, lhsvars, rhs, bufferVal, bufferVar + elseif expr.head == :ref + bufferVar = expr + return lhscoeffs, lhsvars, rhs, bufferVal, bufferVar + end + + # HOT-PATCH : Special Structure Recognition + start_pos = 1 + if (expr.args[1] == :*) && (length(expr.args) == 3) + if (isa(expr.args[2], Float64) || isa(expr.args[2], Int)) && + (expr.args[3].head == :call) + (coef != 0.0) ? coef = expr.args[2] * coef : coef = expr.args[2]# Patch + # coef = expr.args[2] + start_pos = 3 + @warn "Special expression structure detected [*, coef, :call, ...]. Currently using a beta fix..." + end + end + + for i in start_pos:length(expr.args) + lhscoeff, lhsvars, rhs, bufferVal, bufferVar = traverse_expr_linear_to_affine( + expr.args[i], + lhscoeffs, + lhsvars, + rhs, + bufferVal, + bufferVar, + sign * sign_convertor(expr, i), + coef, + level + 1, + ) + if expr.args[1] in [:+, :-] # Term segmentation [:-, :+], see this and wrap-up the current (linear) term + if bufferVal !== nothing && bufferVar !== nothing # (sign) * (coef) * (var) => linear term + push!(lhscoeffs, sign * sign_convertor(expr, i) * bufferVal) + push!(lhsvars, bufferVar) + bufferVal = nothing + bufferVar = nothing + end + if bufferVal !== nothing && bufferVar === nothing # (sign) * (coef) => right-hand-side term + rhs += sign * sign_convertor(expr, i) * bufferVal + bufferVal = nothing + end + if bufferVal === nothing && bufferVar !== nothing && expr.args[1] == :+ + push!(lhscoeffs, sign * 1.0 * coef) + push!(lhsvars, bufferVar) + bufferVar = nothing + end + if bufferVal === nothing && bufferVar !== nothing && expr.args[1] == :- + push!(lhscoeffs, sign * sign_convertor(expr, i) * coef) + push!(lhsvars, bufferVar) + bufferVar = nothing + end + elseif expr.args[1] in [:(<=), :(==), :(>=)] + rhs = expr.args[end] + end + end + + if level == 0 + if bufferVal !== nothing && bufferVar !== nothing + push!(lhscoeffs, bufferVal) push!(lhsvars, bufferVar) + bufferVal = nothing bufferVar = nothing - end - elseif expr.args[1] in [:(<=), :(==), :(>=)] - rhs = expr.args[end] - end - end - - if level == 0 - if bufferVal !== nothing && bufferVar !== nothing - push!(lhscoeffs, bufferVal) - push!(lhsvars, bufferVar) - bufferVal = nothing - bufferVar = nothing - end - end - - return lhscoeffs, lhsvars, rhs, bufferVal, bufferVar -end + end + end + return lhscoeffs, lhsvars, rhs, bufferVal, bufferVar +end """ This function is treats the sign in expression trees by cleaning the following structure: @@ -387,32 +422,31 @@ args ::Call || ::ref By separating the structure with some dummy treatments """ -function expr_resolve_sign(expr, level=0; kwargs...) - - isa(expr, Number) && return - resolver = Dict(:- => -1, :+ => 1) - for i in 2:length(expr.args) - if !isa(expr.args[i], Float64) && !isa(expr.args[i], Int) # Skip the coefficients - if length(expr.args[i].args) == 2 && expr.args[i].head == :call - if expr.args[i].args[1] == :- # Treatment for :(-x), replace with :(x*-1) - if expr.args[1] in [:*] # Only perform the treatment when connected with * - push!(expr.args, resolver[expr.args[i].args[1]]) - expr.args[i] = expr.args[i].args[2] - elseif expr.args[1] in [:+, :-, :(==), :(<=), :(>=)] - expr.args[i] = expr.args[i] - else - error("Unexpected operator $(expr.args[i]) during resolving sign") - end - elseif expr.args[i].args[1] == :+ # Treatment for :(+x) replace with :x - expr.args[i] = expr.args[i].args[2] +function expr_resolve_sign(expr, level = 0; kwargs...) + isa(expr, Number) && return + resolver = Dict(:- => -1, :+ => 1) + for i in 2:length(expr.args) + if !isa(expr.args[i], Float64) && !isa(expr.args[i], Int) # Skip the coefficients + if length(expr.args[i].args) == 2 && expr.args[i].head == :call + if expr.args[i].args[1] == :- # Treatment for :(-x), replace with :(x*-1) + if expr.args[1] in [:*] # Only perform the treatment when connected with * + push!(expr.args, resolver[expr.args[i].args[1]]) + expr.args[i] = expr.args[i].args[2] + elseif expr.args[1] in [:+, :-, :(==), :(<=), :(>=)] + expr.args[i] = expr.args[i] + else + error("Unexpected operator $(expr.args[i]) during resolving sign") + end + elseif expr.args[i].args[1] == :+ # Treatment for :(+x) replace with :x + expr.args[i] = expr.args[i].args[2] + end + elseif expr.args[i].head == :call + Alp.expr_resolve_sign(expr.args[i], level + 1) end - elseif expr.args[i].head == :call - Alp.expr_resolve_sign(expr.args[i], level+1) - end - end - end + end + end - return + return end """ @@ -420,29 +454,28 @@ Recursively pre-process the expression by treating the coefficients TODO: this function requires a lot of refining. Most issues can be caused by this function. """ -function expr_flatten(expr, level=0; kwargs...) - - isa(expr, Number) && return - if level > 0 # No trivial constraint is allowed "3>5" - flat = Alp.expr_arrangeargs(expr.args) - if isa(flat, Number) - return flat - else - expr.args = flat - end - end - - for i in 2:length(expr.args) - if isa(expr.args[i], Expr) && expr.args[i].head == :call - expr.args[i] = expr_flatten(expr.args[i], level+1) - end - end - - if level > 0 #Root level process, no additional processes - expr.args = Alp.expr_arrangeargs(expr.args) - end - - return expr +function expr_flatten(expr, level = 0; kwargs...) + isa(expr, Number) && return + if level > 0 # No trivial constraint is allowed "3>5" + flat = Alp.expr_arrangeargs(expr.args) + if isa(flat, Number) + return flat + else + expr.args = flat + end + end + + for i in 2:length(expr.args) + if isa(expr.args[i], Expr) && expr.args[i].head == :call + expr.args[i] = expr_flatten(expr.args[i], level + 1) + end + end + + if level > 0 #Root level process, no additional processes + expr.args = Alp.expr_arrangeargs(expr.args) + end + + return expr end """ @@ -451,206 +484,205 @@ Only consider 3 types: coefficients(Int64, Float64), :ref, :calls Sequence arrangement is dependent on operator """ function expr_arrangeargs(args::Array; kwargs...) - # A mapping used for operator treatments - reverter = Dict(true=>:-, false=>:+) - operator_coefficient_base = Dict{Symbol, Float64}( - :+ => 0.0, - :- => 0.0, - :/ => 1.0, - :* => 1.0, - :^ => 1.0 - ) - - # Treatment => Flatten pure number sub-tree - allFloats = [i for i in 2:length(args) if isa(args[i], Float64)] - if length(allFloats) == length(args)-1 - val = args[2] - for i in 3:length(args) - val = eval(args[1])(val, args[i]) - end - return val - end - - if args[1] in [:^] - return args - elseif args[1] in [:/] - # error("Alpine does not currently support `$(args[1])` operator") - if (typeof(args[3]) == Float64) || (typeof(args[3]) == Int64) - args = expr_resolve_const_denominator(args) - else - error("Alpine does not currently support `$(args[1])` operator with a variable in the denominator") - end - elseif args[1] in [:*, :+, :-] - # Such generic operators can be handled - else - error("Alpine does not currently support `$(args[1])` operator acting on a variable") - end - - if args[1] in [:*, :+, :-] - val = operator_coefficient_base[args[1]] # initialize - exprs = [] - refs = [] - - valinit = false # what is first children : needs consideration with :(-) - refinit = false - callinit = false - - for i in 2:length(args) - if isa(args[i],Float64) || isa(args[i], Int) - valinit += (i==2) - val = eval(args[1])(val, eval(reverter[(i==2) && (args[1]==:-)])(args[i])) # Revert the first sigh if (-) - elseif typeof(args[i]) == Expr - if args[i].head == :ref - refinit += (i==2) - push!(refs, args[i]) - elseif args[i].head == :call - callinit += (i==2) - push!(exprs, args[i]) + # A mapping used for operator treatments + reverter = Dict(true => :-, false => :+) + operator_coefficient_base = + Dict{Symbol,Float64}(:+ => 0.0, :- => 0.0, :/ => 1.0, :* => 1.0, :^ => 1.0) + + # Treatment => Flatten pure number sub-tree + allFloats = [i for i in 2:length(args) if isa(args[i], Float64)] + if length(allFloats) == length(args) - 1 + val = args[2] + for i in 3:length(args) + val = eval(args[1])(val, args[i]) + end + return val + end + + if args[1] in [:^] + return args + elseif args[1] in [:/] + # error("Alpine does not currently support `$(args[1])` operator") + if (typeof(args[3]) == Float64) || (typeof(args[3]) == Int64) + args = expr_resolve_const_denominator(args) + else + error( + "Alpine does not currently support `$(args[1])` operator with a variable in the denominator", + ) + end + elseif args[1] in [:*, :+, :-] + # Such generic operators can be handled + else + error( + "Alpine does not currently support `$(args[1])` operator acting on a variable", + ) + end + + if args[1] in [:*, :+, :-] + val = operator_coefficient_base[args[1]] # initialize + exprs = [] + refs = [] + + valinit = false # what is first children : needs consideration with :(-) + refinit = false + callinit = false + + for i in 2:length(args) + if isa(args[i], Float64) || isa(args[i], Int) + valinit += (i == 2) + val = eval(args[1])(val, eval(reverter[(i==2)&&(args[1]==:-)])(args[i])) # Revert the first sigh if (-) + elseif typeof(args[i]) == Expr + if args[i].head == :ref + refinit += (i == 2) + push!(refs, args[i]) + elseif args[i].head == :call + callinit += (i == 2) + push!(exprs, args[i]) + else + error("Unkown expression head") + end + else + error("Unkown argument type") + end + end + + # Treatment for 0.0 coefficients + if val == operator_coefficient_base[args[1]] && val == 0.0 + val = [] + end + + # Re-arrange children :: without actually doing anything on them + if args[1] in [:*] + return [args[1]; val; refs; exprs] + elseif args[1] in [:+, :-] + if Bool(valinit) + return [args[1]; val; refs; exprs] + elseif Bool(refinit) + return [args[1]; refs; val; exprs] + elseif Bool(callinit) + return [args[1]; exprs; refs; val] else - error("Unkown expression head") + error("Unexpected condition encountered...") end - else - error("Unkown argument type") - end - end - - # Treatment for 0.0 coefficients - if val == operator_coefficient_base[args[1]] && val == 0.0 - val = [] - end - - # Re-arrange children :: without actually doing anything on them - if args[1] in [:*] - return[args[1];val;refs;exprs] - elseif args[1] in [:+, :-] - if Bool(valinit) - return [args[1];val;refs;exprs] - elseif Bool(refinit) - return [args[1];refs;val;exprs] - elseif Bool(callinit) - return [args[1];exprs;refs;val] - else - error("Unexpected condition encountered...") - end - end - else - error("Unsupported expression arguments $args") - end - - return + end + else + error("Unsupported expression arguments $args") + end + + return end """ Check if a sub-tree is a constant or not """ function expr_resolve_const(expr) - - isa(expr, Number) && return - for i in 1:length(expr.args) - if isa(expr.args[i], Number) || isa(expr.args[i], Symbol) - continue - elseif expr.args[i].head == :call - (expr_isconst(expr.args[i])) && (expr.args[i] = eval(expr.args[i])) - if isa(expr.args[i], Number) || isa(expr.args[i], Symbol) + isa(expr, Number) && return + for i in 1:length(expr.args) + if isa(expr.args[i], Number) || isa(expr.args[i], Symbol) continue - else - expr_resolve_const(expr.args[i]) - end - end - end + elseif expr.args[i].head == :call + (expr_isconst(expr.args[i])) && (expr.args[i] = eval(expr.args[i])) + if isa(expr.args[i], Number) || isa(expr.args[i], Symbol) + continue + else + expr_resolve_const(expr.args[i]) + end + end + end - return + return end """ If the expression's fraction has a constant denominator, then replace the expression as product of a constant and the expression """ function expr_resolve_const_denominator(args) - - @assert args[1] == :/ - @assert length(args) == 3 - resolvable = true - - for i in 3:length(args) - resolvable *= Alp.expr_isconst(args[i]) - end - - if resolvable - for i in 3:length(args) - args[i]=1/eval(args[i]) - end - args[1] = :* - end - - return args + @assert args[1] == :/ + @assert length(args) == 3 + resolvable = true + + for i in 3:length(args) + resolvable *= Alp.expr_isconst(args[i]) + end + + if resolvable + for i in 3:length(args) + args[i] = 1 / eval(args[i]) + end + args[1] = :* + end + + return args end """ Check if a sub-tree(:call) is totally composed of constant values """ function expr_isconst(expr) - (isa(expr, Number) || isa(expr, Symbol)) && return true - - (expr.head == :ref) && return false - const_tree = true - for i in 1:length(expr.args) - if isa(expr.args[i], Number) || isa(expr.args[i], Symbol) - continue - elseif expr.args[i].head == :call - const_tree *= expr_isconst(expr.args[i]) - elseif expr.args[i].head == :ref - return false - end - end - - return const_tree + (isa(expr, Number) || isa(expr, Symbol)) && return true + + (expr.head == :ref) && return false + const_tree = true + for i in 1:length(expr.args) + if isa(expr.args[i], Number) || isa(expr.args[i], Symbol) + continue + elseif expr.args[i].head == :call + const_tree *= expr_isconst(expr.args[i]) + elseif expr.args[i].head == :ref + return false + end + end + + return const_tree end """ Check if a sub-tree(:call) is contains any non-integer exponent values """ function expr_isfracexp(expr) - if expr.head == :call - if length(expr.args) == 3 && expr.args[1] == :^ - if trunc(expr.args[3]) != expr.args[3] - error("Alpine currently supports ^ operator with only positive integer exponents") - end - end - for i=1:length(expr.args) - if typeof(expr.args[i]) == Expr - expr_isfracexp(expr.args[i]) # Recursively search for fractional exponents - end - end - end + if expr.head == :call + if length(expr.args) == 3 && expr.args[1] == :^ + if trunc(expr.args[3]) != expr.args[3] + error( + "Alpine currently supports ^ operator with only positive integer exponents", + ) + end + end + for i in 1:length(expr.args) + if typeof(expr.args[i]) == Expr + expr_isfracexp(expr.args[i]) # Recursively search for fractional exponents + end + end + end end # Returns true if the expression is a constant, linear or affine function expr_isaffine(expr) - Alp.expr_isconst(expr) && return true - expr.head == :ref && return true - - is_affine = false - if expr.head == :call - k=0 - for i = 1:length(expr.args) - if isa(expr.args[i], Number) - k+=1 - continue - end - if isa(expr.args[i], Symbol) - (expr.args[i] in [:+,:-]) && (k+=1) - continue - end - if expr.args[i].head == :ref - k+=1 - elseif expr.args[i].head == :call - status = Alp.expr_isaffine(expr.args[i]) - status && (k += 1) - end - end - (k == length(expr.args)) && (is_affine = true) - end - return is_affine + Alp.expr_isconst(expr) && return true + expr.head == :ref && return true + + is_affine = false + if expr.head == :call + k = 0 + for i in 1:length(expr.args) + if isa(expr.args[i], Number) + k += 1 + continue + end + if isa(expr.args[i], Symbol) + (expr.args[i] in [:+, :-]) && (k += 1) + continue + end + if expr.args[i].head == :ref + k += 1 + elseif expr.args[i].head == :call + status = Alp.expr_isaffine(expr.args[i]) + status && (k += 1) + end + end + (k == length(expr.args)) && (is_affine = true) + end + return is_affine end """ @@ -659,88 +691,108 @@ Signs in the summation can be +/- Note: This function does not support terms of type (a*(x[1] + x[2]))^2 yet. """ function expr_isolate_const(expr) - Alp.expr_isaffine(expr) && return expr - - # Check nonlinear expressions - if (expr.head == :call && expr.args[1] in [:+,:-]) - expr_array = Any[] - for i=2:length(expr.args) - ind = 0 - - # Handle negative sign in the first term - if (!isa(expr.args[i], Number)) && (expr.args[i].args[1] == :-) && (length(expr.args[i].args) == 2) - expr_i = expr.args[i].args[2] - ind = 1 - else - expr_i = expr.args[i] - end - - # Handle constant and linear terms - if (isa(expr_i, Number)) || (expr_i.head == :ref) - if ((expr.args[1] == :-) && (i > 2)) || (ind == 1) - push!(expr_array, :(-$(expr_i))) + Alp.expr_isaffine(expr) && return expr + + # Check nonlinear expressions + if (expr.head == :call && expr.args[1] in [:+, :-]) + expr_array = Any[] + for i in 2:length(expr.args) + ind = 0 + + # Handle negative sign in the first term + if (!isa(expr.args[i], Number)) && + (expr.args[i].args[1] == :-) && + (length(expr.args[i].args) == 2) + expr_i = expr.args[i].args[2] + ind = 1 else - push!(expr_array, :($(expr_i))) + expr_i = expr.args[i] end - # Handle nonlinear terms with coefficients within the exponent - elseif (expr.args[i].head == :call && expr_i.args[1] == :^ && expr_i.args[2].head == :call && isa(expr_i.args[2].args[2], Number) && isa(expr_i.args[3], Number)) - expr_tmp = Expr(:call, :^, expr_i.args[2].args[3], expr_i.args[3]) - if ((expr.args[1] == :-) && (i > 2)) || (ind == 1) - push!(expr_array, Expr(:call, :*, -expr_i.args[2].args[2] ^ expr_i.args[3], expr_tmp)) - else - push!(expr_array, Expr(:call, :*, expr_i.args[2].args[2] ^ expr_i.args[3], expr_tmp)) - end - - # Handle no-coefficients case - elseif expr_i.args[1] == :^ && expr_i.args[2].head == :ref - if (expr.args[1] == :- && (i > 2)) || (ind == 1) - push!(expr_array, Expr(:call, :*, -1, expr_i)) - else - push!(expr_array, expr_i) - end - - # Handle coefficients which are not part of the exponent - elseif expr_i.args[1] == :* && isa(expr_i.args[2], Number) - if ((expr.args[1] == :-) && (i > 2)) || (ind == 1) - #push!(expr_array, Expr(:call, :*, -expr_i.args[2], expr_i.args[3])) - push!(expr_array, Expr(:call, :*, -1, expr_i)) - else - push!(expr_array, expr_i) - end - - # Handle negative sign in the remaining terms - elseif (expr_i.args[1] in [:+,:-]) && (length(expr.args[i].args) > 2) - expr_rec = Alp.expr_isolate_const(expr_i) #recursion - push!(expr_array, expr_rec) - - # For any other terms - else - if (expr.args[1] == :- && (i > 2)) || (ind == 1) - push!(expr_array, Expr(:call, :*, -1, expr_i)) + # Handle constant and linear terms + if (isa(expr_i, Number)) || (expr_i.head == :ref) + if ((expr.args[1] == :-) && (i > 2)) || (ind == 1) + push!(expr_array, :(-$(expr_i))) + else + push!(expr_array, :($(expr_i))) + end + + # Handle nonlinear terms with coefficients within the exponent + elseif ( + expr.args[i].head == :call && + expr_i.args[1] == :^ && + expr_i.args[2].head == :call && + isa(expr_i.args[2].args[2], Number) && + isa(expr_i.args[3], Number) + ) + expr_tmp = Expr(:call, :^, expr_i.args[2].args[3], expr_i.args[3]) + if ((expr.args[1] == :-) && (i > 2)) || (ind == 1) + push!( + expr_array, + Expr(:call, :*, -expr_i.args[2].args[2]^expr_i.args[3], expr_tmp), + ) + else + push!( + expr_array, + Expr(:call, :*, expr_i.args[2].args[2]^expr_i.args[3], expr_tmp), + ) + end + + # Handle no-coefficients case + elseif expr_i.args[1] == :^ && expr_i.args[2].head == :ref + if (expr.args[1] == :- && (i > 2)) || (ind == 1) + push!(expr_array, Expr(:call, :*, -1, expr_i)) + else + push!(expr_array, expr_i) + end + + # Handle coefficients which are not part of the exponent + elseif expr_i.args[1] == :* && isa(expr_i.args[2], Number) + if ((expr.args[1] == :-) && (i > 2)) || (ind == 1) + #push!(expr_array, Expr(:call, :*, -expr_i.args[2], expr_i.args[3])) + push!(expr_array, Expr(:call, :*, -1, expr_i)) + else + push!(expr_array, expr_i) + end + + # Handle negative sign in the remaining terms + elseif (expr_i.args[1] in [:+, :-]) && (length(expr.args[i].args) > 2) + expr_rec = Alp.expr_isolate_const(expr_i) #recursion + push!(expr_array, expr_rec) + + # For any other terms else - push!(expr_array, expr_i) + if (expr.args[1] == :- && (i > 2)) || (ind == 1) + push!(expr_array, Expr(:call, :*, -1, expr_i)) + else + push!(expr_array, expr_i) + end end - end - end - - # Construct the expression from the array - if length(expr_array) == 1 - return expr_array[1] - else - expr_n = Expr(:call, :+, expr_array[1], expr_array[2]) - if length(expr_array) >= 3 - for i = 3:length(expr_array) - expr_n = Expr(:call, :+, expr_n, expr_array[i]) + end + + # Construct the expression from the array + if length(expr_array) == 1 + return expr_array[1] + else + expr_n = Expr(:call, :+, expr_array[1], expr_array[2]) + if length(expr_array) >= 3 + for i in 3:length(expr_array) + expr_n = Expr(:call, :+, expr_n, expr_array[i]) + end end - end - return(expr_n) - end - - elseif (expr.head == :call && expr.args[1] == :^ && expr.args[2].head == :call && isa(expr.args[2].args[2], Number) && isa(expr.args[3], Number)) - expr_tmp = Expr(:call, :^, expr.args[2].args[3], expr.args[3]) - return(Expr(:call, :*, expr.args[2].args[2] ^ expr.args[3], expr_tmp)) - else - return expr - end + return (expr_n) + end + + elseif ( + expr.head == :call && + expr.args[1] == :^ && + expr.args[2].head == :call && + isa(expr.args[2].args[2], Number) && + isa(expr.args[3], Number) + ) + expr_tmp = Expr(:call, :^, expr.args[2].args[3], expr.args[3]) + return (Expr(:call, :*, expr.args[2].args[2]^expr.args[3], expr_tmp)) + else + return expr + end end diff --git a/src/operators.jl b/src/operators.jl index 6399873f..cd7751d8 100644 --- a/src/operators.jl +++ b/src/operators.jl @@ -3,16 +3,15 @@ Recognize and process nonlinear terms in an expression """ -function expr_term_parsing(expr::Any, constr_id::Int, m::Optimizer, level=0; options...) - - isa(expr, Number) && return expr +function expr_term_parsing(expr::Any, constr_id::Int, m::Optimizer, level = 0; options...) + isa(expr, Number) && return expr cnt = 0 for node in expr.args cnt += 1 if isa(node, Float64) || isa(node, Int64) || isa(node, Symbol) continue elseif node.head == :call - expr.args[cnt] = Alp.expr_term_parsing(node, constr_id, m, level+1) + expr.args[cnt] = Alp.expr_term_parsing(node, constr_id, m, level + 1) elseif node.head == :ref continue else @@ -66,39 +65,50 @@ function detect_nonconvex_terms(expr::Any, constr_id::Int, m::Optimizer; kwargs. return expr # if no structure is detected, simply return the original tree end -function store_nonconvex_term(m::Optimizer, nl_key::Any, var_idxs::Any, term_type::Symbol, operator::Symbol, evaluator::Function, bd_resolver::Function, discvar_collector::Function) - +function store_nonconvex_term( + m::Optimizer, + nl_key::Any, + var_idxs::Any, + term_type::Symbol, + operator::Symbol, + evaluator::Function, + bd_resolver::Function, + discvar_collector::Function, +) l_cnt = length(keys(m.linear_terms)) nl_cnt = length(keys(m.nonconvex_terms)) - y_idx = m.num_var_orig + nl_cnt + l_cnt + 1 # y is always lifted var + y_idx = m.num_var_orig + nl_cnt + l_cnt + 1 # y is always lifted var lifted_var_ref = Expr(:ref, :x, y_idx) lifted_constr_ref = Alp.build_constr_block(y_idx, var_idxs, operator) - m.nonconvex_terms[nl_key] = Dict(:lifted_var_ref => lifted_var_ref, - :id => nl_cnt + 1, - :y_idx => y_idx, - :y_type => Alp.resolve_lifted_var_type([m.var_type[k] for k in var_idxs], operator), - :var_idxs => var_idxs, - :ref => nl_key, - :evaluator => evaluator, - :lifted_constr_ref => lifted_constr_ref, - :constr_id => Set(), - :nonlinear_type => term_type, - :convexified => false, - :bound_resolver => bd_resolver, - :discvar_collector => discvar_collector) + m.nonconvex_terms[nl_key] = Dict( + :lifted_var_ref => lifted_var_ref, + :id => nl_cnt + 1, + :y_idx => y_idx, + :y_type => + Alp.resolve_lifted_var_type([m.var_type[k] for k in var_idxs], operator), + :var_idxs => var_idxs, + :ref => nl_key, + :evaluator => evaluator, + :lifted_constr_ref => lifted_constr_ref, + :constr_id => Set(), + :nonlinear_type => term_type, + :convexified => false, + :bound_resolver => bd_resolver, + :discvar_collector => discvar_collector, + ) m.term_seq[nl_cnt+l_cnt+1] = nl_key # Assistive information # push!(m.var_type, :Cont) # TODO check if this replacement is good since additional constraints should be able to sufficiently constraint the type push!(m.var_type, m.nonconvex_terms[nl_key][:y_type]) # Keep track of the lifted var type - Alp.get_option(m, :log_level) > 199 && println("found lifted $(term_type) term $(lifted_constr_ref)") + Alp.get_option(m, :log_level) > 199 && + println("found lifted $(term_type) term $(lifted_constr_ref)") return y_idx end function store_linear_term(m::Optimizer, term_key::Any, expr::Any)#, bound_resolver::Function) - l_cnt = length(keys(m.linear_terms)) nl_cnt = length(keys(m.nonconvex_terms)) @@ -107,19 +117,25 @@ function store_linear_term(m::Optimizer, term_key::Any, expr::Any)#, bound_resol lifted_var_ref = Expr(:ref, :x, y_idx) lifted_constr_ref = Expr(:call, :(==), lifted_var_ref, expr) - m.linear_terms[term_key] = Dict(:lifted_var_ref => lifted_var_ref, - :id => length(keys(m.linear_terms)) + 1, - :ref => term_key, - :y_idx => y_idx, - :y_type => Alp.resolve_lifted_var_type([m.var_type[k[2]] for k in term_key[:coef_var]], :+), - :evaluator => linear, - :lifted_constr_ref => lifted_constr_ref, - :constr_id => Set(), - :bound_resolver => nothing) - - m.term_seq[l_cnt+nl_cnt + 1] = term_key + m.linear_terms[term_key] = Dict( + :lifted_var_ref => lifted_var_ref, + :id => length(keys(m.linear_terms)) + 1, + :ref => term_key, + :y_idx => y_idx, + :y_type => Alp.resolve_lifted_var_type( + [m.var_type[k[2]] for k in term_key[:coef_var]], + :+, + ), + :evaluator => linear, + :lifted_constr_ref => lifted_constr_ref, + :constr_id => Set(), + :bound_resolver => nothing, + ) + + m.term_seq[l_cnt+nl_cnt+1] = term_key push!(m.var_type, m.linear_terms[term_key][:y_type]) # Keep track of the lifted var type - Alp.get_option(m, :log_level) > 199 && println("found lifted linear term $(lifted_var_ref) = $expr") + Alp.get_option(m, :log_level) > 199 && + println("found lifted linear term $(lifted_var_ref) = $expr") return y_idx end @@ -135,7 +151,6 @@ function lift_nonconvex_term(m::Optimizer, nl_key, constr_id::Int, scalar = 1.0) end function lift_linear_term(m::Optimizer, term_key, constr_id::Int) - push!(m.linear_terms[term_key][:constr_id], constr_id) return m.linear_terms[term_key][:lifted_var_ref] @@ -143,7 +158,6 @@ function lift_linear_term(m::Optimizer, term_key, constr_id::Int) end function detect_linear_term(expr::Any, constr_id::Int, m::Optimizer) - @assert (expr.head == :call || expr.head == :ref) coef_fetch = Dict(:+ => 1.0, :- => -1.0) @@ -156,42 +170,57 @@ function detect_linear_term(expr::Any, constr_id::Int, m::Optimizer) scalar = 0.0 coef_var = Set() for i in 2:length(expr.args) # TODO: Consider recursive operation - if isa(expr.args[i], Float64) || isa(expr.args[i], Int) - (i == 2) ? scalar=expr.args[i] : scalar+=coef_fetch[expr.args[1]]*expr.args[i] + (i == 2) ? scalar = expr.args[i] : + scalar += coef_fetch[expr.args[1]] * expr.args[i] continue end (isa(expr.args[i], Symbol)) && continue #should never happen - if (expr.args[i].head==:ref) && isa(expr.args[i].args[2], Int) - (i == 2) ? push!(coef_var, (1.0, expr.args[i].args[2])) : push!(coef_var, (coef_fetch[expr.args[1]],expr.args[i].args[2])) + if (expr.args[i].head == :ref) && isa(expr.args[i].args[2], Int) + (i == 2) ? push!(coef_var, (1.0, expr.args[i].args[2])) : + push!(coef_var, (coef_fetch[expr.args[1]], expr.args[i].args[2])) continue end # Specical Check - if expr.args[i].head == :call && expr.args[i].args[1] == :* && length(expr.args[i].args) == 3 - sub_coef = [j for j in expr.args[i].args if (isa(j, Int) || isa(j, Float64))] - sub_vars = [j.args[2] for j in expr.args[i].args if ((:head in fieldnames(typeof(j))) && j.head == :ref)] + if expr.args[i].head == :call && + expr.args[i].args[1] == :* && + length(expr.args[i].args) == 3 + sub_coef = + [j for j in expr.args[i].args if (isa(j, Int) || isa(j, Float64))] + sub_vars = [ + j.args[2] for j in expr.args[i].args if + ((:head in fieldnames(typeof(j))) && j.head == :ref) + ] (isempty(sub_coef) || isempty(sub_vars)) && return false, expr (length(sub_coef) != 1 || length(sub_vars) != 1) && return false, expr - (i == 2) ? push!(coef_var, (1.0*sub_coef[1], sub_vars[1])) : push!(coef_var, (coef_fetch[expr.args[1]]*sub_coef[1], sub_vars[1])) + (i == 2) ? push!(coef_var, (1.0 * sub_coef[1], sub_vars[1])) : + push!(coef_var, (coef_fetch[expr.args[1]] * sub_coef[1], sub_vars[1])) continue end # General Check - if expr.args[i].head == :call && expr.args[i].args[1] in [:-,:+] && length(expr.args[i].args) == 2 # resolve -(2) or -(x) terms + if expr.args[i].head == :call && + expr.args[i].args[1] in [:-, :+] && + length(expr.args[i].args) == 2 # resolve -(2) or -(x) terms expr.args[i].args[1] == :+ ? sub_coef = [1.0] : sub_coef = [-1.0] - sub_vars = [j.args[2] for j in expr.args[i].args if ((:head in fieldnames(typeof(j))) && j.head == :ref)] + sub_vars = [ + j.args[2] for j in expr.args[i].args if + ((:head in fieldnames(typeof(j))) && j.head == :ref) + ] isempty(sub_vars) && return false, expr length(sub_vars) != 1 && return false, expr - (i == 2) ? push!(coef_var, (1.0*sub_coef[1], sub_vars[1])) : push!(coef_var, (coef_fetch[expr.args[1]]*sub_coef[1], sub_vars[1])) + (i == 2) ? push!(coef_var, (1.0 * sub_coef[1], sub_vars[1])) : + push!(coef_var, (coef_fetch[expr.args[1]] * sub_coef[1], sub_vars[1])) else - down_check, linear_lift_var = Alp.detect_linear_term(expr.args[i], constr_id, m) # Recursive detection + down_check, linear_lift_var = + Alp.detect_linear_term(expr.args[i], constr_id, m) # Recursive detection down_check ? expr.args[i] = linear_lift_var : return false, expr push!(coef_var, (1.0, expr.args[i].args[2])) end end # By reaching here, it is already certain that we have found the term, always treat with :+ - term_key = Dict(:scalar=>scalar, :coef_var=>coef_var, :sign=>:+) + term_key = Dict(:scalar => scalar, :coef_var => coef_var, :sign => :+) term_key in keys(m.linear_terms) || Alp.store_linear_term(m, term_key, expr) return true, Alp.lift_linear_term(m, term_key, constr_id) elseif expr.args[1] in [:*] && length(expr.args) == 3 @@ -200,13 +229,16 @@ function detect_linear_term(expr::Any, constr_id::Int, m::Optimizer) coef_var = Set() sub_coef = [i for i in expr.args if (isa(i, Int) || isa(i, Float64))] - sub_vars = [i.args[2] for i in expr.args if ((:head in fieldnames(typeof(i))) && i.head == :ref)] + sub_vars = [ + i.args[2] for + i in expr.args if ((:head in fieldnames(typeof(i))) && i.head == :ref) + ] (isempty(sub_coef) || isempty(sub_vars)) && return false, expr (length(sub_coef) != 1 || length(sub_vars) != 1) && return false, expr - push!(coef_var, (1.0*sub_coef[1], sub_vars[1])) + push!(coef_var, (1.0 * sub_coef[1], sub_vars[1])) # By reaching here, it is already certain that we have found the term, always treat with :+ - term_key = Dict(:scalar=>scalar, :coef_var=>coef_var, :sign=>:+) + term_key = Dict(:scalar => scalar, :coef_var => coef_var, :sign => :+) term_key in keys(m.linear_terms) || Alp.store_linear_term(m, term_key, expr) return true, Alp.lift_linear_term(m, term_key, constr_id) end @@ -215,15 +247,16 @@ function detect_linear_term(expr::Any, constr_id::Int, m::Optimizer) end function basic_linear_bounds(m::Optimizer, k::Any, linear_terms = nothing) - linear_terms === nothing ? linear_terms = m.linear_terms : linear_term = linear_terms lifted_idx = linear_terms[k][:y_idx] ub = 0.0 lb = 0.0 for j in linear_terms[k][:ref][:coef_var] - (j[1] > 0.0) ? ub += abs(j[1])*m.u_var_tight[j[2]] : ub -= abs(j[1])*m.l_var_tight[j[2]] - (j[1] > 0.0) ? lb += abs(j[1])*m.l_var_tight[j[2]] : lb -= abs(j[1])*m.u_var_tight[j[2]] + (j[1] > 0.0) ? ub += abs(j[1]) * m.u_var_tight[j[2]] : + ub -= abs(j[1]) * m.l_var_tight[j[2]] + (j[1] > 0.0) ? lb += abs(j[1]) * m.l_var_tight[j[2]] : + lb -= abs(j[1]) * m.u_var_tight[j[2]] end lb += linear_terms[k][:ref][:scalar] ub += linear_terms[k][:ref][:scalar] @@ -238,13 +271,12 @@ function basic_linear_bounds(m::Optimizer, k::Any, linear_terms = nothing) end function basic_linear_bounds(m::Optimizer, k::Any, d::Dict) - lifted_idx = m.linear_terms[k][:y_idx] ub = 0.0 lb = 0.0 for j in m.linear_terms[k][:ref][:coef_var] - (j[1] > 0.0) ? ub += abs(j[1])*d[j[2]][end] : ub -= abs(j[1])*d[j[2]][1] - (j[1] > 0.0) ? lb += abs(j[1])*d[j[2]][1] : lb -= abs(j[1])*d[j[2]][end] + (j[1] > 0.0) ? ub += abs(j[1]) * d[j[2]][end] : ub -= abs(j[1]) * d[j[2]][1] + (j[1] > 0.0) ? lb += abs(j[1]) * d[j[2]][1] : lb -= abs(j[1]) * d[j[2]][end] end lb += m.linear_terms[k][:ref][:scalar] ub += m.linear_terms[k][:ref][:scalar] @@ -259,16 +291,17 @@ function basic_linear_bounds(m::Optimizer, k::Any, d::Dict) return d end - ## Evaluators ## -bpml(k,vec) = prod([vec[i] for i in k[:var_idxs]]) +bpml(k, vec) = prod([vec[i] for i in k[:var_idxs]]) discretemulti(k, vec) = prod([vec[i] for i in k[:var_idxs]]) binprod(k, vec) = prod([vec[i] for i in k[:var_idxs]]) -binlin(k,vec) = prod([vec[i] for i in k[:var_idxs]]) -bilinear(k,vec) = prod([vec[i] for i in k[:var_idxs]]) -multilinear(k,vec) = prod([vec[i] for i in k[:var_idxs]]) +binlin(k, vec) = prod([vec[i] for i in k[:var_idxs]]) +bilinear(k, vec) = prod([vec[i] for i in k[:var_idxs]]) +multilinear(k, vec) = prod([vec[i] for i in k[:var_idxs]]) monomial(k, vec) = vec[k[:var_idxs][1]]^2 -linear(k, vec) = k[:ref][:scalar] .+ sum([i[1]*vec[i[2]] for i in k[:ref][:coef_var]]) +function linear(k, vec) + return k[:ref][:scalar] .+ sum([i[1] * vec[i[2]] for i in k[:ref][:coef_var]]) +end """ Recognize prodcuts of binary variables and multilinear products @@ -294,10 +327,15 @@ function detect_discretemulti_term(expr::Any, constr_id::Int, m::Optimizer) continue end (isa(expr.args[i], Symbol)) && continue - (expr.args[i].head == :ref) && isa(expr.args[i].args[2], Int) && push!(var_idxs, expr.args[i].args[2]) - (expr.args[i].head == :ref) && isa(expr.args[i].args[2], Int) && push!(var_types, m.var_type[expr.args[i].args[2]]) + (expr.args[i].head == :ref) && + isa(expr.args[i].args[2], Int) && + push!(var_idxs, expr.args[i].args[2]) + (expr.args[i].head == :ref) && + isa(expr.args[i].args[2], Int) && + push!(var_types, m.var_type[expr.args[i].args[2]]) if (expr.args[i].head == :call) - down_check, linear_lift_var = Alp.detect_linear_term(expr.args[i], constr_id, m) + down_check, linear_lift_var = + Alp.detect_linear_term(expr.args[i], constr_id, m) !down_check && return false, expr push!(var_idxs, linear_lift_var.args[2]) push!(var_types, m.var_type[linear_lift_var.args[2]]) @@ -357,7 +395,16 @@ function detect_discretemulti_term(expr::Any, constr_id::Int, m::Optimizer) if ip_idx < 0 # binlin term if no integer variable binlin_key = [Expr(:ref, :x, bp_idx), Expr(:ref, :x, ml_idx)] binlin_idxs = [bp_idx; ml_idx] - binlin_key in keys(m.nonconvex_terms) || Alp.store_nonconvex_term(m, binlin_key, binlin_idxs, :BINLIN, :*, binlin, basic_binlin_bounds, collect_binlin_discvar) + binlin_key in keys(m.nonconvex_terms) || Alp.store_nonconvex_term( + m, + binlin_key, + binlin_idxs, + :BINLIN, + :*, + binlin, + basic_binlin_bounds, + collect_binlin_discvar, + ) return true, Alp.lift_nonconvex_term(m, binlin_key, constr_id, scalar) end @@ -365,7 +412,16 @@ function detect_discretemulti_term(expr::Any, constr_id::Int, m::Optimizer) binlin_key = [Expr(:ref, :x, bp_idx)] # binlin_idxs = [bp_idx; intlin_idx] binlin_idxs = [bp_idx] - binlin_key in keys(m.nonconvex_terms) || Alp.store_nonconvex_term(m, binlin_key, binlin_idxs, :BINLIN, :*, binlin, basic_binlin_bounds, collect_binlin_discvar) + binlin_key in keys(m.nonconvex_terms) || Alp.store_nonconvex_term( + m, + binlin_key, + binlin_idxs, + :BINLIN, + :*, + binlin, + basic_binlin_bounds, + collect_binlin_discvar, + ) return true, Alp.lift_nonconvex_term(m, binlin_key, constr_id, scalar) end @@ -373,7 +429,6 @@ function detect_discretemulti_term(expr::Any, constr_id::Int, m::Optimizer) end function basic_binlin_bounds(m::Optimizer, k::Any) - lifted_idx = m.nonconvex_terms[k][:y_idx] prod_idxs = [i for i in m.nonconvex_terms[k][:var_idxs] if m.var_type[i] == :Cont] @@ -395,7 +450,6 @@ function basic_binlin_bounds(m::Optimizer, k::Any) end function basic_binlin_bounds(m::Optimizer, k::Any, d::Dict) - lifted_idx = m.nonconvex_terms[k][:y_idx] prod_idxs = [i for i in m.nonconvex_terms[k][:var_idxs] if m.var_type[i] == :Cont] @@ -416,7 +470,7 @@ function basic_binlin_bounds(m::Optimizer, k::Any, d::Dict) return d end -function collect_binlin_discvar(m::Optimizer, k::Any; var_bowl=nothing) +function collect_binlin_discvar(m::Optimizer, k::Any; var_bowl = nothing) # Exact linearization exists return end @@ -425,7 +479,6 @@ end Recognize products of binary variables : x1 * x2 * .. * xN """ function detect_binprod_term(expr::Any, constr_id::Int, m::Optimizer) - @assert (expr.head == :call || expr.head == :ref) if (expr.args[1] == :*) # Pattern: coefficients * x * y * z ..., where x, y, z are all binary variables @@ -437,10 +490,13 @@ function detect_binprod_term(expr::Any, constr_id::Int, m::Optimizer) continue end (isa(expr.args[i], Symbol)) && continue - (expr.args[i].head == :ref) && isa(expr.args[i].args[2], Int) && push!(var_idxs, expr.args[i].args[2]) + (expr.args[i].head == :ref) && + isa(expr.args[i].args[2], Int) && + push!(var_idxs, expr.args[i].args[2]) !isempty(var_idxs) && m.var_type[var_idxs[end]] != :Bin && return false, expr if (expr.args[i].head == :call) - down_check, linear_lift_var = Alp.detect_linear_term(expr.args[i], constr_id, m) + down_check, linear_lift_var = + Alp.detect_linear_term(expr.args[i], constr_id, m) !down_check && return false, expr m.var_type[linear_lift_var.args[2]] != :Bin && return false, expr push!(var_idxs, linear_lift_var.args[2]) @@ -449,7 +505,16 @@ function detect_binprod_term(expr::Any, constr_id::Int, m::Optimizer) end if length(var_idxs) >= 2 term_key = [Expr(:ref, :x, idx) for idx in var_idxs] - term_key in keys(m.nonconvex_terms) || Alp.store_nonconvex_term(m, term_key, var_idxs, :BINPROD, :*, binprod, basic_binprod_bounds, collect_binprod_discvar) + term_key in keys(m.nonconvex_terms) || Alp.store_nonconvex_term( + m, + term_key, + var_idxs, + :BINPROD, + :*, + binprod, + basic_binprod_bounds, + collect_binprod_discvar, + ) return true, Alp.lift_nonconvex_term(m, term_key, constr_id, scalar) end elseif (expr.args[1] == :^) && length(expr.args) == 3 @@ -463,10 +528,13 @@ function detect_binprod_term(expr::Any, constr_id::Int, m::Optimizer) continue end (isa(expr.args[i], Symbol)) && continue - (expr.args[i].head == :ref) && isa(expr.args[i].args[2], Int) && push!(var_idxs, expr.args[i].args[2]) + (expr.args[i].head == :ref) && + isa(expr.args[i].args[2], Int) && + push!(var_idxs, expr.args[i].args[2]) !isempty(var_idxs) && m.var_type[var_idxs[end]] != :Bin && return false, expr if (expr.args[i].head == :call) - down_check, linear_lift_var = Alp.detect_linear_term(expr.args[i], constr_id, m) + down_check, linear_lift_var = + Alp.detect_linear_term(expr.args[i], constr_id, m) !down_check && return false, expr m.var_type[linear_lift_var.args[2]] != :Bin && return false, expr push!(var_idxs, linear_lift_var.args[2]) @@ -475,7 +543,16 @@ function detect_binprod_term(expr::Any, constr_id::Int, m::Optimizer) end if length(var_idxs) == 1 && power_scalar > 2.0 && mod(power_scalar, 1.0) == 0.0 term_key = [Expr(:ref, :x, var_idxs[1]) for i in 1:power_scalar] - term_key in keys(m.nonconvex_terms) || Alp.store_nonconvex_term(m, term_key, var_idxs, :BINPROD, :*, binprod, basic_binprod_bounds, collect_binprod_discvar) + term_key in keys(m.nonconvex_terms) || Alp.store_nonconvex_term( + m, + term_key, + var_idxs, + :BINPROD, + :*, + binprod, + basic_binprod_bounds, + collect_binprod_discvar, + ) return true, Alp.lift_nonconvex_term(m, term_key, constr_id, scalar) end end @@ -484,7 +561,6 @@ function detect_binprod_term(expr::Any, constr_id::Int, m::Optimizer) end function basic_binprod_bounds(m::Optimizer, k::Any) - lifted_idx = m.nonconvex_terms[k][:lifted_var_ref].args[2] m.l_var_tight[lifted_idx] = 0 m.u_var_tight[lifted_idx] = 1 @@ -493,7 +569,6 @@ function basic_binprod_bounds(m::Optimizer, k::Any) end function basic_binprod_bounds(m::Optimizer, k::Any, d::Dict) - lifted_idx = m.nonconvex_terms[k][:lifted_var_ref].args[2] d[lifted_idx][1] = 0 d[lifted_idx][end] = 1 @@ -501,12 +576,11 @@ function basic_binprod_bounds(m::Optimizer, k::Any, d::Dict) return d end -function collect_binprod_discvar(m::Optimizer, k::Any; var_bowl=nothing) +function collect_binprod_discvar(m::Optimizer, k::Any; var_bowl = nothing) # Exact linearization exists return end - """ Future MONOMIAL Cluster Recognize bilinear terms: x * y, where x and y are continous variables @@ -514,7 +588,6 @@ end Recognize monomial terms: x^2 or x * x, where x is continuous """ function detect_bilinear_term(expr::Any, constr_id::Int, m::Optimizer) - @assert (expr.head == :call || expr.head == :ref) if (expr.args[1] == :*) # confirm head (:*) # ----- Pattern : coefficient * x * y ------ # @@ -527,13 +600,18 @@ function detect_bilinear_term(expr::Any, constr_id::Int, m::Optimizer) continue end (isa(expr.args[i], Symbol)) && continue - (expr.args[i].head == :ref) && isa(expr.args[i].args[2], Int) && push!(var_idxs, expr.args[i].args[2]) - !isempty(var_idxs) && m.var_type[var_idxs[end]] in [:Bin, :Int] && return false ,expr # Don't consider the discrete variable + (expr.args[i].head == :ref) && + isa(expr.args[i].args[2], Int) && + push!(var_idxs, expr.args[i].args[2]) + !isempty(var_idxs) && + m.var_type[var_idxs[end]] in [:Bin, :Int] && + return false, expr # Don't consider the discrete variable if (expr.args[i].head == :call) - down_check, linear_lift_var = Alp.detect_linear_term(expr.args[i], constr_id, m) + down_check, linear_lift_var = + Alp.detect_linear_term(expr.args[i], constr_id, m) !down_check && return false, expr push!(var_idxs, linear_lift_var.args[2]) - m.var_type[var_idxs[end]] in [:Bin, :Int] && return false ,expr # Don't consider the discrete variable + m.var_type[var_idxs[end]] in [:Bin, :Int] && return false, expr # Don't consider the discrete variable continue end end @@ -541,11 +619,22 @@ function detect_bilinear_term(expr::Any, constr_id::Int, m::Optimizer) # Cofirm detection of patter A and perform store & lifting procedures if (length(var_idxs) == 2) && length(Set(var_idxs)) == 2 term_key = [Expr(:ref, :x, var_idxs[1]), Expr(:ref, :x, var_idxs[2])] - if term_key in keys(m.nonconvex_terms) || reverse(term_key) in keys(m.nonconvex_terms) - term_key in keys(m.nonconvex_terms) ? term_key = term_key : term_key = reverse(term_key) + if term_key in keys(m.nonconvex_terms) || + reverse(term_key) in keys(m.nonconvex_terms) + term_key in keys(m.nonconvex_terms) ? term_key = term_key : + term_key = reverse(term_key) return true, Alp.lift_nonconvex_term(m, term_key, constr_id, scalar) else - Alp.store_nonconvex_term(m, term_key, var_idxs, :BILINEAR, :*, bilinear, Alp.basic_monomial_bounds, collect_monomial_discvar) + Alp.store_nonconvex_term( + m, + term_key, + var_idxs, + :BILINEAR, + :*, + bilinear, + Alp.basic_monomial_bounds, + collect_monomial_discvar, + ) return true, Alp.lift_nonconvex_term(m, term_key, constr_id, scalar) end end @@ -555,7 +644,6 @@ function detect_bilinear_term(expr::Any, constr_id::Int, m::Optimizer) end function detect_multilinear_term(expr::Any, constr_id::Int, m::Optimizer) - @assert (expr.head == :call || expr.head == :ref) if (expr.args[1] == :*) # Pattern: coefficients * x * y * z ... var_idxs = [] @@ -566,19 +654,33 @@ function detect_multilinear_term(expr::Any, constr_id::Int, m::Optimizer) continue end (isa(expr.args[i], Symbol)) && continue - (expr.args[i].head == :ref) && isa(expr.args[i].args[2], Int) && push!(var_idxs, expr.args[i].args[2]) - !isempty(var_idxs) && m.var_type[var_idxs[end]] in [:Bin, :Int] && return false ,expr + (expr.args[i].head == :ref) && + isa(expr.args[i].args[2], Int) && + push!(var_idxs, expr.args[i].args[2]) + !isempty(var_idxs) && + m.var_type[var_idxs[end]] in [:Bin, :Int] && + return false, expr if (expr.args[i].head == :call) - down_check, linear_lift_var = Alp.detect_linear_term(expr.args[i], constr_id, m) + down_check, linear_lift_var = + Alp.detect_linear_term(expr.args[i], constr_id, m) !down_check && return false, expr push!(var_idxs, linear_lift_var.args[2]) - m.var_type[var_idxs[end]] in [:Bin, :Int] && return false ,expr + m.var_type[var_idxs[end]] in [:Bin, :Int] && return false, expr continue end end if length(var_idxs) > 2 term_key = [Expr(:ref, :x, idx) for idx in var_idxs] - term_key in keys(m.nonconvex_terms) || Alp.store_nonconvex_term(m, term_key, var_idxs, :MULTILINEAR, :*, multilinear, Alp.basic_monomial_bounds, collect_monomial_discvar) + term_key in keys(m.nonconvex_terms) || Alp.store_nonconvex_term( + m, + term_key, + var_idxs, + :MULTILINEAR, + :*, + multilinear, + Alp.basic_monomial_bounds, + collect_monomial_discvar, + ) return true, Alp.lift_nonconvex_term(m, term_key, constr_id, scalar) end elseif (expr.args[1] == :^) && length(expr.args) == 3 # Pattern: (x)^(>2) @@ -591,19 +693,33 @@ function detect_multilinear_term(expr::Any, constr_id::Int, m::Optimizer) continue end (isa(expr.args[i], Symbol)) && continue - (expr.args[i].head == :ref) && isa(expr.args[i].args[2], Int) && push!(var_idxs, expr.args[i].args[2]) - !isempty(var_idxs) && m.var_type[var_idxs[end]] in [:Bin, :Int] && return false ,expr # Avoid fetching terms with discrete variables + (expr.args[i].head == :ref) && + isa(expr.args[i].args[2], Int) && + push!(var_idxs, expr.args[i].args[2]) + !isempty(var_idxs) && + m.var_type[var_idxs[end]] in [:Bin, :Int] && + return false, expr # Avoid fetching terms with discrete variables if (expr.args[i].head == :call) - down_check, linear_lift_var = Alp.detect_linear_term(expr.args[i], constr_id, m) + down_check, linear_lift_var = + Alp.detect_linear_term(expr.args[i], constr_id, m) !down_check && return false, expr push!(var_idxs, linear_lift_var.args[2]) - m.var_type[var_idxs[end]] in [:Bin, :Int] && return false ,expr + m.var_type[var_idxs[end]] in [:Bin, :Int] && return false, expr continue end end if length(var_idxs) == 1 && power_scalar > 2.0 && mod(power_scalar, 1.0) == 0.0 term_key = [Expr(:ref, :x, var_idxs[1]) for i in 1:power_scalar] - term_key in keys(m.nonconvex_terms) || Alp.store_nonconvex_term(m, term_key, var_idxs, :MULTILINEAR, :*, multilinear, Alp.basic_monomial_bounds, collect_monomial_discvar) + term_key in keys(m.nonconvex_terms) || Alp.store_nonconvex_term( + m, + term_key, + var_idxs, + :MULTILINEAR, + :*, + multilinear, + Alp.basic_monomial_bounds, + collect_monomial_discvar, + ) return true, Alp.lift_nonconvex_term(m, term_key, constr_id, scalar) end end @@ -612,7 +728,6 @@ function detect_multilinear_term(expr::Any, constr_id::Int, m::Optimizer) end function detect_monomial_term(expr::Any, constr_id::Int, m::Optimizer) - if (expr.args[1] == :^) && length(expr.args) == 3 # Pattern: (x)^(2) var_idxs = [] @@ -624,25 +739,39 @@ function detect_monomial_term(expr::Any, constr_id::Int, m::Optimizer) continue end (isa(expr.args[i], Symbol)) && continue - (expr.args[i].head == :ref) && isa(expr.args[i].args[2], Int) && push!(var_idxs, expr.args[i].args[2]) - !isempty(var_idxs) && m.var_type[var_idxs[end]] in [:Bin, :Int] && return false ,expr # Avoid fetching terms with discrete variables + (expr.args[i].head == :ref) && + isa(expr.args[i].args[2], Int) && + push!(var_idxs, expr.args[i].args[2]) + !isempty(var_idxs) && + m.var_type[var_idxs[end]] in [:Bin, :Int] && + return false, expr # Avoid fetching terms with discrete variables if (expr.args[i].head == :call) - down_check, linear_lift_var = Alp.detect_linear_term(expr.args[i], constr_id, m) + down_check, linear_lift_var = + Alp.detect_linear_term(expr.args[i], constr_id, m) !down_check && return false, expr push!(var_idxs, linear_lift_var.args[2]) - m.var_type[var_idxs[end]] in [:Bin, :Int] && return false ,expr # Avoid fetching terms with discrete variables + m.var_type[var_idxs[end]] in [:Bin, :Int] && return false, expr # Avoid fetching terms with discrete variables continue end end # Detect 1.0 in the exponent and return only the variable - if length(var_idxs) == 1 && power_scalar == 1.0 + if length(var_idxs) == 1 && power_scalar == 1.0 return false, Expr(:call, expr.args[2]) - end - + end + if length(var_idxs) == 1 && power_scalar == 2.0 term_key = [Expr(:ref, :x, var_idxs[1]) for i in 1:2] - term_key in keys(m.nonconvex_terms) || Alp.store_nonconvex_term(m, term_key, var_idxs, :MONOMIAL, :*, monomial, Alp.basic_monomial_bounds, collect_monomial_discvar) + term_key in keys(m.nonconvex_terms) || Alp.store_nonconvex_term( + m, + term_key, + var_idxs, + :MONOMIAL, + :*, + monomial, + Alp.basic_monomial_bounds, + collect_monomial_discvar, + ) return true, Alp.lift_nonconvex_term(m, term_key, constr_id, scalar) end end @@ -658,20 +787,34 @@ function detect_monomial_term(expr::Any, constr_id::Int, m::Optimizer) continue end (isa(expr.args[i], Symbol)) && continue - (expr.args[i].head == :ref) && isa(expr.args[i].args[2], Int) && push!(var_idxs, expr.args[i].args[2]) - !isempty(var_idxs) && m.var_type[var_idxs[end]] in [:Bin, :Int] && return false ,expr # Avoid fetching terms with discrete variables + (expr.args[i].head == :ref) && + isa(expr.args[i].args[2], Int) && + push!(var_idxs, expr.args[i].args[2]) + !isempty(var_idxs) && + m.var_type[var_idxs[end]] in [:Bin, :Int] && + return false, expr # Avoid fetching terms with discrete variables if (expr.args[i].head == :call) - down_check, linear_lift_var = Alp.detect_linear_term(expr.args[i], constr_id, m) + down_check, linear_lift_var = + Alp.detect_linear_term(expr.args[i], constr_id, m) !down_check && return false, expr push!(var_idxs, linear_lift_var.args[2]) - m.var_type[var_idxs[end]] in [:Bin, :Int] && return false ,expr # Avoid fetching terms with discrete variables + m.var_type[var_idxs[end]] in [:Bin, :Int] && return false, expr # Avoid fetching terms with discrete variables continue end end # Confirm detection of pattern A and perform store & lifting procedures if (length(var_idxs) == 2) && (length(Set(var_idxs)) == 1) term_key = [Expr(:ref, :x, var_idxs[1]) for i in 1:2] - term_key in keys(m.nonconvex_terms) || Alp.store_nonconvex_term(m, term_key, var_idxs, :MONOMIAL, :*, monomial, Alp.basic_monomial_bounds, collect_monomial_discvar) + term_key in keys(m.nonconvex_terms) || Alp.store_nonconvex_term( + m, + term_key, + var_idxs, + :MONOMIAL, + :*, + monomial, + Alp.basic_monomial_bounds, + collect_monomial_discvar, + ) return true, Alp.lift_nonconvex_term(m, term_key, constr_id, scalar) end end @@ -680,7 +823,6 @@ function detect_monomial_term(expr::Any, constr_id::Int, m::Optimizer) end function basic_monomial_bounds(m::Optimizer, k::Any) - lifted_idx = m.nonconvex_terms[k][:lifted_var_ref].args[2] cnt = 0 bound = [] @@ -710,7 +852,6 @@ function basic_monomial_bounds(m::Optimizer, k::Any) end function basic_monomial_bounds(m::Optimizer, nlk::Any, d::Dict) - lifted_idx = m.nonconvex_terms[nlk][:lifted_var_ref].args[2] cnt = 0 bound = [] @@ -738,11 +879,12 @@ function basic_monomial_bounds(m::Optimizer, nlk::Any, d::Dict) return d end -function collect_monomial_discvar(m::Optimizer, k::Any; var_bowl=nothing) +function collect_monomial_discvar(m::Optimizer, k::Any; var_bowl = nothing) for var in k @assert isa(var.args[2], Int) if var_bowl === nothing - var.args[2] in m.candidate_disc_vars || push!(m.candidate_disc_vars, var.args[2]) + var.args[2] in m.candidate_disc_vars || + push!(m.candidate_disc_vars, var.args[2]) else var.args[2] in var_bowl || push!(var_bowl, var.args[2]) end @@ -754,8 +896,15 @@ end Recognize convex constraints A catch for type-A convex constraint expression """ -function resolve_convex_constr(expr::Any, m::Optimizer=nothing, idx::Int=0, scalar_bin=[], idxs_bin=[], power_bin=[], rhs=0.0) - +function resolve_convex_constr( + expr::Any, + m::Optimizer = nothing, + idx::Int = 0, + scalar_bin = [], + idxs_bin = [], + power_bin = [], + rhs = 0.0, +) if expr.args[1] in [:(<=), :(>=)] && idx > 0 expr_orig = :constr sense = expr.args[1] @@ -771,13 +920,14 @@ function resolve_convex_constr(expr::Any, m::Optimizer=nothing, idx::Int=0, scal for sub in subs (isa(sub, Float64) || isa(sub, Int) || isa(sub, Symbol)) && return false - !(sub.args[1] in [:+,:-,:*]) && return false + !(sub.args[1] in [:+, :-, :*]) && return false (sub.head == :ref) && return false (sub.head == :call) && (length(sub.args) < 3) && return false if sub.args[1] in [:-, :+] for i in 2:length(sub.args) if isa(sub.args[i], Float64) || isa(sub.args[i], Int) - (sub.args[1] == [:-]) && ((i == 1) ? rhs += sub.args[i] : rhs -= sub.args[i]) + (sub.args[1] == [:-]) && + ((i == 1) ? rhs += sub.args[i] : rhs -= sub.args[i]) (sub.args[1] == [:+]) && (rhs += sub.args[i]) elseif (sub.args[i].head == :ref) return false @@ -790,7 +940,9 @@ function resolve_convex_constr(expr::Any, m::Optimizer=nothing, idx::Int=0, scal else return false end - (sub.args[1] == :-) && ((i == 2) ? push!(scalar_bin, scalar) : push!(scalar_bin, -scalar)) + (sub.args[1] == :-) && ( + (i == 2) ? push!(scalar_bin, scalar) : push!(scalar_bin, -scalar) + ) (sub.args[1] == :+) && (push!(scalar_bin, scalar)) end end @@ -840,30 +992,41 @@ function resolve_convex_constr(expr::Any, m::Optimizer=nothing, idx::Int=0, scal # sum_i (c_i*x_i^p) <= K (K > 0, p >= 1 and x_i >= 0) => Convex lb_check = [m.l_var_orig[i.args[2]] >= 0.0 for i in idxs_bin] power_check = [i > 1.0 for i in power_bin] - (convex_type == :Unknown) && prod(lb_check) && prod(power_check) && (convex_type = :convexB) + (convex_type == :Unknown) && + prod(lb_check) && + prod(power_check) && + (convex_type = :convexB) # Convex constraint Type-C # sum_i (c_i*x_i^p) >= K (K > 0, 0 < p < 1 and x_i >= 0) => Convex power_check = [i < 1 && i > 0.0 for i in power_bin] lb_check = [m.l_var_orig[i.args[2]] >= 0.0 for i in idxs_bin] - (convex_type == :Unknown) && prod(power_check) && prod(power_check) && (convex_type = :convexC) + (convex_type == :Unknown) && + prod(power_check) && + prod(power_check) && + (convex_type = :convexC) # Convex constraint Type-D # sum_i (c_i*x_i^p) <= K (K > 0, p <= 0 and x_i > 0) => Convex power_check = [i <= 0.0 for i in power_bin] - lb_check = [m.l_var_orig[i.args[2]] >= 0.0 for i in idxs_bin] - (convex_type == :Unknown) && prod(power_check) && prod(power_check) && (convex_type = :convexD) + lb_check = [m.l_var_orig[i.args[2]] >= 0.0 for i in idxs_bin] + (convex_type == :Unknown) && + prod(power_check) && + prod(power_check) && + (convex_type = :convexD) # If we really cannot figure out what is going on... (convex_type == :Unknown) && return false # Recording the nonlinear info - m.nonlinear_constrs[idx] = Dict(:expr_idx => idx, - :convex_type => convex_type, - :nonlinear_type => :convex, - :expr_orig => :constraints, - :expr_ref => deepcopy(expr), - :convexified => false) + m.nonlinear_constrs[idx] = Dict( + :expr_idx => idx, + :convex_type => convex_type, + :nonlinear_type => :convex, + :expr_orig => :constraints, + :expr_ref => deepcopy(expr), + :convexified => false, + ) # Recording the un-changed expression m.bounding_constr_expr_mip[idx] = expr @@ -872,20 +1035,22 @@ function resolve_convex_constr(expr::Any, m::Optimizer=nothing, idx::Int=0, scal m.constr_structure[idx] = :convex # Recording the function for adding constraints - m.bounding_constr_mip[idx] = Dict(:idx => idx, - :expr => expr, - :sense => sense, - :coefs => scalar_bin, - :vars => idxs_bin, - :rhs => rhs, - :cnt => length(idxs_bin), - :powers => power_bin) + m.bounding_constr_mip[idx] = Dict( + :idx => idx, + :expr => expr, + :sense => sense, + :coefs => scalar_bin, + :vars => idxs_bin, + :rhs => rhs, + :cnt => length(idxs_bin), + :powers => power_bin, + ) Alp.get_option(m, :log_level) > 99 && println("CONVEX Constraint $(idx): $(expr)") return true elseif expr_orig == :obj - minimum + minimum convex_type = :Unknown (expr_isconst(m.obj_expr_orig)) && return true # Follows the same mapping to convex constraints @@ -903,23 +1068,31 @@ function resolve_convex_constr(expr::Any, m::Optimizer=nothing, idx::Int=0, scal # sum_i (c_i*x_i^p) (p >= 1 and x_i >= 0) => Convex lb_check = [m.l_var_orig[i.args[2]] >= 0.0 for i in idxs_bin] power_check = [i > 1.0 for i in power_bin] - (convex_type == :Unknown) && prod(lb_check) && prod(power_check) && (convex_type = :convexB) + (convex_type == :Unknown) && + prod(lb_check) && + prod(power_check) && + (convex_type = :convexB) # Type-D: Convex objective function # sum_i (c_i*x_i^p) (p <= 0 and x_i > 0) => Convex power_check = [i <= 0.0 for i in power_bin] - lb_check = [m.l_var_orig[i.args[2]] >= 0.0 for i in idxs_bin] - (convex_type == :Unknown) && prod(power_check) && prod(power_check) && (convex_type = :convexD) + lb_check = [m.l_var_orig[i.args[2]] >= 0.0 for i in idxs_bin] + (convex_type == :Unknown) && + prod(power_check) && + prod(power_check) && + (convex_type = :convexD) convex_type == :Unknown && return false # Recording the nonlinear info - m.nonlinear_constrs[idx] = Dict(:expr_orig => :objective, - :expr_idx => idx, - :convex_type => convex_type, - :nonlinear_type => :convex, - :expr_ref => deepcopy(expr), - :convexified => false) + m.nonlinear_constrs[idx] = Dict( + :expr_orig => :objective, + :expr_idx => idx, + :convex_type => convex_type, + :nonlinear_type => :convex, + :expr_ref => deepcopy(expr), + :convexified => false, + ) # Recording the un-changed expression m.bounding_obj_expr_mip = expr @@ -928,16 +1101,18 @@ function resolve_convex_constr(expr::Any, m::Optimizer=nothing, idx::Int=0, scal m.obj_structure = :convex # Record a function that can be used to add objective function - m.bounding_obj_mip = Dict(:sense => nothing, - :coefs => scalar_bin, - :vars => idxs_bin, - :rhs => -rhs, - :cnt => length(idxs_bin), - :powers => power_bin) + m.bounding_obj_mip = Dict( + :sense => nothing, + :coefs => scalar_bin, + :vars => idxs_bin, + :rhs => -rhs, + :cnt => length(idxs_bin), + :powers => power_bin, + ) Alp.get_option(m, :log_level) > 99 && println("CONVEX Objective: $(expr)") return true end return false -end \ No newline at end of file +end diff --git a/src/presolve.jl b/src/presolve.jl index cfbe7b90..4b240fb9 100644 --- a/src/presolve.jl +++ b/src/presolve.jl @@ -11,13 +11,12 @@ Currently, two OBBT methods are implemented in [`minmax_bound_tightening`](@ref) If no local feasible solution is obtained, the algorithm defaults to OBBT without partitions """ function bound_tightening(m::Optimizer; use_bound = true, kwargs...) - Alp.get_option(m, :presolve_bt) || return if Alp.get_option(m, :presolve_bt_algo) == 1 - Alp.minmax_bound_tightening(m, use_bound=use_bound) + Alp.minmax_bound_tightening(m, use_bound = use_bound) elseif Alp.get_option(m, :presolve_bt_algo) == 2 - Alp.minmax_bound_tightening(m, use_bound=use_bound, use_tmc=true) + Alp.minmax_bound_tightening(m, use_bound = use_bound, use_tmc = true) elseif isa(Alp.get_option(m, :presolve_bt_algo), Function) # eval(Alp.get_option(m, :presolve_bt_algo))(m) Alp.get_option(m, :presolve_bt_algo)(m) @@ -49,11 +48,16 @@ Several other user-input options can be used to tune the OBBT algorithm. For more details, see [Presolve Options](https://lanl-ansi.github.io/Alpine.jl/latest/parameters/#Presolve-Options). """ -function minmax_bound_tightening(m::Optimizer; use_bound = true, time_limit = Inf, kwargs...) +function minmax_bound_tightening( + m::Optimizer; + use_bound = true, + time_limit = Inf, + kwargs..., +) # Some functinal constants both_senses = [MOI.MIN_SENSE, MOI.MAX_SENSE] # Senses during bound tightening procedures - tell_side = Dict(MOI.MIN_SENSE => 1, MOI.MAX_SENSE=>2) # Positional information + tell_side = Dict(MOI.MIN_SENSE => 1, MOI.MAX_SENSE => 2) # Positional information tell_round = Dict(MOI.MIN_SENSE => floor, MOI.MAX_SENSE => ceil) options = Dict(kwargs) @@ -70,82 +74,126 @@ function minmax_bound_tightening(m::Optimizer; use_bound = true, time_limit = In discretization = Alp.to_discretization(m, m.l_var_tight, m.u_var_tight) if use_bound == false && haskey(options, :use_tmc) - (Alp.get_option(m, :log_level) > 0) && @warn " Local solve infeasible; defaulting to doing bound-tightening without partitions." + (Alp.get_option(m, :log_level) > 0) && + @warn " Local solve infeasible; defaulting to doing bound-tightening without partitions." end if use_bound == true && haskey(options, :use_tmc) - discretization = Alp.add_adaptive_partition(m, use_solution=m.best_sol, use_disc=discretization) + discretization = Alp.add_adaptive_partition( + m, + use_solution = m.best_sol, + use_disc = discretization, + ) end discretization = Alp.resolve_var_bounds(m, discretization) # recomputation of bounds for lifted_variables (Alp.get_option(m, :log_level) > 0) && println(" Starting bound-tightening") - width_tol = Alp.get_option(m, :presolve_bt_width_tol) - bound_tol = Alp.get_option(m, :presolve_bt_bound_tol) + width_tol = Alp.get_option(m, :presolve_bt_width_tol) + bound_tol = Alp.get_option(m, :presolve_bt_bound_tol) improv_tol = Alp.get_option(m, :presolve_bt_improv_tol) keep_tightening = true # start of the solve - while keep_tightening && (m.logs[:time_left] > Alp.get_option(m, :tol)) && (m.logs[:bt_iter] < Alp.get_option(m, :presolve_bt_max_iter)) # Stopping criteria - + while keep_tightening && + (m.logs[:time_left] > Alp.get_option(m, :tol)) && + (m.logs[:bt_iter] < Alp.get_option(m, :presolve_bt_max_iter)) # Stopping criteria keep_tightening = false m.logs[:bt_iter] += 1 - Alp.get_option(m, :log_level) > 199 && println(" Iteration - $(m.logs[:bt_iter])") + Alp.get_option(m, :log_level) > 199 && + println(" Iteration - $(m.logs[:bt_iter])") temp_bounds = Dict() - avg_reduction = 0.0 - max_reduction = 0.0 + avg_reduction = 0.0 + max_reduction = 0.0 total_reduction = 0.0 - max_width = 0.0 + max_width = 0.0 current_rel_gap = 0.0 # Perform sequential bound tightening for var_idx in m.candidate_disc_vars - - temp_bounds[var_idx] = [discretization[var_idx][1], discretization[var_idx][end]] + temp_bounds[var_idx] = + [discretization[var_idx][1], discretization[var_idx][end]] if (discretization[var_idx][end] - discretization[var_idx][1]) > width_tol Alp.create_bound_tightening_model(m, discretization, bound) for sense in both_senses - JuMP.@objective(m.model_mip, sense, _index_to_variable_ref(m.model_mip, var_idx)) + JuMP.@objective( + m.model_mip, + sense, + _index_to_variable_ref(m.model_mip, var_idx) + ) stats = Alp.solve_bound_tightening_model(m) if stats["status"] in STATUS_OPT - temp_bounds[var_idx][tell_side[sense]] = tell_round[sense](JuMP.objective_value(m.model_mip)/bound_tol)*bound_tol # Objective truncation for numerical issues + temp_bounds[var_idx][tell_side[sense]] = + tell_round[sense]( + JuMP.objective_value(m.model_mip) / bound_tol, + ) * bound_tol # Objective truncation for numerical issues elseif stats["status"] in STATUS_LIMIT - temp_bounds[var_idx][tell_side[sense]] = tell_round[sense](JuMP.objective_bound(m.model_mip)/bound_tol)*bound_tol + temp_bounds[var_idx][tell_side[sense]] = + tell_round[sense]( + JuMP.objective_bound(m.model_mip) / bound_tol, + ) * bound_tol elseif stats["status"] in STATUS_INF - @warn("Infeasible model detected within bound tightening - bounds not updated") + @warn( + "Infeasible model detected within bound tightening - bounds not updated" + ) else @warn("Unknown status within bound tightening models") end end end - if (temp_bounds[var_idx][tell_side[MOI.MIN_SENSE]] > temp_bounds[var_idx][tell_side[MOI.MAX_SENSE]]) - temp_bounds[var_idx] = [discretization[var_idx][1], discretization[var_idx][end]] + if ( + temp_bounds[var_idx][tell_side[MOI.MIN_SENSE]] > + temp_bounds[var_idx][tell_side[MOI.MAX_SENSE]] + ) + temp_bounds[var_idx] = + [discretization[var_idx][1], discretization[var_idx][end]] end - if (temp_bounds[var_idx][tell_side[MOI.MIN_SENSE]] > discretization[var_idx][end]) - temp_bounds[var_idx][tell_side[MOI.MIN_SENSE]] = discretization[var_idx][1] + if ( + temp_bounds[var_idx][tell_side[MOI.MIN_SENSE]] > + discretization[var_idx][end] + ) + temp_bounds[var_idx][tell_side[MOI.MIN_SENSE]] = + discretization[var_idx][1] end - if (temp_bounds[var_idx][tell_side[MOI.MAX_SENSE]] < discretization[var_idx][1]) - temp_bounds[var_idx][tell_side[MOI.MAX_SENSE]] = discretization[var_idx][end] + if ( + temp_bounds[var_idx][tell_side[MOI.MAX_SENSE]] < + discretization[var_idx][1] + ) + temp_bounds[var_idx][tell_side[MOI.MAX_SENSE]] = + discretization[var_idx][end] end bound_reduction = 0.0 - if (temp_bounds[var_idx][tell_side[MOI.MAX_SENSE]] - temp_bounds[var_idx][tell_side[MOI.MIN_SENSE]]) <= width_tol + if ( + temp_bounds[var_idx][tell_side[MOI.MAX_SENSE]] - + temp_bounds[var_idx][tell_side[MOI.MIN_SENSE]] + ) <= width_tol midpoint = (temp_bounds[var_idx][1] + temp_bounds[var_idx][end]) / 2 - if (midpoint - discretization[var_idx][1] < width_tol/2) - temp_bounds[var_idx][tell_side[MOI.MIN_SENSE]] = discretization[var_idx][1] - temp_bounds[var_idx][tell_side[MOI.MAX_SENSE]] = discretization[var_idx][1] + (width_tol) - elseif (discretization[var_idx][end] - midpoint < width_tol/2) - temp_bounds[var_idx][tell_side[MOI.MIN_SENSE]] = discretization[var_idx][end] - (width_tol) - temp_bounds[var_idx][tell_side[MOI.MAX_SENSE]] = discretization[var_idx][end] + if (midpoint - discretization[var_idx][1] < width_tol / 2) + temp_bounds[var_idx][tell_side[MOI.MIN_SENSE]] = + discretization[var_idx][1] + temp_bounds[var_idx][tell_side[MOI.MAX_SENSE]] = + discretization[var_idx][1] + (width_tol) + elseif (discretization[var_idx][end] - midpoint < width_tol / 2) + temp_bounds[var_idx][tell_side[MOI.MIN_SENSE]] = + discretization[var_idx][end] - (width_tol) + temp_bounds[var_idx][tell_side[MOI.MAX_SENSE]] = + discretization[var_idx][end] else - temp_bounds[var_idx][tell_side[MOI.MIN_SENSE]] = midpoint - (width_tol/2) - temp_bounds[var_idx][tell_side[MOI.MAX_SENSE]] = midpoint + (width_tol/2) + temp_bounds[var_idx][tell_side[MOI.MIN_SENSE]] = + midpoint - (width_tol / 2) + temp_bounds[var_idx][tell_side[MOI.MAX_SENSE]] = + midpoint + (width_tol / 2) end end - new_range = round(temp_bounds[var_idx][tell_side[MOI.MAX_SENSE]] - temp_bounds[var_idx][tell_side[MOI.MIN_SENSE]], digits = 4) + new_range = round( + temp_bounds[var_idx][tell_side[MOI.MAX_SENSE]] - + temp_bounds[var_idx][tell_side[MOI.MIN_SENSE]], + digits = 4, + ) old_range = discretization[var_idx][end] - discretization[var_idx][1] bound_reduction = old_range - new_range total_reduction += bound_reduction @@ -153,20 +201,23 @@ function minmax_bound_tightening(m::Optimizer; use_bound = true, time_limit = In max_width = max(new_range, max_width) (Alp.get_option(m, :log_level) > 99) && print("+") - (Alp.get_option(m, :log_level) > 99) && println(" VAR $(var_idx) LB contracted $(discretization[var_idx][1])=>$(temp_bounds[var_idx][1])") + (Alp.get_option(m, :log_level) > 99) && println( + " VAR $(var_idx) LB contracted $(discretization[var_idx][1])=>$(temp_bounds[var_idx][1])", + ) (Alp.get_option(m, :log_level) > 99) && print("+") - (Alp.get_option(m, :log_level) > 99) && println(" VAR $(var_idx) UB contracted $(discretization[var_idx][end])=>$(temp_bounds[var_idx][end])") - - discretization[var_idx][1] = temp_bounds[var_idx][1] - discretization[var_idx][end] = temp_bounds[var_idx][end] + (Alp.get_option(m, :log_level) > 99) && println( + " VAR $(var_idx) UB contracted $(discretization[var_idx][end])=>$(temp_bounds[var_idx][end])", + ) + discretization[var_idx][1] = temp_bounds[var_idx][1] + discretization[var_idx][end] = temp_bounds[var_idx][end] end - avg_reduction = total_reduction/length(keys(temp_bounds)) + avg_reduction = total_reduction / length(keys(temp_bounds)) bound_avg_reduction = (avg_reduction > improv_tol) bound_max_reduction = (max_reduction > improv_tol) - bound_max_width = (max_width > width_tol) + bound_max_width = (max_width > width_tol) # Deactivate this termination criterion if it slows down the OBBT convergence stats = Alp.relaxation_model_obbt(m, discretization, bound) @@ -176,34 +227,51 @@ function minmax_bound_tightening(m::Optimizer; use_bound = true, time_limit = In current_rel_gap = Alp.eval_opt_gap(m, bound, stats["relaxed_obj"]) end - keep_tightening = (bound_avg_reduction) && (bound_max_reduction) && (bound_max_width) && (current_rel_gap > Alp.get_option(m, :rel_gap)) + keep_tightening = + (bound_avg_reduction) && + (bound_max_reduction) && + (bound_max_width) && + (current_rel_gap > Alp.get_option(m, :rel_gap)) if !keep_tightening && !isinf(current_rel_gap) m.presolve_best_rel_gap = current_rel_gap * 100 - end + end discretization = Alp.resolve_var_bounds(m, discretization) - + if haskey(options, :use_tmc) - discretization = Alp.add_adaptive_partition(m, use_solution=m.best_sol, use_disc = Alp.flatten_discretization(discretization)) + discretization = Alp.add_adaptive_partition( + m, + use_solution = m.best_sol, + use_disc = Alp.flatten_discretization(discretization), + ) else discretization = discretization end time() - st > time_limit && break - end - (Alp.get_option(m, :log_level) > 1) && println(" Variables whose bounds were tightened:") - (Alp.get_option(m, :log_level) > 0) && println(" Actual iterations (OBBT): ", (m.logs[:bt_iter])) - + (Alp.get_option(m, :log_level) > 1) && + println(" Variables whose bounds were tightened:") + (Alp.get_option(m, :log_level) > 0) && + println(" Actual iterations (OBBT): ", (m.logs[:bt_iter])) + m.l_var_tight, m.u_var_tight = Alp.update_var_bounds(discretization) m.discretization = Alp.add_adaptive_partition(m, use_solution = m.best_sol) for i in m.disc_vars - contract_ratio = round(1-abs(m.l_var_tight[i] - m.u_var_tight[i])/abs(l_var_orig[i] - u_var_orig[i]); digits=2)*100 + contract_ratio = + round( + 1 - + abs(m.l_var_tight[i] - m.u_var_tight[i]) / + abs(l_var_orig[i] - u_var_orig[i]); + digits = 2, + ) * 100 if Alp.get_option(m, :log_level) > 0 && contract_ratio > 0.0001 - (Alp.get_option(m, :log_level) > 1) && (println(" VAR $(i): $(contract_ratio)% contraction |$(round(l_var_orig[i]; digits=4)) --> | $(round(m.l_var_tight[i]; digits=4)) - $(round(m.u_var_tight[i]; digits=4)) | <-- $(round(u_var_orig[i]; digits=4)) |")) + (Alp.get_option(m, :log_level) > 1) && (println( + " VAR $(i): $(contract_ratio)% contraction |$(round(l_var_orig[i]; digits=4)) --> | $(round(m.l_var_tight[i]; digits=4)) - $(round(m.u_var_tight[i]; digits=4)) | <-- $(round(u_var_orig[i]; digits=4)) |", + )) end end # (Alp.get_option(m, :log_level) > 0) && print("\n") @@ -216,7 +284,12 @@ end This function takes in the initial discretization information and builds the OBBT model. It is an algorithm specific function called by [`minmax_bound_tightening`](@ref). """ -function create_bound_tightening_model(m::Optimizer, discretization, bound::Number; kwargs...) +function create_bound_tightening_model( + m::Optimizer, + discretization, + bound::Number; + kwargs..., +) # options = Dict(kwargs) start_build = time() @@ -227,7 +300,7 @@ function create_bound_tightening_model(m::Optimizer, discretization, bound::Numb if !(isinf(bound)) Alp.post_objective_bound(m, bound) - else + else @warn "Dropping the objective bound constraint in presolve bound tightening" end @@ -241,8 +314,11 @@ end function relaxation_model_obbt(m::Optimizer, discretization, bound::Number) Alp.create_bound_tightening_model(m, discretization, bound) - obj_expr = sum(m.bounding_obj_mip[:coefs][j]*_index_to_variable_ref(m.model_mip, m.bounding_obj_mip[:vars][j].args[2]) - for j in 1:m.bounding_obj_mip[:cnt]) + obj_expr = sum( + m.bounding_obj_mip[:coefs][j] * + _index_to_variable_ref(m.model_mip, m.bounding_obj_mip[:vars][j].args[2]) for + j in 1:m.bounding_obj_mip[:cnt] + ) if Alp.is_min_sense(m) JuMP.@objective(m.model_mip, Min, obj_expr) @@ -251,7 +327,7 @@ function relaxation_model_obbt(m::Optimizer, discretization, bound::Number) end stats = Alp.solve_bound_tightening_model(m) - + return stats end @@ -266,11 +342,17 @@ function solve_bound_tightening_model(m::Optimizer; kwargs...) stats = Dict() # ========= MILP Solve ========= # - time_limit = max(0.0, if Alp.get_option(m, :presolve_bt_mip_time_limit) < Inf - min(Alp.get_option(m, :presolve_bt_mip_time_limit), Alp.get_option(m, :time_limit) - m.logs[:total_time]) - else - Alp.get_option(m, :time_limit) - m.logs[:total_time] - end) + time_limit = max( + 0.0, + if Alp.get_option(m, :presolve_bt_mip_time_limit) < Inf + min( + Alp.get_option(m, :presolve_bt_mip_time_limit), + Alp.get_option(m, :time_limit) - m.logs[:total_time], + ) + else + Alp.get_option(m, :time_limit) - m.logs[:total_time] + end, + ) MOI.set(m.model_mip, MOI.TimeLimitSec(), time_limit) start_solve = time() @@ -283,7 +365,7 @@ function solve_bound_tightening_model(m::Optimizer; kwargs...) stats["status"] = status stats["relaxed_obj"] = JuMP.objective_value(m.model_mip) - + cputime_solve = time() - start_solve m.logs[:total_time] += cputime_solve m.logs[:time_left] = max(0.0, Alp.get_option(m, :time_limit) - m.logs[:total_time]) @@ -299,16 +381,24 @@ This function adds the upper/lower bounding constraint on the objective function for the optimization models solved within the OBBT algorithm. """ function post_objective_bound(m::Optimizer, bound::Number; kwargs...) + obj_expr = sum( + m.bounding_obj_mip[:coefs][j] * + _index_to_variable_ref(m.model_mip, m.bounding_obj_mip[:vars][j].args[2]) for + j in 1:m.bounding_obj_mip[:cnt] + ) - obj_expr = sum(m.bounding_obj_mip[:coefs][j]*_index_to_variable_ref(m.model_mip, m.bounding_obj_mip[:vars][j].args[2]) - for j in 1:m.bounding_obj_mip[:cnt]) - obj_bound_tol = Alp.get_option(m, :presolve_bt_obj_bound_tol) if Alp.is_max_sense(m) - JuMP.@constraint(m.model_mip, obj_expr >= floor(bound/obj_bound_tol) * obj_bound_tol) + JuMP.@constraint( + m.model_mip, + obj_expr >= floor(bound / obj_bound_tol) * obj_bound_tol + ) elseif Alp.is_min_sense(m) - JuMP.@constraint(m.model_mip, obj_expr <= ceil(bound/obj_bound_tol) * obj_bound_tol) + JuMP.@constraint( + m.model_mip, + obj_expr <= ceil(bound / obj_bound_tol) * obj_bound_tol + ) end return diff --git a/src/solver.jl b/src/solver.jl index 2a2c3463..920784c0 100644 --- a/src/solver.jl +++ b/src/solver.jl @@ -4,178 +4,179 @@ mutable struct OptimizerOptions # Parameters for tuning Alpine # Basic solver parameters - log_level :: Int # Verbosity flag: 0 for quiet, 1 for basic solve info, 2 for iteration info - time_limit :: Float64 # Time limit for algorithm (in seconds) - max_iter :: Int # Maximum bound on number of iterations for partitioning algorithm - rel_gap :: Float64 # Relative optimality gap for termination condition - abs_gap :: Float64 # Absolute optimality gap for termination condition - tol :: Float64 # Numerical tol used in algorithms - large_bound :: Float64 # Large bounds for problems with unbounded variables + log_level::Int # Verbosity flag: 0 for quiet, 1 for basic solve info, 2 for iteration info + time_limit::Float64 # Time limit for algorithm (in seconds) + max_iter::Int # Maximum bound on number of iterations for partitioning algorithm + rel_gap::Float64 # Relative optimality gap for termination condition + abs_gap::Float64 # Absolute optimality gap for termination condition + tol::Float64 # Numerical tol used in algorithms + large_bound::Float64 # Large bounds for problems with unbounded variables # All the solver options - nlp_solver :: Union{MOI.OptimizerWithAttributes, Nothing} # Local continuous NLP solver for solving NLPs at each iteration - minlp_solver :: Union{MOI.OptimizerWithAttributes, Nothing} # Local MINLP solver for solving MINLPs at each iteration - mip_solver :: Union{MOI.OptimizerWithAttributes, Nothing} # MIP solver for successive lower bound solves + nlp_solver::Union{MOI.OptimizerWithAttributes,Nothing} # Local continuous NLP solver for solving NLPs at each iteration + minlp_solver::Union{MOI.OptimizerWithAttributes,Nothing} # Local MINLP solver for solving MINLPs at each iteration + mip_solver::Union{MOI.OptimizerWithAttributes,Nothing} # MIP solver for successive lower bound solves # Convexification methods - recognize_convex :: Bool # Recognize convex expressions in parsing objective functions and constraints - bilinear_mccormick :: Bool # Convexify bilinear terms using piecwise McCormick representation - bilinear_convexhull :: Bool # Convexify bilinear terms using lambda representation - monomial_convexhull :: Bool # Convexify monomial terms using convex-hull representation + recognize_convex::Bool # Recognize convex expressions in parsing objective functions and constraints + bilinear_mccormick::Bool # Convexify bilinear terms using piecwise McCormick representation + bilinear_convexhull::Bool # Convexify bilinear terms using lambda representation + monomial_convexhull::Bool # Convexify monomial terms using convex-hull representation # Expression-based user-inputs - # method_convexification :: Array{Function} # Array of functions that user can choose to convexify specific non-linear terms : no over-ride privilege + # method_convexification :: Array{Function} # Array of functions that user can choose to convexify specific non-linear terms : no over-ride privilege # Parameters used in Alpine's MIP-based partitioning algorithm - apply_partitioning :: Bool # Apply the partitioning algorithm only if thhis true, else terminate after presolve - disc_var_pick :: Any # Algorithm for choosing the variables to discretize: 1 for minimum vertex cover, 0 for all variables - disc_ratio :: Any # Discretization ratio parameter, which is critical for convergence (using a fixed value for now, later switch to a function) - disc_uniform_rate :: Int # Discretization rate parameter when using uniform partitions - disc_add_partition_method :: Any # Additional methods to add discretization - disc_divert_chunks :: Int # How many uniform partitions to construct - disc_abs_width_tol :: Float64 # Absolute tolerance used when setting up a partition - disc_rel_width_tol :: Float64 # Relative width tolerance when setting up a partition - disc_consecutive_forbid :: Int # Prevent bounding model to add partitions consecutively in the same region when bounds do not improve - disc_ratio_branch :: Bool # Branching tests for picking fixed discretization ratio + apply_partitioning::Bool # Apply the partitioning algorithm only if thhis true, else terminate after presolve + disc_var_pick::Any # Algorithm for choosing the variables to discretize: 1 for minimum vertex cover, 0 for all variables + disc_ratio::Any # Discretization ratio parameter, which is critical for convergence (using a fixed value for now, later switch to a function) + disc_uniform_rate::Int # Discretization rate parameter when using uniform partitions + disc_add_partition_method::Any # Additional methods to add discretization + disc_divert_chunks::Int # How many uniform partitions to construct + disc_abs_width_tol::Float64 # Absolute tolerance used when setting up a partition + disc_rel_width_tol::Float64 # Relative width tolerance when setting up a partition + disc_consecutive_forbid::Int # Prevent bounding model to add partitions consecutively in the same region when bounds do not improve + disc_ratio_branch::Bool # Branching tests for picking fixed discretization ratio # MIP formulation parameters - convhull_formulation :: String # MIP Formulation for the relaxation - convhull_ebd :: Bool # Enable embedding formulation - convhull_ebd_encode :: Any # Encoding method used for convhull_ebd - convhull_ebd_ibs :: Bool # Enable independent branching scheme - convhull_ebd_link :: Bool # Linking constraints between x and α, type 1 uses hierarchical and type 2 uses big-m - convhull_warmstart :: Bool # Warm start the bounding MIP - convhull_no_good_cuts :: Bool # Add no-good cuts to MIP based on the pool solutions + convhull_formulation::String # MIP Formulation for the relaxation + convhull_ebd::Bool # Enable embedding formulation + convhull_ebd_encode::Any # Encoding method used for convhull_ebd + convhull_ebd_ibs::Bool # Enable independent branching scheme + convhull_ebd_link::Bool # Linking constraints between x and α, type 1 uses hierarchical and type 2 uses big-m + convhull_warmstart::Bool # Warm start the bounding MIP + convhull_no_good_cuts::Bool # Add no-good cuts to MIP based on the pool solutions # Bound-tightening parameters - presolve_track_time :: Bool # Account presolve time for total time usage - presolve_bt :: Bool # Perform bound tightening procedure before the main algorithm (default: true) - presolve_bt_time_limit :: Float64 # Time limit for presolving (seconds) - presolve_bt_max_iter :: Int # Maximum iterations allowed to perform presolve - presolve_bt_width_tol :: Float64 # Width tolerance for bound-tightening - presolve_bt_improv_tol :: Float64 # Improvement tolerance for average reduction of variable ranges - presolve_bt_bound_tol :: Float64 # Variable bounds truncation precicision tol - presolve_bt_obj_bound_tol :: Float64 # Objective upper bound truncation tol - presolve_bt_algo :: Any # Method used for bound tightening procedures, can either be an index of default methods or functional inputs - presolve_bt_relax_integrality :: Bool # Relax the MIP solved in built-in relaxation scheme for time performance - presolve_bt_mip_time_limit :: Float64 # Time limit for a single MIP solved in the built-in bound tightening algorithm (with partitions) + presolve_track_time::Bool # Account presolve time for total time usage + presolve_bt::Bool # Perform bound tightening procedure before the main algorithm (default: true) + presolve_bt_time_limit::Float64 # Time limit for presolving (seconds) + presolve_bt_max_iter::Int # Maximum iterations allowed to perform presolve + presolve_bt_width_tol::Float64 # Width tolerance for bound-tightening + presolve_bt_improv_tol::Float64 # Improvement tolerance for average reduction of variable ranges + presolve_bt_bound_tol::Float64 # Variable bounds truncation precicision tol + presolve_bt_obj_bound_tol::Float64 # Objective upper bound truncation tol + presolve_bt_algo::Any # Method used for bound tightening procedures, can either be an index of default methods or functional inputs + presolve_bt_relax_integrality::Bool # Relax the MIP solved in built-in relaxation scheme for time performance + presolve_bt_mip_time_limit::Float64 # Time limit for a single MIP solved in the built-in bound tightening algorithm (with partitions) # Domain Reduction - presolve_bp :: Bool # Conduct basic bound propagation + presolve_bp::Bool # Conduct basic bound propagation # Features for integer variable problems - int_enable :: Bool # Convert integer problem into binary problem - int_cumulative_disc :: Bool # Cumulatively involve integer variables for discretization + int_enable::Bool # Convert integer problem into binary problem + int_cumulative_disc::Bool # Cumulatively involve integer variables for discretization # Linking constraint feature - linking_constraints :: Bool + linking_constraints::Bool end function get_default_options() - log_level = 1 - time_limit = 1E6 - max_iter = 99 - rel_gap = 1e-4 - abs_gap = 1e-6 - tol = 1e-6 - large_bound = 1E6 - - nlp_solver = nothing - minlp_solver = nothing - mip_solver = nothing - - recognize_convex = true - bilinear_mccormick = false - bilinear_convexhull = true - monomial_convexhull = true - - # method_convexification = Array{Function}(undef, 0) - # method_partition_injection = Array{Function}(undef, 0) - # term_patterns = Array{Function}(undef, 0) - # constr_patterns = Array{Function}(undef, 0) - - apply_partitioning = true - disc_var_pick = 2 # By default, uses the 15-variable selective rule - disc_ratio = 10 - disc_uniform_rate = 2 - disc_add_partition_method = "adaptive" - disc_divert_chunks = 5 - disc_abs_width_tol = 1e-4 - disc_rel_width_tol = 1e-6 - disc_consecutive_forbid = false - disc_ratio_branch = false - - convhull_formulation = "sos2" - convhull_ebd = false - convhull_ebd_encode = "default" - convhull_ebd_ibs = false - convhull_ebd_link = false - convhull_warmstart = true - convhull_no_good_cuts = true - - presolve_track_time = true - presolve_bt = true - presolve_bt_time_limit = 900 - presolve_bt_max_iter = 25 - presolve_bt_width_tol = 1e-2 - presolve_bt_improv_tol = 1e-3 - presolve_bt_bound_tol = 1e-4 - presolve_bt_obj_bound_tol = 1e-2 - presolve_bt_algo = 1 - presolve_bt_relax_integrality = false - presolve_bt_mip_time_limit = Inf - presolve_bp = false - - int_enable = false - int_cumulative_disc = true - - linking_constraints = false - - return OptimizerOptions(log_level, - time_limit, - max_iter, - rel_gap, - abs_gap, - tol, - large_bound, - nlp_solver, - minlp_solver, - mip_solver, - recognize_convex, - bilinear_mccormick, - bilinear_convexhull, - monomial_convexhull, - apply_partitioning, - disc_var_pick, - disc_ratio, - disc_uniform_rate, - disc_add_partition_method, - disc_divert_chunks, - disc_abs_width_tol, - disc_rel_width_tol, - disc_consecutive_forbid, - disc_ratio_branch, - convhull_formulation, - convhull_ebd, - convhull_ebd_encode, - convhull_ebd_ibs, - convhull_ebd_link, - convhull_warmstart, - convhull_no_good_cuts, - presolve_track_time, - presolve_bt, - presolve_bt_time_limit, - presolve_bt_max_iter, - presolve_bt_width_tol, - presolve_bt_improv_tol, - presolve_bt_bound_tol, - presolve_bt_obj_bound_tol, - presolve_bt_algo, - presolve_bt_relax_integrality, - presolve_bt_mip_time_limit, - presolve_bp, - int_enable, - int_cumulative_disc, - linking_constraints) - -end \ No newline at end of file + log_level = 1 + time_limit = 1E6 + max_iter = 99 + rel_gap = 1e-4 + abs_gap = 1e-6 + tol = 1e-6 + large_bound = 1E6 + + nlp_solver = nothing + minlp_solver = nothing + mip_solver = nothing + + recognize_convex = true + bilinear_mccormick = false + bilinear_convexhull = true + monomial_convexhull = true + + # method_convexification = Array{Function}(undef, 0) + # method_partition_injection = Array{Function}(undef, 0) + # term_patterns = Array{Function}(undef, 0) + # constr_patterns = Array{Function}(undef, 0) + + apply_partitioning = true + disc_var_pick = 2 # By default, uses the 15-variable selective rule + disc_ratio = 10 + disc_uniform_rate = 2 + disc_add_partition_method = "adaptive" + disc_divert_chunks = 5 + disc_abs_width_tol = 1e-4 + disc_rel_width_tol = 1e-6 + disc_consecutive_forbid = false + disc_ratio_branch = false + + convhull_formulation = "sos2" + convhull_ebd = false + convhull_ebd_encode = "default" + convhull_ebd_ibs = false + convhull_ebd_link = false + convhull_warmstart = true + convhull_no_good_cuts = true + + presolve_track_time = true + presolve_bt = true + presolve_bt_time_limit = 900 + presolve_bt_max_iter = 25 + presolve_bt_width_tol = 1e-2 + presolve_bt_improv_tol = 1e-3 + presolve_bt_bound_tol = 1e-4 + presolve_bt_obj_bound_tol = 1e-2 + presolve_bt_algo = 1 + presolve_bt_relax_integrality = false + presolve_bt_mip_time_limit = Inf + presolve_bp = false + + int_enable = false + int_cumulative_disc = true + + linking_constraints = false + + return OptimizerOptions( + log_level, + time_limit, + max_iter, + rel_gap, + abs_gap, + tol, + large_bound, + nlp_solver, + minlp_solver, + mip_solver, + recognize_convex, + bilinear_mccormick, + bilinear_convexhull, + monomial_convexhull, + apply_partitioning, + disc_var_pick, + disc_ratio, + disc_uniform_rate, + disc_add_partition_method, + disc_divert_chunks, + disc_abs_width_tol, + disc_rel_width_tol, + disc_consecutive_forbid, + disc_ratio_branch, + convhull_formulation, + convhull_ebd, + convhull_ebd_encode, + convhull_ebd_ibs, + convhull_ebd_link, + convhull_warmstart, + convhull_no_good_cuts, + presolve_track_time, + presolve_bt, + presolve_bt_time_limit, + presolve_bt_max_iter, + presolve_bt_width_tol, + presolve_bt_improv_tol, + presolve_bt_bound_tol, + presolve_bt_obj_bound_tol, + presolve_bt_algo, + presolve_bt_relax_integrality, + presolve_bt_mip_time_limit, + presolve_bp, + int_enable, + int_cumulative_disc, + linking_constraints, + ) +end diff --git a/src/tmc.jl b/src/tmc.jl index 772c4aac..7088b808 100644 --- a/src/tmc.jl +++ b/src/tmc.jl @@ -1,9 +1,9 @@ function amp_post_mccormick(m::Optimizer; kwargs...) - options = Dict(kwargs) # detect whether to use specific discretization information - haskey(options, :use_disc) ? discretization = options[:use_disc] : discretization = m.discretization + haskey(options, :use_disc) ? discretization = options[:use_disc] : + discretization = m.discretization λ = Dict() λλ = Dict() @@ -13,7 +13,10 @@ function amp_post_mccormick(m::Optimizer; kwargs...) for bi in keys(m.nonconvex_terms) nl_type = m.nonconvex_terms[bi][:nonlinear_type] - if ((!Alp.get_option(m, :monomial_convexhull))*(nl_type == :MONOMIAL) || (!Alp.get_option(m, :bilinear_convexhull))*(nl_type == :BILINEAR)) && (m.nonconvex_terms[bi][:convexified] == false) + if ( + (!Alp.get_option(m, :monomial_convexhull)) * (nl_type == :MONOMIAL) || + (!Alp.get_option(m, :bilinear_convexhull)) * (nl_type == :BILINEAR) + ) && (m.nonconvex_terms[bi][:convexified] == false) @assert length(bi) == 2 m.nonconvex_terms[bi][:convexified] = true # Bookkeeping the examined terms idx_a = bi[1].args[2] @@ -28,17 +31,35 @@ function amp_post_mccormick(m::Optimizer; kwargs...) lb[idx_b] = discretization[idx_b][1:(end-1)] ub[idx_b] = discretization[idx_b][2:end] - (lb[idx_a][1] == -Inf) && error("Infinite lower bound detected on VAR$idx_a, resolve it please") - (lb[idx_b][1] == -Inf) && error("Infinite lower bound detected on VAR$idx_b, resolve it please") - (ub[idx_a][end] == +Inf) && error("Infinite upper bound detected on VAR$idx_a, resolve it please") - (ub[idx_b][end] == +Inf) && error("Infinite upper bound detected on VAR$idx_b, resolve it please") + (lb[idx_a][1] == -Inf) && + error("Infinite lower bound detected on VAR$idx_a, resolve it please") + (lb[idx_b][1] == -Inf) && + error("Infinite lower bound detected on VAR$idx_b, resolve it please") + (ub[idx_a][end] == +Inf) && + error("Infinite upper bound detected on VAR$idx_a, resolve it please") + (ub[idx_b][end] == +Inf) && + error("Infinite upper bound detected on VAR$idx_b, resolve it please") if (length(lb[idx_a]) == 1) && (length(lb[idx_b]) == 1) # Basic McCormick if m.nonconvex_terms[bi][:nonlinear_type] == :MONOMIAL - Alp.mccormick_monomial(m.model_mip, _index_to_variable_ref(m.model_mip, idx_ab), _index_to_variable_ref(m.model_mip,idx_a), lb[idx_a][1], ub[idx_a][1]) + Alp.mccormick_monomial( + m.model_mip, + _index_to_variable_ref(m.model_mip, idx_ab), + _index_to_variable_ref(m.model_mip, idx_a), + lb[idx_a][1], + ub[idx_a][1], + ) elseif m.nonconvex_terms[bi][:nonlinear_type] == :BILINEAR - Alp.mccormick(m.model_mip, _index_to_variable_ref(m.model_mip, idx_ab), _index_to_variable_ref(m.model_mip, idx_a), _index_to_variable_ref(m.model_mip, idx_b), - lb[idx_a][1], ub[idx_a][1], lb[idx_b][1], ub[idx_b][1]) + Alp.mccormick( + m.model_mip, + _index_to_variable_ref(m.model_mip, idx_ab), + _index_to_variable_ref(m.model_mip, idx_a), + _index_to_variable_ref(m.model_mip, idx_b), + lb[idx_a][1], + ub[idx_a][1], + lb[idx_b][1], + ub[idx_b][1], + ) end else # Tighten McCormick @@ -47,40 +68,91 @@ function amp_post_mccormick(m::Optimizer; kwargs...) λ = Alp.amp_post_tmc_λ(m.model_mip, λ, lb, ub, part_cnt_a, idx_a) λX = Alp.amp_post_tmc_λX(m.model_mip, λX, part_cnt_a, idx_a, idx_b) Alp.amp_post_tmc_λxX_mc(m.model_mip, λX, λ, lb, ub, idx_a, idx_b) - Alp.amp_post_tmc_monomial_mc(m.model_mip, idx_ab, λ, λX, lb, ub, part_cnt_a, idx_a) - # else + Alp.amp_post_tmc_monomial_mc( + m.model_mip, + idx_ab, + λ, + λX, + lb, + ub, + part_cnt_a, + idx_a, + ) + # else elseif m.nonconvex_terms[bi][:nonlinear_type] == :BILINEAR # Partitioning on left - if (idx_a in m.disc_vars) && !(idx_b in m.disc_vars) && (part_cnt_b == 1) + if (idx_a in m.disc_vars) && + !(idx_b in m.disc_vars) && + (part_cnt_b == 1) λ = Alp.amp_post_tmc_λ(m.model_mip, λ, lb, ub, part_cnt_a, idx_a) - λX = Alp.amp_post_tmc_λX(m.model_mip, λX, part_cnt_a, idx_a, idx_b) - λX[(idx_b,idx_a)] = [_index_to_variable_ref(m.model_mip, idx_a)] + λX = + Alp.amp_post_tmc_λX(m.model_mip, λX, part_cnt_a, idx_a, idx_b) + λX[(idx_b, idx_a)] = [_index_to_variable_ref(m.model_mip, idx_a)] λλ = Alp.amp_post_tmc_λλ(λλ, λ, idx_a, idx_b) Alp.amp_post_tmc_λxX_mc(m.model_mip, λX, λ, lb, ub, idx_a, idx_b) - Alp.amp_post_tmc_XX_mc(m.model_mip, idx_ab, λX, λλ, lb, ub, idx_a, idx_b) + Alp.amp_post_tmc_XX_mc( + m.model_mip, + idx_ab, + λX, + λλ, + lb, + ub, + idx_a, + idx_b, + ) end # Partitioning of right - if !(idx_a in m.disc_vars) && (idx_b in m.disc_vars) && (part_cnt_a == 1) + if !(idx_a in m.disc_vars) && + (idx_b in m.disc_vars) && + (part_cnt_a == 1) λ = Alp.amp_post_tmc_λ(m.model_mip, λ, lb, ub, part_cnt_b, idx_b) - λX = Alp.amp_post_tmc_λX(m.model_mip, λX, part_cnt_b, idx_b, idx_a) - λX[(idx_a,idx_b)] = [_index_to_variable_ref(m.model_mip, idx_b)] + λX = + Alp.amp_post_tmc_λX(m.model_mip, λX, part_cnt_b, idx_b, idx_a) + λX[(idx_a, idx_b)] = [_index_to_variable_ref(m.model_mip, idx_b)] λλ = Alp.amp_post_tmc_λλ(λλ, λ, idx_b, idx_a) Alp.amp_post_tmc_λxX_mc(m.model_mip, λX, λ, lb, ub, idx_b, idx_a) - Alp.amp_post_tmc_XX_mc(m.model_mip,idx_ab, λX, λλ, lb, ub, idx_b, idx_a) + Alp.amp_post_tmc_XX_mc( + m.model_mip, + idx_ab, + λX, + λλ, + lb, + ub, + idx_b, + idx_a, + ) end # Partitioning on both variables if (idx_a in m.disc_vars) && (idx_b in m.disc_vars) λ = Alp.amp_post_tmc_λ(m.model_mip, λ, lb, ub, part_cnt_a, idx_a) λ = Alp.amp_post_tmc_λ(m.model_mip, λ, lb, ub, part_cnt_b, idx_b) - λX = Alp.amp_post_tmc_λX(m.model_mip, λX, part_cnt_a, idx_a, idx_b) - λX = Alp.amp_post_tmc_λX(m.model_mip, λX, part_cnt_b, idx_b, idx_a) - λλ = Alp.amp_post_tmc_λλ(m.model_mip, λλ, part_cnt_a, part_cnt_b, idx_a, idx_b) + λX = + Alp.amp_post_tmc_λX(m.model_mip, λX, part_cnt_a, idx_a, idx_b) + λX = + Alp.amp_post_tmc_λX(m.model_mip, λX, part_cnt_b, idx_b, idx_a) + λλ = Alp.amp_post_tmc_λλ( + m.model_mip, + λλ, + part_cnt_a, + part_cnt_b, + idx_a, + idx_b, + ) Alp.amp_post_tmc_λxX_mc(m.model_mip, λX, λ, lb, ub, idx_a, idx_b) Alp.amp_post_tmc_λxX_mc(m.model_mip, λX, λ, lb, ub, idx_b, idx_a) Alp.amp_post_tmc_λxλ_mc(m.model_mip, λλ, λ, idx_a, idx_b) - Alp.amp_post_tmc_XX_mc(m.model_mip, idx_ab, λX, λλ, lb, ub, idx_a, idx_b) + Alp.amp_post_tmc_XX_mc( + m.model_mip, + idx_ab, + λX, + λλ, + lb, + ub, + idx_a, + idx_b, + ) end # Error condition @@ -94,9 +166,17 @@ function amp_post_mccormick(m::Optimizer; kwargs...) return end -function amp_post_tmc_λ(m::JuMP.Model, λ::Dict, lb::Dict, ub::Dict, dim::Int, idx::Int, relax=false) +function amp_post_tmc_λ( + m::JuMP.Model, + λ::Dict, + lb::Dict, + ub::Dict, + dim::Int, + idx::Int, + relax = false, +) if !haskey(λ, idx) - λ[idx] = JuMP.@variable(m, [1:dim], Bin, base_name=string("L",idx)) + λ[idx] = JuMP.@variable(m, [1:dim], Bin, base_name = string("L", idx)) JuMP.@constraint(m, sum(λ[idx]) == 1) # SOS-1 Constraints JuMP.@constraint(m, _index_to_variable_ref(m, idx) >= dot(lb[idx], λ[idx])) JuMP.@constraint(m, _index_to_variable_ref(m, idx) <= dot(ub[idx], λ[idx])) @@ -105,31 +185,60 @@ function amp_post_tmc_λ(m::JuMP.Model, λ::Dict, lb::Dict, ub::Dict, dim::Int, return λ end -function amp_post_tmc_monomial_mc(m::JuMP.Model, idx_aa::Int, λ::Dict, λX::Dict, LB::Dict, UB::Dict, dim::Int, idx_a::Int) - JuMP.@constraint(m, _index_to_variable_ref(m, idx_aa) >= _index_to_variable_ref(m, idx_a)^(2)) - JuMP.@constraint(m, _index_to_variable_ref(m, idx_aa) <= dot(λX[(idx_a,idx_a)],LB[idx_a]) + dot(λX[(idx_a,idx_a)],UB[idx_a]) - dot(λ[idx_a], *(Matrix(Diagonal(LB[idx_a])), UB[idx_a]))) +function amp_post_tmc_monomial_mc( + m::JuMP.Model, + idx_aa::Int, + λ::Dict, + λX::Dict, + LB::Dict, + UB::Dict, + dim::Int, + idx_a::Int, +) + JuMP.@constraint( + m, + _index_to_variable_ref(m, idx_aa) >= _index_to_variable_ref(m, idx_a)^(2) + ) + JuMP.@constraint( + m, + _index_to_variable_ref(m, idx_aa) <= + dot(λX[(idx_a, idx_a)], LB[idx_a]) + dot(λX[(idx_a, idx_a)], UB[idx_a]) - + dot(λ[idx_a], *(Matrix(Diagonal(LB[idx_a])), UB[idx_a])) + ) return end function amp_post_tmc_λX(m::JuMP.Model, λX::Dict, dim::Int, idx_a::Int, idx_b::Int) - if !haskey(λX, (idx_a,idx_b)) - λX[(idx_a,idx_b)] = JuMP.@variable(m, [1:dim], base_name=string("L",idx_a,"X",idx_b)) + if !haskey(λX, (idx_a, idx_b)) + λX[(idx_a, idx_b)] = + JuMP.@variable(m, [1:dim], base_name = string("L", idx_a, "X", idx_b)) end return λX end -function amp_post_tmc_λλ(m::JuMP.Model, λλ::Dict, dim_a::Int, dim_b::Int, idx_a::Int, idx_b::Int) +function amp_post_tmc_λλ( + m::JuMP.Model, + λλ::Dict, + dim_a::Int, + dim_b::Int, + idx_a::Int, + idx_b::Int, +) if !haskey(λλ, (idx_a, idx_b)) - λλ[(idx_a,idx_b)] = JuMP.@variable(m, [1:dim_a, 1:dim_b], base_name=string("L",idx_a,"L",idx_b)) + λλ[(idx_a, idx_b)] = JuMP.@variable( + m, + [1:dim_a, 1:dim_b], + base_name = string("L", idx_a, "L", idx_b) + ) for i in 1:dim_a - for j in 1:dim_b - JuMP.set_lower_bound(λλ[(idx_a, idx_b)][i,j], 0) - JuMP.set_upper_bound(λλ[(idx_a, idx_b)][i,j], 1) - end - end - λλ[(idx_b,idx_a)] = λλ[(idx_a,idx_b)]' + for j in 1:dim_b + JuMP.set_lower_bound(λλ[(idx_a, idx_b)][i, j], 0) + JuMP.set_upper_bound(λλ[(idx_a, idx_b)][i, j], 1) + end + end + λλ[(idx_b, idx_a)] = λλ[(idx_a, idx_b)]' end return λλ @@ -137,9 +246,9 @@ end function amp_post_tmc_λλ(λλ::Dict, λ::Dict, idx_a::Int, idx_b::Int) if !haskey(λλ, (idx_a, idx_b)) - λλ[(idx_a,idx_b)] = λ[idx_a] - λλ[(idx_a,idx_b)] = reshape(λλ[(idx_a,idx_b)], (length(λ[idx_a]), 1)) - λλ[(idx_b,idx_a)] = λλ[(idx_a,idx_b)]' + λλ[(idx_a, idx_b)] = λ[idx_a] + λλ[(idx_a, idx_b)] = reshape(λλ[(idx_a, idx_b)], (length(λ[idx_a]), 1)) + λλ[(idx_b, idx_a)] = λλ[(idx_a, idx_b)]' end return λλ @@ -150,10 +259,30 @@ function amp_post_tmc_XX_mc(m::JuMP.Model, ab, λX, λλ, LB, UB, a, b) @assert length(LB[b]) == length(UB[b]) dim_A = length(LB[a]) dim_B = length(LB[b]) - JuMP.@constraint(m, _index_to_variable_ref(m, ab) .>= dot(λX[(a,b)],LB[a]) + dot(λX[(b,a)],LB[b]) - reshape(LB[a], (1, dim_A))*λλ[(a,b)]*reshape(LB[b], (dim_B, 1))) - JuMP.@constraint(m, _index_to_variable_ref(m, ab) .>= dot(λX[(a,b)],UB[a]) + dot(λX[(b,a)],UB[b]) - reshape(UB[a], (1, dim_A))*λλ[(a,b)]*reshape(UB[b], (dim_B, 1))) - JuMP.@constraint(m, _index_to_variable_ref(m, ab) .<= dot(λX[(a,b)],LB[a]) + dot(λX[(b,a)],UB[b]) - reshape(LB[a], (1, dim_A))*λλ[(a,b)]*reshape(UB[b], (dim_B, 1))) - JuMP.@constraint(m, _index_to_variable_ref(m, ab) .<= dot(λX[(a,b)],UB[a]) + dot(λX[(b,a)],LB[b]) - reshape(UB[a], (1, dim_A))*λλ[(a,b)]*reshape(LB[b], (dim_B, 1))) + JuMP.@constraint( + m, + _index_to_variable_ref(m, ab) .>= + dot(λX[(a, b)], LB[a]) + dot(λX[(b, a)], LB[b]) - + reshape(LB[a], (1, dim_A)) * λλ[(a, b)] * reshape(LB[b], (dim_B, 1)) + ) + JuMP.@constraint( + m, + _index_to_variable_ref(m, ab) .>= + dot(λX[(a, b)], UB[a]) + dot(λX[(b, a)], UB[b]) - + reshape(UB[a], (1, dim_A)) * λλ[(a, b)] * reshape(UB[b], (dim_B, 1)) + ) + JuMP.@constraint( + m, + _index_to_variable_ref(m, ab) .<= + dot(λX[(a, b)], LB[a]) + dot(λX[(b, a)], UB[b]) - + reshape(LB[a], (1, dim_A)) * λλ[(a, b)] * reshape(UB[b], (dim_B, 1)) + ) + JuMP.@constraint( + m, + _index_to_variable_ref(m, ab) .<= + dot(λX[(a, b)], UB[a]) + dot(λX[(b, a)], LB[b]) - + reshape(UB[a], (1, dim_A)) * λλ[(a, b)] * reshape(LB[b], (dim_B, 1)) + ) return end @@ -161,50 +290,58 @@ end _lower_bound(x) = JuMP.is_binary(x) ? 0.0 : JuMP.lower_bound(x) _upper_bound(x) = JuMP.is_binary(x) ? 1.0 : JuMP.upper_bound(x) -function amp_post_tmc_λxX_mc(m::JuMP.Model, λX::Dict, λ::Dict, lb::Dict, ub::Dict, ind_λ::Int, ind_X::Int) +function amp_post_tmc_λxX_mc( + m::JuMP.Model, + λX::Dict, + λ::Dict, + lb::Dict, + ub::Dict, + ind_λ::Int, + ind_X::Int, +) # X_u and λ here are vectors, and X is one variable, - # After the product, we have a polynomial to multiply X, - # forming |λ| new variables stored in λX dictionary + # After the product, we have a polynomial to multiply X, + # forming |λ| new variables stored in λX dictionary - dim_λ = length(λ[ind_λ]) # This is how many new variables to be generated - for i in 1:dim_λ + dim_λ = length(λ[ind_λ]) # This is how many new variables to be generated + for i in 1:dim_λ v = _index_to_variable_ref(m, ind_X) - lb_X = JuMP.lower_bound(v) - ub_X = JuMP.upper_bound(v) + lb_X = JuMP.lower_bound(v) + ub_X = JuMP.upper_bound(v) lb_λ = _lower_bound(λ[ind_λ][i]) - ub_λ = _upper_bound(λ[ind_λ][i]) + ub_λ = _upper_bound(λ[ind_λ][i]) @assert (lb_λ == 0.0) && (ub_λ == 1.0) - Alp.mccormick(m, λX[(ind_λ,ind_X)][i], λ[ind_λ][i], v, lb_λ, ub_λ, lb_X, ub_X) - end + Alp.mccormick(m, λX[(ind_λ, ind_X)][i], λ[ind_λ][i], v, lb_λ, ub_λ, lb_X, ub_X) + end return end function amp_post_tmc_λxλ_mc(m::JuMP.Model, λλ::Dict, λ::Dict, ind_A::Int, ind_B::Int) - #= - A 3 x 2 example, some new variables are formed - | y11y21 y11y22 | | y11 | | y21 |T - | y12y21 y12y22 | = | y12 | x | | - | y13y21 y13y22 | | y13 | | y22 | - =# - - # Prepare the new variable, these two counts track the total count of new variables - dim_A = length(λ[ind_A]) - dim_B = length(λ[ind_B]) - for i in 1:dim_A - for j in 1:dim_B - JuMP.set_lower_bound(λλ[(ind_A,ind_B)][i,j],0) - JuMP.set_upper_bound(λλ[(ind_A,ind_B)][i,j],1) - end - end - - for i in 1:dim_A - for j in 1:dim_B - Alp.mccormick_bin(m, λλ[(ind_A,ind_B)][i,j], λ[ind_A][i], λ[ind_B][j]) - end - end + #= + A 3 x 2 example, some new variables are formed + | y11y21 y11y22 | | y11 | | y21 |T + | y12y21 y12y22 | = | y12 | x | | + | y13y21 y13y22 | | y13 | | y22 | + =# + + # Prepare the new variable, these two counts track the total count of new variables + dim_A = length(λ[ind_A]) + dim_B = length(λ[ind_B]) + for i in 1:dim_A + for j in 1:dim_B + JuMP.set_lower_bound(λλ[(ind_A, ind_B)][i, j], 0) + JuMP.set_upper_bound(λλ[(ind_A, ind_B)][i, j], 1) + end + end + + for i in 1:dim_A + for j in 1:dim_B + Alp.mccormick_bin(m, λλ[(ind_A, ind_B)][i, j], λ[ind_A][i], λ[ind_B][j]) + end + end return end @@ -214,17 +351,32 @@ end Generic function to add a McCormick convex envelop, where `xy=x*y` and `x_l, x_u, y_l, y_u` are variable bounds. """ -function mccormick(m::JuMP.Model, xy::JuMP.VariableRef, x::JuMP.VariableRef, y::JuMP.VariableRef, lb_x, ub_x, lb_y, ub_y) - - JuMP.@constraint(m, xy >= lb_x*y + lb_y*x - lb_x*lb_y) - JuMP.@constraint(m, xy >= ub_x*y + ub_y*x - ub_x*ub_y) - JuMP.@constraint(m, xy <= lb_x*y + ub_y*x - lb_x*ub_y) - JuMP.@constraint(m, xy <= ub_x*y + lb_y*x - ub_x*lb_y) +function mccormick( + m::JuMP.Model, + xy::JuMP.VariableRef, + x::JuMP.VariableRef, + y::JuMP.VariableRef, + lb_x, + ub_x, + lb_y, + ub_y, +) + JuMP.@constraint(m, xy >= lb_x * y + lb_y * x - lb_x * lb_y) + JuMP.@constraint(m, xy >= ub_x * y + ub_y * x - ub_x * ub_y) + JuMP.@constraint(m, xy <= lb_x * y + ub_y * x - lb_x * ub_y) + JuMP.@constraint(m, xy <= ub_x * y + lb_y * x - ub_x * lb_y) return end -function mccormick_binlin(m::JuMP.Model, binlin::JuMP.VariableRef, bin::JuMP.VariableRef, lin::JuMP.VariableRef, lb, ub) +function mccormick_binlin( + m::JuMP.Model, + binlin::JuMP.VariableRef, + bin::JuMP.VariableRef, + lin::JuMP.VariableRef, + lb, + ub, +) # TODO think about how to address this issue warnuser = false @@ -239,16 +391,16 @@ function mccormick_binlin(m::JuMP.Model, binlin::JuMP.VariableRef, bin::JuMP.Var end if lb >= 0 - JuMP.@constraint(m, binlin <= ub*bin) + JuMP.@constraint(m, binlin <= ub * bin) JuMP.@constraint(m, binlin <= lin) - JuMP.@constraint(m, binlin >= lin - (1-bin)*ub) + JuMP.@constraint(m, binlin >= lin - (1 - bin) * ub) else JuMP.@constraint(m, binlin <= ub) JuMP.@constraint(m, binlin >= lb) - JuMP.@constraint(m, binlin <= bin*ub) - JuMP.@constraint(m, binlin >= bin*lb) - JuMP.@constraint(m, binlin <= lin - (1-bin)*lb) - JuMP.@constraint(m, binlin >= lin - (1-bin)*ub) + JuMP.@constraint(m, binlin <= bin * ub) + JuMP.@constraint(m, binlin >= bin * lb) + JuMP.@constraint(m, binlin <= lin - (1 - bin) * lb) + JuMP.@constraint(m, binlin >= lin - (1 - bin) * ub) end # Second position to handle inf bounds @@ -257,17 +409,28 @@ function mccormick_binlin(m::JuMP.Model, binlin::JuMP.VariableRef, bin::JuMP.Var return end -function mccormick_bin(m::JuMP.Model, xy::JuMP.VariableRef, x::JuMP.VariableRef, y::JuMP.VariableRef) +function mccormick_bin( + m::JuMP.Model, + xy::JuMP.VariableRef, + x::JuMP.VariableRef, + y::JuMP.VariableRef, +) JuMP.@constraint(m, xy <= x) JuMP.@constraint(m, xy <= y) - JuMP.@constraint(m, xy >= x+y-1) + JuMP.@constraint(m, xy >= x + y - 1) return end # [TODO] Unused functions but will be used for later -function mccormick_monomial(m::JuMP.Model, xy::JuMP.VariableRef, x::JuMP.VariableRef, lb_x, ub_x) +function mccormick_monomial( + m::JuMP.Model, + xy::JuMP.VariableRef, + x::JuMP.VariableRef, + lb_x, + ub_x, +) JuMP.@constraint(m, xy >= x^2) - JuMP.@constraint(m, xy <= (lb_x+ub_x)*x - (lb_x*ub_x)) + JuMP.@constraint(m, xy <= (lb_x + ub_x) * x - (lb_x * ub_x)) return end @@ -275,11 +438,10 @@ end # Fortet linearization # Reference: https://doi.org/10.1007/s10288-006-0015-3 function binprod_relax(m::JuMP.Model, z::JuMP.VariableRef, x::Vector) - for i in x JuMP.@constraint(m, z <= i) end - JuMP.@constraint(m, z >= sum(x) - (length(x)-1)) + JuMP.@constraint(m, z >= sum(x) - (length(x) - 1)) return end diff --git a/src/utility.jl b/src/utility.jl index e4e88710..15055068 100644 --- a/src/utility.jl +++ b/src/utility.jl @@ -15,80 +15,83 @@ The absolute gap calculation is ``` """ function update_opt_gap(m::Optimizer) - - tol = Alp.get_option(m, :tol) - - if m.best_obj in [Inf, -Inf] - m.best_rel_gap = Inf - return - else - p = convert(Int, round(abs(log(10, Alp.get_option(m, :rel_gap))))) - n = round(abs(m.best_obj - m.best_bound); digits=p) - # dn = round(abs(1e-12+abs(m.best_obj)); digits=p) - if isapprox(n, 0.0; atol = tol) && isapprox(m.best_obj,0.0; atol = tol) - m.best_rel_gap = 0.0 - return - end - - if Alp.is_min_sense(m) - m.best_rel_gap = Alp.eval_opt_gap(m, m.best_bound, m.best_obj) - elseif Alp.is_max_sense(m) - m.best_rel_gap = Alp.eval_opt_gap(m, m.best_obj, m.best_bound) - end - - end - - m.best_abs_gap = abs(m.best_obj - m.best_bound) - - return + tol = Alp.get_option(m, :tol) + + if m.best_obj in [Inf, -Inf] + m.best_rel_gap = Inf + return + else + p = convert(Int, round(abs(log(10, Alp.get_option(m, :rel_gap))))) + n = round(abs(m.best_obj - m.best_bound); digits = p) + # dn = round(abs(1e-12+abs(m.best_obj)); digits=p) + if isapprox(n, 0.0; atol = tol) && isapprox(m.best_obj, 0.0; atol = tol) + m.best_rel_gap = 0.0 + return + end + + if Alp.is_min_sense(m) + m.best_rel_gap = Alp.eval_opt_gap(m, m.best_bound, m.best_obj) + elseif Alp.is_max_sense(m) + m.best_rel_gap = Alp.eval_opt_gap(m, m.best_obj, m.best_bound) + end + end + + m.best_abs_gap = abs(m.best_obj - m.best_bound) + + return end function eval_opt_gap(m::Optimizer, lower_bound::Number, upper_bound::Number) + tol = Alp.get_option(m, :tol) - tol = Alp.get_option(m, :tol) + if isapprox(lower_bound, upper_bound, atol = tol) + m.best_rel_gap = 0.0 - if isapprox(lower_bound, upper_bound, atol = tol) - m.best_rel_gap = 0.0 + elseif (lower_bound - upper_bound) > 1E-5 + error("Lower bound cannot cross the upper bound in optimality gap evaluation") - elseif (lower_bound - upper_bound) > 1E-5 - error("Lower bound cannot cross the upper bound in optimality gap evaluation") + elseif isinf(lower_bound) || isinf(upper_bound) + error("Infinite bounds detected in optimality gap evalutation") - elseif isinf(lower_bound) || isinf(upper_bound) - error("Infinite bounds detected in optimality gap evalutation") - - else - if isapprox(upper_bound, 0.0; atol = tol) # zero upper bound case - eps = 1 # shift factor - m.best_rel_gap = abs((upper_bound + eps) - (lower_bound + eps))/(tol + abs(upper_bound) + eps) - else - m.best_rel_gap = abs(upper_bound - lower_bound)/(tol + abs(upper_bound)) - end - end - - return m.best_rel_gap + else + if isapprox(upper_bound, 0.0; atol = tol) # zero upper bound case + eps = 1 # shift factor + m.best_rel_gap = + abs((upper_bound + eps) - (lower_bound + eps)) / + (tol + abs(upper_bound) + eps) + else + m.best_rel_gap = abs(upper_bound - lower_bound) / (tol + abs(upper_bound)) + end + end + + return m.best_rel_gap end -function measure_relaxed_deviation(m::Optimizer;sol=nothing) +function measure_relaxed_deviation(m::Optimizer; sol = nothing) + sol = something(sol, m.best_bound_sol) - sol = something(sol, m.best_bound_sol) + isempty(sol) && return - isempty(sol) && return + dev = [] + for k in keys(m.nonconvex_terms) + y_idx = m.nonconvex_terms[k][:y_idx] + y_hat = sol[y_idx] + y_val = m.nonconvex_terms[k][:evaluator](m.nonconvex_terms[k], sol) + push!( + dev, + (y_idx, abs(y_hat - y_val), y_hat, y_val, m.nonconvex_terms[k][:var_idxs]), + ) + end - dev = [] - for k in keys(m.nonconvex_terms) - y_idx = m.nonconvex_terms[k][:y_idx] - y_hat = sol[y_idx] - y_val = m.nonconvex_terms[k][:evaluator](m.nonconvex_terms[k], sol) - push!(dev, (y_idx, abs(y_hat-y_val), y_hat, y_val, m.nonconvex_terms[k][:var_idxs])) - end + sort!(dev, by = x -> x[1]) - sort!(dev, by=x->x[1]) + for i in dev + Alp.get_option(m, :log_level) > 199 && println( + "Y-VAR$(i[1]): DIST=$(i[2]) || Y-hat = $(i[3]), Y-val = $(i[4]) || COMP $(i[5])", + ) + end - for i in dev - Alp.get_option(m, :log_level) > 199 && println("Y-VAR$(i[1]): DIST=$(i[2]) || Y-hat = $(i[3]), Y-val = $(i[4]) || COMP $(i[5])") - end - - return + return end """ @@ -96,21 +99,21 @@ end Same as [`update_var_bounds`](@ref) """ -discretization_to_bounds(d::Dict, l::Int) = Alp.update_var_bounds(d, len=l) +discretization_to_bounds(d::Dict, l::Int) = Alp.update_var_bounds(d, len = l) """ Update the data structure with feasible solution and its associated objective (if better) """ function update_incumb_objective(m::Optimizer, objval::Float64, sol::Vector) - convertor = Dict(MOI.MAX_SENSE => :>, MOI.MIN_SENSE => :<) - push!(m.logs[:obj], objval) - if eval(convertor[m.sense_orig])(objval, m.best_obj) #&& !eval(convertor[m.sense_orig])(objval, m.best_bound) - m.best_obj = objval - m.best_sol = sol - m.detected_feasible_solution = true - end - - return + convertor = Dict(MOI.MAX_SENSE => :>, MOI.MIN_SENSE => :<) + push!(m.logs[:obj], objval) + if eval(convertor[m.sense_orig])(objval, m.best_obj) #&& !eval(convertor[m.sense_orig])(objval, m.best_bound) + m.best_obj = objval + m.best_sol = sol + m.detected_feasible_solution = true + end + + return end """ @@ -119,47 +122,45 @@ end Prints values of all the variables after optimizing the original JuMP model. """ function variable_values(m::JuMP.Model) - for var in all_variables(m) - if isapprox(abs(JuMP.value(var)), 0, atol = 1E-6) - println("$var = 0.0") - else - println("$var = $(round(JuMP.value(var), digits = 5))") - end - end - - return + for var in all_variables(m) + if isapprox(abs(JuMP.value(var)), 0, atol = 1E-6) + println("$var = 0.0") + else + println("$var = $(round(JuMP.value(var), digits = 5))") + end + end + + return end - """ Mention the variable type of the lifted term. This function is with limited functionality """ function resolve_lifted_var_type(var_types::Vector{Symbol}, operator::Symbol) + if operator == :+ + detector = [i in [:Bin, :Int] ? true : false for i in var_types] + if length(detector) == 1 && detector[1] # Special case + if :Bin in var_types + return :Bin + else + return :Int + end + end + prod(detector) && return :Int + # o/w continous variables - if operator == :+ - detector = [i in [:Bin, :Int] ? true : false for i in var_types] - if length(detector) == 1 && detector[1] # Special case - if :Bin in var_types - return :Bin - else - return :Int - end - end - prod(detector) && return :Int - # o/w continous variables - - elseif operator == :* - detector = [i == :Bin ? true : false for i in var_types] - prod(detector) && return :Bin - detector = [i in [:Bin, :Int] ? true : false for i in var_types] - prod(detector) && return :Int - # o/w continous variables + elseif operator == :* + detector = [i == :Bin ? true : false for i in var_types] + prod(detector) && return :Bin + detector = [i in [:Bin, :Int] ? true : false for i in var_types] + prod(detector) && return :Int + # o/w continous variables - end + end - return :Cont + return :Cont end """ @@ -168,19 +169,27 @@ end Check if the solution is always the same within the last disc_consecutive_forbid iterations. Return `true` if solution has stalled. """ function check_solution_history(m::Optimizer, ind::Int) - - Alp.get_option(m, :disc_consecutive_forbid) == 0 && return false - (m.logs[:n_iter] < Alp.get_option(m, :disc_consecutive_forbid)) && return false - - sol_val = m.bound_sol_history[mod(m.logs[:n_iter]-1, Alp.get_option(m, :disc_consecutive_forbid))+1][ind] - for i in 1:(Alp.get_option(m, :disc_consecutive_forbid)-1) - search_pos = mod(m.logs[:n_iter]-1-i, Alp.get_option(m, :disc_consecutive_forbid))+1 - !isapprox(sol_val, m.bound_sol_history[search_pos][ind]; atol=Alp.get_option(m, :disc_rel_width_tol)) && return false - end - - Alp.get_option(m, :log_level) > 99 && println("Consecutive bounding solution on VAR$(ind) obtained. Diverting...") - - return true + Alp.get_option(m, :disc_consecutive_forbid) == 0 && return false + (m.logs[:n_iter] < Alp.get_option(m, :disc_consecutive_forbid)) && return false + + sol_val = m.bound_sol_history[mod( + m.logs[:n_iter] - 1, + Alp.get_option(m, :disc_consecutive_forbid), + )+1][ind] + for i in 1:(Alp.get_option(m, :disc_consecutive_forbid)-1) + search_pos = + mod(m.logs[:n_iter] - 1 - i, Alp.get_option(m, :disc_consecutive_forbid)) + 1 + !isapprox( + sol_val, + m.bound_sol_history[search_pos][ind]; + atol = Alp.get_option(m, :disc_rel_width_tol), + ) && return false + end + + Alp.get_option(m, :log_level) > 99 && + println("Consecutive bounding solution on VAR$(ind) obtained. Diverting...") + + return true end """ @@ -191,40 +200,42 @@ More specifically, it is used in [`local_solve`](@ref) to fix binary and integer and discretizing variables to the active domain according to lower bound solution. """ function fix_domains(m::Optimizer; discrete_sol = nothing, use_orig = false) + discrete_sol !== nothing && @assert length(discrete_sol) >= m.num_var_orig - discrete_sol !== nothing && @assert length(discrete_sol) >= m.num_var_orig + l_var = [m.l_var_tight[i] for i in 1:m.num_var_orig] + u_var = [m.u_var_tight[i] for i in 1:m.num_var_orig] - l_var = [m.l_var_tight[i] for i in 1:m.num_var_orig] - u_var = [m.u_var_tight[i] for i in 1:m.num_var_orig] - - for i in 1:m.num_var_orig - if i in m.disc_vars && m.var_type[i] == :Cont - point = if discrete_sol === nothing - m.best_bound_sol[i] - else - discrete_sol[i] - end - PCnt = length(m.discretization[i]) - 1 - for j in 1:PCnt - if point >= (m.discretization[i][j] - Alp.get_option(m, :tol)) && (point <= m.discretization[i][j+1] + Alp.get_option(m, :tol)) - @assert j < length(m.discretization[i]) - use_orig ? l_var[i] = m.discretization[i][1] : l_var[i] = m.discretization[i][j] - use_orig ? u_var[i] = m.discretization[i][end] : u_var[i] = m.discretization[i][j+1] - break + for i in 1:m.num_var_orig + if i in m.disc_vars && m.var_type[i] == :Cont + point = if discrete_sol === nothing + m.best_bound_sol[i] + else + discrete_sol[i] end - end - elseif m.var_type[i] == :Bin || m.var_type[i] == :Int - if discrete_sol === nothing - l_var[i] = round(m.best_bound_sol[i]) - u_var[i] = round(m.best_bound_sol[i]) - else - l_var[i] = round(discrete_sol[i]) - u_var[i] = round(discrete_sol[i]) - end - end - end + PCnt = length(m.discretization[i]) - 1 + for j in 1:PCnt + if point >= (m.discretization[i][j] - Alp.get_option(m, :tol)) && + (point <= m.discretization[i][j+1] + Alp.get_option(m, :tol)) + @assert j < length(m.discretization[i]) + use_orig ? l_var[i] = m.discretization[i][1] : + l_var[i] = m.discretization[i][j] + use_orig ? u_var[i] = m.discretization[i][end] : + u_var[i] = m.discretization[i][j+1] + break + end + end + elseif m.var_type[i] == :Bin || m.var_type[i] == :Int + if discrete_sol === nothing + l_var[i] = round(m.best_bound_sol[i]) + u_var[i] = round(m.best_bound_sol[i]) + else + l_var[i] = round(discrete_sol[i]) + u_var[i] = round(discrete_sol[i]) + end + end + end - return l_var, u_var + return l_var, u_var end """ @@ -232,33 +243,37 @@ end """ function is_fully_convexified(m::Optimizer) - # Other more advanced convexification check goes here - for term in keys(m.nonconvex_terms) - if !m.nonconvex_terms[term][:convexified] - @warn " Warning: Detected terms that is not convexified $(term[:lifted_constr_ref]), bounding model solver may report a error due to this" - return - else - m.nonconvex_terms[term][:convexified] = false # Reset status for next iteration - end - end - - return + # Other more advanced convexification check goes here + for term in keys(m.nonconvex_terms) + if !m.nonconvex_terms[term][:convexified] + @warn " Warning: Detected terms that is not convexified $(term[:lifted_constr_ref]), bounding model solver may report a error due to this" + return + else + m.nonconvex_terms[term][:convexified] = false # Reset status for next iteration + end + end + + return end """ Collect active partition idx Need to be careful with the diverted point """ -function get_active_partition_idx(discretization::Dict, val::Float64, idx::Int; tol=1e-6) - - for j in 1:length(discretization[idx])-1 - if val > discretization[idx][j] - tol && val < discretization[idx][j+1] + tol - return j - end - end - - @warn " Warning: Activate parition not found [VAR$(idx)]. Returning default partition 1." - return 1 +function get_active_partition_idx( + discretization::Dict, + val::Float64, + idx::Int; + tol = 1e-6, +) + for j in 1:length(discretization[idx])-1 + if val > discretization[idx][j] - tol && val < discretization[idx][j+1] + tol + return j + end + end + + @warn " Warning: Activate parition not found [VAR$(idx)]. Returning default partition 1." + return 1 end """ @@ -267,118 +282,116 @@ end A built-in method for selecting variables for discretization. This function selects all candidate variables in the nonlinear terms for discretization, if under a threshold value of the number of nonlinear terms. """ -function get_candidate_disc_vars(m::Optimizer;getoutput=false) +function get_candidate_disc_vars(m::Optimizer; getoutput = false) - # Pick variables that is bound width more than tolerance length - if getoutput - return [i for i in m.candidate_disc_vars] - else - m.disc_vars = [i for i in m.candidate_disc_vars] - m.num_var_disc_mip = length(m.disc_vars) - end + # Pick variables that is bound width more than tolerance length + if getoutput + return [i for i in m.candidate_disc_vars] + else + m.disc_vars = [i for i in m.candidate_disc_vars] + m.num_var_disc_mip = length(m.disc_vars) + end - return + return end function initialize_solution_pool(m::Optimizer, cnt::Int) + s = Dict() - s = Dict() + s[:cnt] = cnt - s[:cnt] = cnt + # Column dimension changing variable + s[:len] = m.num_var_orig + m.num_var_linear_mip + m.num_var_nonlinear_mip - # Column dimension changing variable - s[:len] = m.num_var_orig + m.num_var_linear_mip + m.num_var_nonlinear_mip + # !! Be careful with the :vars when utilizing the dynamic discretization variable selection !! + s[:vars] = [i for i in m.candidate_disc_vars if length(m.discretization[i]) > 2] - # !! Be careful with the :vars when utilizing the dynamic discretization variable selection !! - s[:vars] = [i for i in m.candidate_disc_vars if length(m.discretization[i]) > 2] + s[:sol] = Vector{Vector}(undef, cnt) # Solution value + s[:obj] = Vector{Float64}(undef, cnt) # Objecitve value + s[:disc] = Vector{Dict}(undef, cnt) # Discretization + s[:stat] = [:Alive for i in 1:cnt] # Solution status + s[:iter] = [m.logs[:n_iter] for i in 1:cnt] # Iteration collected + s[:ubstart] = [false for i in 1:cnt] # Solution used for ub multistart - s[:sol] = Vector{Vector}(undef, cnt) # Solution value - s[:obj] = Vector{Float64}(undef, cnt) # Objecitve value - s[:disc] = Vector{Dict}(undef, cnt) # Discretization - s[:stat] = [:Alive for i in 1:cnt] # Solution status - s[:iter] = [m.logs[:n_iter] for i in 1:cnt] # Iteration collected - s[:ubstart] = [false for i in 1:cnt] # Solution used for ub multistart - - return s + return s end """ Reconsideration required """ function ncvar_collect_arcs(m::Optimizer, nodes::Vector) - - arcs = Set() - - for k in keys(m.nonconvex_terms) - - if m.nonconvex_terms[k][:nonlinear_type] == :BILINEAR - arc = [i.args[2] for i in k] - length(arc) == 2 && push!(arcs, sort(arc)) - - elseif m.nonconvex_terms[k][:nonlinear_type] == :MONOMIAL - @assert isa(m.nonconvex_terms[k][:var_idxs][1], Int) - varidx = m.nonconvex_terms[k][:var_idxs][1] - push!(arcs, [varidx; varidx]) - - elseif m.nonconvex_terms[k][:nonlinear_type] == :MULTILINEAR - varidxs = m.nonconvex_terms[k][:var_idxs] - for i in 1:length(varidxs) - for j in 1:length(varidxs) - if i != j - push!(arcs, sort([varidxs[i]; varidxs[j]])) - end + arcs = Set() + + for k in keys(m.nonconvex_terms) + if m.nonconvex_terms[k][:nonlinear_type] == :BILINEAR + arc = [i.args[2] for i in k] + length(arc) == 2 && push!(arcs, sort(arc)) + + elseif m.nonconvex_terms[k][:nonlinear_type] == :MONOMIAL + @assert isa(m.nonconvex_terms[k][:var_idxs][1], Int) + varidx = m.nonconvex_terms[k][:var_idxs][1] + push!(arcs, [varidx; varidx]) + + elseif m.nonconvex_terms[k][:nonlinear_type] == :MULTILINEAR + varidxs = m.nonconvex_terms[k][:var_idxs] + for i in 1:length(varidxs) + for j in 1:length(varidxs) + if i != j + push!(arcs, sort([varidxs[i]; varidxs[j]])) + end + end + end + if length(varidxs) == 1 + push!(arcs, sort([varidxs[1]; varidxs[1]])) end - end - if length(varidxs) == 1 - push!(arcs, sort([varidxs[1]; varidxs[1]])) - end - - # elseif m.nonconvex_terms[k][:nonlinear_type] == :INTLIN - # var_idxs = copy(m.nonconvex_terms[k][:var_idxs]) - # push!(arcs, sort(var_idxs)) - # elseif m.nonconvex_terms[k][:nonlinear_type] == :INTPROD - # var_idxs = m.nonconvex_terms[k][:var_idxs] - # for i in 1:length(var_idxs) - # for j in 1:length(var_idxs) - # i != j && push!(arcs, sort([var_idxs[i]; var_idxs[j]])) - # end - # end - # elseif m.nonconvex_terms[k][:nonlinear_type] in [:cos, :sin] - # @assert length(m.nonconvex_terms[k][:var_idxs]) == 1 - # var_idx = m.nonconvex_terms[k][:var_idxs][1] - # push!(arcs, [var_idx; var_idx]) - - elseif m.nonconvex_terms[k][:nonlinear_type] in [:BININT, :BINLIN, :BINPROD] - continue - else - - error("[EXCEPTION] Unexpected nonlinear term when building interaction graphs for min. vertex cover.") - end - end - return arcs + # elseif m.nonconvex_terms[k][:nonlinear_type] == :INTLIN + # var_idxs = copy(m.nonconvex_terms[k][:var_idxs]) + # push!(arcs, sort(var_idxs)) + # elseif m.nonconvex_terms[k][:nonlinear_type] == :INTPROD + # var_idxs = m.nonconvex_terms[k][:var_idxs] + # for i in 1:length(var_idxs) + # for j in 1:length(var_idxs) + # i != j && push!(arcs, sort([var_idxs[i]; var_idxs[j]])) + # end + # end + # elseif m.nonconvex_terms[k][:nonlinear_type] in [:cos, :sin] + # @assert length(m.nonconvex_terms[k][:var_idxs]) == 1 + # var_idx = m.nonconvex_terms[k][:var_idxs][1] + # push!(arcs, [var_idx; var_idx]) + + elseif m.nonconvex_terms[k][:nonlinear_type] in [:BININT, :BINLIN, :BINPROD] + continue + else + error( + "[EXCEPTION] Unexpected nonlinear term when building interaction graphs for min. vertex cover.", + ) + end + end + + return arcs end """ """ function build_discvar_graph(m::Optimizer) - # Collect the information of nonlinear terms in terms of arcs and nodes - nodes = Alp.get_candidate_disc_vars(m, getoutput=true) - arcs = Alp.ncvar_collect_arcs(m, nodes) + # Collect the information of nonlinear terms in terms of arcs and nodes + nodes = Alp.get_candidate_disc_vars(m, getoutput = true) + arcs = Alp.ncvar_collect_arcs(m, nodes) - # Collect integer variables - for i in 1:m.num_var_orig - if !(i in nodes) && m.var_type[i] == :Int - push!(nodes, i) - push!(arcs, [i; i]) - end - end + # Collect integer variables + for i in 1:m.num_var_orig + if !(i in nodes) && m.var_type[i] == :Int + push!(nodes, i) + push!(arcs, [i; i]) + end + end - nodes = collect(nodes) - arcs = collect(arcs) + nodes = collect(nodes) + arcs = collect(arcs) - return nodes, arcs + return nodes, arcs end """ @@ -389,174 +402,185 @@ nonlinear terms which are adaptively partitioned for global optimization. This o setting `disc_var_pick = 1`. """ function min_vertex_cover(m::Optimizer) - - nodes, arcs = Alp.build_discvar_graph(m) - - # Set up minimum vertex cover problem - minvertex = Model(Alp.get_option(m, :mip_solver)) - MOI.set(minvertex, MOI.TimeLimitSec(), 60.0) # Time limit for min vertex cover formulation - JuMP.@variable(minvertex, 0 <= x[nodes] <= 1, Bin) - JuMP.@constraint(minvertex, [a in arcs], x[a[1]] + x[a[2]] >= 1) - JuMP.@objective(minvertex, Min, sum(x)) - - JuMP.optimize!(minvertex) - # status = MOI.get(minvertex, MOI.TerminationStatus()) - xVal = JuMP.value.(x) - - - # Collecting required information - m.num_var_disc_mip = Int(sum(xVal)) - m.disc_vars = [i for i in nodes if xVal[i] > Alp.get_option(m, :tol) && abs(m.u_var_tight[i]-m.l_var_tight[i]) >= Alp.get_option(m, :tol)] - - return + nodes, arcs = Alp.build_discvar_graph(m) + + # Set up minimum vertex cover problem + minvertex = Model(Alp.get_option(m, :mip_solver)) + MOI.set(minvertex, MOI.TimeLimitSec(), 60.0) # Time limit for min vertex cover formulation + JuMP.@variable(minvertex, 0 <= x[nodes] <= 1, Bin) + JuMP.@constraint(minvertex, [a in arcs], x[a[1]] + x[a[2]] >= 1) + JuMP.@objective(minvertex, Min, sum(x)) + + JuMP.optimize!(minvertex) + # status = MOI.get(minvertex, MOI.TerminationStatus()) + xVal = JuMP.value.(x) + + # Collecting required information + m.num_var_disc_mip = Int(sum(xVal)) + m.disc_vars = [ + i for i in nodes if xVal[i] > Alp.get_option(m, :tol) && + abs(m.u_var_tight[i] - m.l_var_tight[i]) >= Alp.get_option(m, :tol) + ] + + return end function weighted_min_vertex_cover(m::Optimizer, distance::Dict) - # Collect the graph information - nodes, arcs = Alp.build_discvar_graph(m) - - # A little bit redundancy before - disvec = [distance[i] for i in keys(distance) if i in m.candidate_disc_vars] - disvec = abs.(disvec[disvec .> 0.0]) - isempty(disvec) ? heavy = 1.0 : heavy = 1/minimum(disvec) - weights = Dict() - for i in m.candidate_disc_vars - isapprox(distance[i], 0.0; atol=1e-6) ? weights[i] = heavy : (weights[i]=(1/distance[i])) - (Alp.get_option(m, :log_level) > 100) && println("VAR$(i) WEIGHT -> $(weights[i]) ||| DISTANCE -> $(distance[i])") - end - - # Set up minimum vertex cover problem - minvertex = Model(Alp.get_option(m, :mip_solver)) - MOI.set(minvertex, MOI.TimeLimitSec(), 60.0) # Set a timer to avoid waste of time in proving optimality - JuMP.@variable(minvertex, 0 <= x[nodes] <= 1, Bin) - for arc in arcs - JuMP.@constraint(minvertex, x[arc[1]] + x[arc[2]] >= 1) - end - JuMP.@objective(minvertex, Min, sum(weights[i]*x[i] for i in nodes)) - - # Solve the minimum vertex cover - JuMP.optimize!(minvertex) - - xVal = JuMP.value.(x) - m.num_var_disc_mip = Int(sum(xVal)) - m.disc_vars = [i for i in nodes if xVal[i] > 0 && abs(m.u_var_tight[i]-m.l_var_tight[i]) >= Alp.get_option(m, :tol)] - Alp.get_option(m, :log_level) >= 99 && println("UPDATED DISC-VAR COUNT = $(length(m.disc_vars)) : $(m.disc_vars)") - - return + # Collect the graph information + nodes, arcs = Alp.build_discvar_graph(m) + + # A little bit redundancy before + disvec = [distance[i] for i in keys(distance) if i in m.candidate_disc_vars] + disvec = abs.(disvec[disvec.>0.0]) + isempty(disvec) ? heavy = 1.0 : heavy = 1 / minimum(disvec) + weights = Dict() + for i in m.candidate_disc_vars + isapprox(distance[i], 0.0; atol = 1e-6) ? weights[i] = heavy : + (weights[i] = (1 / distance[i])) + (Alp.get_option(m, :log_level) > 100) && + println("VAR$(i) WEIGHT -> $(weights[i]) ||| DISTANCE -> $(distance[i])") + end + + # Set up minimum vertex cover problem + minvertex = Model(Alp.get_option(m, :mip_solver)) + MOI.set(minvertex, MOI.TimeLimitSec(), 60.0) # Set a timer to avoid waste of time in proving optimality + JuMP.@variable(minvertex, 0 <= x[nodes] <= 1, Bin) + for arc in arcs + JuMP.@constraint(minvertex, x[arc[1]] + x[arc[2]] >= 1) + end + JuMP.@objective(minvertex, Min, sum(weights[i] * x[i] for i in nodes)) + + # Solve the minimum vertex cover + JuMP.optimize!(minvertex) + + xVal = JuMP.value.(x) + m.num_var_disc_mip = Int(sum(xVal)) + m.disc_vars = [ + i for i in nodes if xVal[i] > 0 && + abs(m.u_var_tight[i] - m.l_var_tight[i]) >= Alp.get_option(m, :tol) + ] + Alp.get_option(m, :log_level) >= 99 && + println("UPDATED DISC-VAR COUNT = $(length(m.disc_vars)) : $(m.disc_vars)") + + return end function round_sol(m::Optimizer, relaxed_sol) - rounded_sol = copy(relaxed_sol) - for i in 1:m.num_var_orig - if m.var_type_orig[i] == :Bin - relaxed_sol[i] >= 0.5 ? rounded_sol[i] = 1 : rounded_sol[i] = 0 - elseif m.var_type_orig[i] == :Int - rounded_sol[i] = round(relaxed_sol[i]) - else - rounded_sol[i] = relaxed_sol[i] - end - end - - return rounded_sol + rounded_sol = copy(relaxed_sol) + for i in 1:m.num_var_orig + if m.var_type_orig[i] == :Bin + relaxed_sol[i] >= 0.5 ? rounded_sol[i] = 1 : rounded_sol[i] = 0 + elseif m.var_type_orig[i] == :Int + rounded_sol[i] = round(relaxed_sol[i]) + else + rounded_sol[i] = relaxed_sol[i] + end + end + + return rounded_sol end -function fetch_mip_solver_identifier(m::Optimizer;override="") - - isempty(override) ? solverstring = string(Alp.get_option(m, :mip_solver)) : solverstring = override - - # Higher-level solvers: that can use sub-solvers - if occursin("Pajarito", solverstring) - m.mip_solver_id = "Pajarito" - return - elseif occursin("Pavito", solverstring) - m.mip_solver_id = "Pavito" - return - elseif occursin("Juniper", solverstring) - m.mip_solver_id = "Juniper" - return - end - - # Lower level solvers - if occursin("Gurobi", solverstring) - m.mip_solver_id = "Gurobi" - elseif occursin("CPLEX", solverstring) - m.mip_solver_id = "Cplex" - elseif occursin("Cbc", solverstring) # /!\ the `SolverName()` is "COIN Branch-and-Cut (Cbc)" - m.mip_solver_id = "Cbc" - elseif occursin("GLPK", solverstring) - m.mip_solver_id = "GLPK" - elseif occursin("HiGHS", solverstring) - m.mip_solver_id = "HiGHS" - elseif occursin("Xpress", solverstring) - m.mip_solver_id = "Xpress" - else - error("Unsupported MIP solver $solverstring; use a Alpine-supported MIP solver") - end - - return +function fetch_mip_solver_identifier(m::Optimizer; override = "") + isempty(override) ? solverstring = string(Alp.get_option(m, :mip_solver)) : + solverstring = override + + # Higher-level solvers: that can use sub-solvers + if occursin("Pajarito", solverstring) + m.mip_solver_id = "Pajarito" + return + elseif occursin("Pavito", solverstring) + m.mip_solver_id = "Pavito" + return + elseif occursin("Juniper", solverstring) + m.mip_solver_id = "Juniper" + return + end + + # Lower level solvers + if occursin("Gurobi", solverstring) + m.mip_solver_id = "Gurobi" + elseif occursin("CPLEX", solverstring) + m.mip_solver_id = "Cplex" + elseif occursin("Cbc", solverstring) # /!\ the `SolverName()` is "COIN Branch-and-Cut (Cbc)" + m.mip_solver_id = "Cbc" + elseif occursin("GLPK", solverstring) + m.mip_solver_id = "GLPK" + elseif occursin("HiGHS", solverstring) + m.mip_solver_id = "HiGHS" + elseif occursin("Xpress", solverstring) + m.mip_solver_id = "Xpress" + else + error("Unsupported MIP solver $solverstring; use a Alpine-supported MIP solver") + end + + return end -function fetch_nlp_solver_identifier(m::Optimizer;override="") - - isempty(override) ? solverstring = string(Alp.get_option(m, :nlp_solver)) : solverstring = override - - # Higher-level solver - if occursin("Pajarito", solverstring) - m.nlp_solver_id = "Pajarito" - return - elseif occursin("Pavito", solverstring) - m.nlp_solver_id = "Pavito" - return - end - - # Lower-level solver - if occursin("Ipopt", solverstring) - m.nlp_solver_id = "Ipopt" - elseif occursin("AmplNL", solverstring) && occursin("bonmin", solverstring) - m.nlp_solver_id = "Bonmin" - elseif occursin("KNITRO", solverstring) # /!\ the `SolverName()` is "Knitro" - m.nlp_solver_id = "Knitro" - elseif occursin("NLopt", solverstring) - m.nlp_solver_id = "NLopt" - else - error("Unsupported NLP local solver $solverstring; use a Alpine-supported NLP local solver") - end - - return +function fetch_nlp_solver_identifier(m::Optimizer; override = "") + isempty(override) ? solverstring = string(Alp.get_option(m, :nlp_solver)) : + solverstring = override + + # Higher-level solver + if occursin("Pajarito", solverstring) + m.nlp_solver_id = "Pajarito" + return + elseif occursin("Pavito", solverstring) + m.nlp_solver_id = "Pavito" + return + end + + # Lower-level solver + if occursin("Ipopt", solverstring) + m.nlp_solver_id = "Ipopt" + elseif occursin("AmplNL", solverstring) && occursin("bonmin", solverstring) + m.nlp_solver_id = "Bonmin" + elseif occursin("KNITRO", solverstring) # /!\ the `SolverName()` is "Knitro" + m.nlp_solver_id = "Knitro" + elseif occursin("NLopt", solverstring) + m.nlp_solver_id = "NLopt" + else + error( + "Unsupported NLP local solver $solverstring; use a Alpine-supported NLP local solver", + ) + end + + return end -function fetch_minlp_solver_identifier(m::Optimizer;override="") - - (Alp.get_option(m, :minlp_solver) === nothing) && return - - isempty(override) ? solverstring = string(Alp.get_option(m, :minlp_solver)) : solverstring = override - - # Higher-level solver - if occursin("Pajarito", solverstring) - m.minlp_solver_id = "Pajarito" - return - elseif occursin("Pavito", solverstring) - m.minlp_solver_id = "Pavito" - return - end - - # Lower-level Solver - if occursin("AmplNL", solverstring) && occursin("bonmin", solverstring) - m.minlp_solver_id = "Bonmin" - elseif occursin("KNITRO", solverstring) - m.minlp_solver_id = "Knitro" - elseif occursin("NLopt", solverstring) - m.minlp_solver_id = "NLopt" - elseif occursin("CoinOptServices.OsilSolver(\"bonmin\"", solverstring) - m.minlp_solver_id = "Bonmin" - elseif occursin("Juniper", solverstring) - m.minlp_solver_id = "Juniper" - else - error("Unsupported MINLP local solver $solverstring; use an Alpine-supported MINLP local solver (Juniper.jl for example)") - end - - return +function fetch_minlp_solver_identifier(m::Optimizer; override = "") + (Alp.get_option(m, :minlp_solver) === nothing) && return + + isempty(override) ? solverstring = string(Alp.get_option(m, :minlp_solver)) : + solverstring = override + + # Higher-level solver + if occursin("Pajarito", solverstring) + m.minlp_solver_id = "Pajarito" + return + elseif occursin("Pavito", solverstring) + m.minlp_solver_id = "Pavito" + return + end + + # Lower-level Solver + if occursin("AmplNL", solverstring) && occursin("bonmin", solverstring) + m.minlp_solver_id = "Bonmin" + elseif occursin("KNITRO", solverstring) + m.minlp_solver_id = "Knitro" + elseif occursin("NLopt", solverstring) + m.minlp_solver_id = "NLopt" + elseif occursin("CoinOptServices.OsilSolver(\"bonmin\"", solverstring) + m.minlp_solver_id = "Bonmin" + elseif occursin("Juniper", solverstring) + m.minlp_solver_id = "Juniper" + else + error( + "Unsupported MINLP local solver $solverstring; use an Alpine-supported MINLP local solver (Juniper.jl for example)", + ) + end + + return end """ @@ -565,32 +589,32 @@ end An utility function used to dynamically regulate MILP solver time limits to fit Alpine solver's time limits. """ function set_mip_time_limit(m::Optimizer) - time_limit = max(0.0, Alp.get_option(m, :time_limit) - m.logs[:total_time]) - MOI.set(m.model_mip, MOI.TimeLimitSec(), time_limit) + time_limit = max(0.0, Alp.get_option(m, :time_limit) - m.logs[:total_time]) + return MOI.set(m.model_mip, MOI.TimeLimitSec(), time_limit) end """ Follow the definition of terms to calculate the value of lifted terms """ function resolve_lifted_var_value(m::Optimizer, sol_vec::Array) - - @assert length(sol_vec) == m.num_var_orig - sol_vec = [sol_vec; fill(NaN, m.num_var_linear_mip+m.num_var_nonlinear_mip)] - - for i in 1:length(m.term_seq) - k = m.term_seq[i] - if haskey(m.nonconvex_terms, k) - lvar_idx = m.nonconvex_terms[k][:y_idx] - sol_vec[lvar_idx] = m.nonconvex_terms[k][:evaluator](m.nonconvex_terms[k], sol_vec) - elseif haskey(m.linear_terms, k) - lvar_idx = m.linear_terms[k][:y_idx] - sol_vec[lvar_idx] = m.linear_terms[k][:evaluator](m.linear_terms[k], sol_vec) - else - error("[RARE] Found homeless term key $(k) during bound resolution.") - end - end - - return sol_vec + @assert length(sol_vec) == m.num_var_orig + sol_vec = [sol_vec; fill(NaN, m.num_var_linear_mip + m.num_var_nonlinear_mip)] + + for i in 1:length(m.term_seq) + k = m.term_seq[i] + if haskey(m.nonconvex_terms, k) + lvar_idx = m.nonconvex_terms[k][:y_idx] + sol_vec[lvar_idx] = + m.nonconvex_terms[k][:evaluator](m.nonconvex_terms[k], sol_vec) + elseif haskey(m.linear_terms, k) + lvar_idx = m.linear_terms[k][:y_idx] + sol_vec[lvar_idx] = m.linear_terms[k][:evaluator](m.linear_terms[k], sol_vec) + else + error("[RARE] Found homeless term key $(k) during bound resolution.") + end + end + + return sol_vec end #-----------------------------------------------------------------# @@ -802,7 +826,6 @@ function eval_objective(m::Optimizer; svec::Vector=[]) return obj end - """ Special function for debugging bounding models """ @@ -840,7 +863,6 @@ function print_iis_gurobi(m::JuMP.Model) return end - """ eval_feasibility(m::Optimizer, sol::Vector) @@ -870,7 +892,7 @@ function eval_feasibility(m::Optimizer, sol::Vector) func = m.lin_quad_constraints[i][1] eval_rhs[i] = MOI.Utilities.eval_variables(vi -> rounded_sol[vi.value], func) end - + start = m.num_constr_orig - length(m.nl_constraint_bounds_orig) + 1 @assert start == length(m.lin_quad_constraints) + 1 interface_eval_g(m.d_orig, view(eval_rhs, start:m.num_constr_orig), rounded_sol) @@ -902,7 +924,6 @@ function eval_feasibility(m::Optimizer, sol::Vector) return feasible end - function adjust_branch_priority(m::Optimizer) if m.mip_solver_id == "Gurobi" @@ -928,4 +949,4 @@ function adjust_branch_priority(m::Optimizer) end -=# \ No newline at end of file +=# diff --git a/test/runtests.jl b/test/runtests.jl index b53f7b39..987631b3 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -13,10 +13,26 @@ for file in readdir(_EXAMPLES_DIR) include(joinpath(_EXAMPLES_DIR, file)) end -const IPOPT = MOI.OptimizerWithAttributes(Ipopt.Optimizer, MOI.Silent() => true, "sb" => "yes", "max_iter" => 9999) -const CBC = MOI.OptimizerWithAttributes(Cbc.Optimizer, MOI.Silent() => true) -const JUNIPER = MOI.OptimizerWithAttributes(Juniper.Optimizer, MOI.Silent() => true, "mip_solver" => CBC, "nl_solver" => IPOPT) -const PAVITO = MOI.OptimizerWithAttributes(Pavito.Optimizer, MOI.Silent() => true, "mip_solver" => CBC, "cont_solver" => IPOPT, "mip_solver_drives" => false) +const IPOPT = MOI.OptimizerWithAttributes( + Ipopt.Optimizer, + MOI.Silent() => true, + "sb" => "yes", + "max_iter" => 9999, +) +const CBC = MOI.OptimizerWithAttributes(Cbc.Optimizer, MOI.Silent() => true) +const JUNIPER = MOI.OptimizerWithAttributes( + Juniper.Optimizer, + MOI.Silent() => true, + "mip_solver" => CBC, + "nl_solver" => IPOPT, +) +const PAVITO = MOI.OptimizerWithAttributes( + Pavito.Optimizer, + MOI.Silent() => true, + "mip_solver" => CBC, + "cont_solver" => IPOPT, + "mip_solver_drives" => false, +) function _build(model::JuMP.Model) JuMP.set_optimize_hook(model, MOI.Utilities.attach_optimizer) diff --git a/test/test_algorithm.jl b/test/test_algorithm.jl index 806f4402..01151a44 100644 --- a/test/test_algorithm.jl +++ b/test/test_algorithm.jl @@ -1,83 +1,89 @@ @testset " Validation Test || AMP-TMC || basic solve || examples/nlp1.jl" begin - - test_solver = optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => PAVITO, - "bilinear_convexhull" => false, - "monomial_convexhull" => false, - "presolve_bt" => false, - "presolve_bp" => true, - "presolve_bt_bound_tol" => 1e-1, - "disc_ratio" => 10, - "log_level" =>100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => PAVITO, + "bilinear_convexhull" => false, + "monomial_convexhull" => false, + "presolve_bt" => false, + "presolve_bp" => true, + "presolve_bt_bound_tol" => 1e-1, + "disc_ratio" => 10, + "log_level" => 100, + ) m = nlp1(solver = test_solver) JuMP.optimize!(m) @test termination_status(m) == MOI.OPTIMAL - @test isapprox(objective_value(m), 58.38367169858795; atol=1e-4) + @test isapprox(objective_value(m), 58.38367169858795; atol = 1e-4) @test MOI.get(m, Alpine.NumberOfIterations()) == 4 end @testset " Validation Test || AMP-TMC || basic solve || examples/nlp3.jl (2 iterations)" begin - - test_solver=optimizer_with_attributes(Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "bilinear_convexhull" => false, - "monomial_convexhull" => false, - "presolve_bp" => true, - "log_level" =>100, - "max_iter" => 2, - "presolve_bt_width_tol" => 1e-3, - "presolve_bt" => false, - "disc_ratio" => 10, - "disc_var_pick" => 0) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "bilinear_convexhull" => false, + "monomial_convexhull" => false, + "presolve_bp" => true, + "log_level" => 100, + "max_iter" => 2, + "presolve_bt_width_tol" => 1e-3, + "presolve_bt" => false, + "disc_ratio" => 10, + "disc_var_pick" => 0, + ) m = nlp3(solver = test_solver) JuMP.optimize!(m) @test termination_status(m) == MOI.OTHER_LIMIT - @test isapprox(objective_value(m), 7049.247897696512; atol=1e-4) + @test isapprox(objective_value(m), 7049.247897696512; atol = 1e-4) @test MOI.get(m, Alpine.NumberOfIterations()) == 2 end @testset " Validation Test || AMP-TMC || minimum-vertex solving || examples/nlp3.jl (3 iterations)" begin - - test_solver=optimizer_with_attributes(Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "bilinear_convexhull" => false, - "monomial_convexhull" => false, - "presolve_bp" => true, - "disc_var_pick" => 1, - "log_level" =>100, - "max_iter" => 2, - "disc_ratio" => 10, - "presolve_bt_width_tol" => 1e-3, - "presolve_bt" => false) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "bilinear_convexhull" => false, + "monomial_convexhull" => false, + "presolve_bp" => true, + "disc_var_pick" => 1, + "log_level" => 100, + "max_iter" => 2, + "disc_ratio" => 10, + "presolve_bt_width_tol" => 1e-3, + "presolve_bt" => false, + ) m = nlp3(solver = test_solver) JuMP.optimize!(m) @test termination_status(m) == MOI.OTHER_LIMIT - @test isapprox(objective_value(m), 7049.247897696512; atol=1e-4) + @test isapprox(objective_value(m), 7049.247897696512; atol = 1e-4) @test MOI.get(m, Alpine.NumberOfIterations()) == 2 end @testset " Validation Test || BT-AMP-TMC || basic solve || examples/nlp3.jl" begin - - test_solver = optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "bilinear_convexhull" => false, - "log_level" =>100, - "max_iter" => 2, - "disc_ratio" => 10, - "presolve_bt_width_tol" => 1e-3, - "presolve_bt_bound_tol" => 1e-1, - "presolve_bt" => true, - "presolve_bt_algo" => 1, - "presolve_bp" => true, - "presolve_bt_max_iter" => 2, - "presolve_track_time" => true, - "disc_var_pick" => max_cover_var_picker) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "bilinear_convexhull" => false, + "log_level" => 100, + "max_iter" => 2, + "disc_ratio" => 10, + "presolve_bt_width_tol" => 1e-3, + "presolve_bt_bound_tol" => 1e-1, + "presolve_bt" => true, + "presolve_bt_algo" => 1, + "presolve_bp" => true, + "presolve_bt_max_iter" => 2, + "presolve_track_time" => true, + "disc_var_pick" => max_cover_var_picker, + ) m = nlp3(solver = test_solver) JuMP.optimize!(m) @@ -87,239 +93,265 @@ end @test MOI.get(m, Alpine.NumberOfPresolveIterations()) == 2 vars = all_variables(m) - @test MOI.get.(m, Alpine.TightenedLowerBound(), vars) ≈ [100, 999.9, 999.9, 10, 150.2, 10, 35.4, 168] rtol=1e-6 - @test MOI.get.(m, Alpine.TightenedUpperBound(), vars) ≈ [4573.8, 5547.9, 5913.4, 332.4, 551, 390, 571.1, 638.7] rtol=1e-6 + @test MOI.get.(m, Alpine.TightenedLowerBound(), vars) ≈ + [100, 999.9, 999.9, 10, 150.2, 10, 35.4, 168] rtol = 1e-6 + @test MOI.get.(m, Alpine.TightenedUpperBound(), vars) ≈ + [4573.8, 5547.9, 5913.4, 332.4, 551, 390, 571.1, 638.7] rtol = 1e-6 end # FIXME Pavito terminates with `NUMERICAL_ERROR` on Julia v1.0: @testset " Validation Test || PBT-AMP-TMC || basic solve || examples/nlp3.jl" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "bilinear_convexhull" => false, + "log_level" => 100, + "max_iter" => 2, + "disc_ratio" => 10, + "presolve_bt" => true, + "presolve_bt_width_tol" => 1e-3, + "presolve_bt_bound_tol" => 1e-1, + "presolve_bt_algo" => 2, + "presolve_bp" => true, + "presolve_bt_max_iter" => 2, + "disc_var_pick" => max_cover_var_picker, + ) - test_solver = optimizer_with_attributes(Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "bilinear_convexhull" => false, - "log_level" =>100, - "max_iter" => 2, - "disc_ratio" => 10, - "presolve_bt" => true, - "presolve_bt_width_tol" => 1e-3, - "presolve_bt_bound_tol" => 1e-1, - "presolve_bt_algo" => 2, - "presolve_bp" => true, - "presolve_bt_max_iter" => 2, - "disc_var_pick" => max_cover_var_picker) - - m = nlp3(solver = test_solver) - JuMP.optimize!(m) - @test termination_status(m) == MOI.OTHER_LIMIT - @test MOI.get(m, Alpine.NumberOfIterations()) == 2 + m = nlp3(solver = test_solver) + JuMP.optimize!(m) + @test termination_status(m) == MOI.OTHER_LIMIT + @test MOI.get(m, Alpine.NumberOfIterations()) == 2 end @testset " Validation Test || AMP-CONV || basic solve || examples/nlp1.jl" begin - test_solver = optimizer_with_attributes(Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => PAVITO, - "bilinear_convexhull" => true, - "monomial_convexhull" => true, - "presolve_bt" => false, - "presolve_bp" => true, - "disc_ratio" => 10, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => PAVITO, + "bilinear_convexhull" => true, + "monomial_convexhull" => true, + "presolve_bt" => false, + "presolve_bp" => true, + "disc_ratio" => 10, + "log_level" => 100, + ) m = nlp1(solver = test_solver) JuMP.optimize!(m) @test termination_status(m) == MOI.OPTIMAL - @test isapprox(objective_value(m), 58.38367169858795; atol=1e-4) + @test isapprox(objective_value(m), 58.38367169858795; atol = 1e-4) @test MOI.get(m, Alpine.NumberOfIterations()) == 4 end @testset " Validation Test || AMP-CONV || basic solve || examples/nlp3.jl" begin - test_solver = optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "bilinear_convexhull" => true, - "monomial_convexhull" => true, - "presolve_bt" => false, - "presolve_bp" => false, - "disc_ratio" => 14, - "max_iter" => 4, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "bilinear_convexhull" => true, + "monomial_convexhull" => true, + "presolve_bt" => false, + "presolve_bp" => false, + "disc_ratio" => 14, + "max_iter" => 4, + "log_level" => 100, + ) m = nlp3(solver = test_solver) JuMP.optimize!(m) @test termination_status(m) == MOI.OTHER_LIMIT - @test isapprox(objective_value(m), 7049.24789; atol=1e-4) + @test isapprox(objective_value(m), 7049.24789; atol = 1e-4) @test isapprox(objective_bound(m), 6839.487709940, atol = 1E-4) @test MOI.get(m, Alpine.NumberOfIterations()) == 4 end @testset " Validation Test || AMP || basic solve || examples/circle.jl" begin - test_solver=optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => PAVITO, - "disc_abs_width_tol" => 1e-3, - "disc_ratio" => 8, - "max_iter" => 6, - "presolve_bt" => false, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => PAVITO, + "disc_abs_width_tol" => 1e-3, + "disc_ratio" => 8, + "max_iter" => 6, + "presolve_bt" => false, + "log_level" => 100, + ) m = circle(solver = test_solver) # This is fixed in Alpine - TODO (odow): cycling detected in Pavito when disc_abs_width_tol = 1E-2 JuMP.optimize!(m) - @test isapprox(objective_value(m), 1.4142135534556992; atol=1e-3) + @test isapprox(objective_value(m), 1.4142135534556992; atol = 1e-3) end @testset " Validation Test || AMP || basic solve || examples/circle_MINLPLib.jl" begin - test_solver=optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => PAVITO, - "disc_abs_width_tol" => 1e-2, - "disc_ratio" => 5, - "presolve_bt" => true, - "presolve_bt_max_iter" => 1, - "presolve_bt_algo" => 1, - "presolve_bt_bound_tol" => 1e-2, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => PAVITO, + "disc_abs_width_tol" => 1e-2, + "disc_ratio" => 5, + "presolve_bt" => true, + "presolve_bt_max_iter" => 1, + "presolve_bt_algo" => 1, + "presolve_bt_bound_tol" => 1e-2, + "log_level" => 100, + ) m = circle_MINLPLib(solver = test_solver) - + JuMP.optimize!(m) - @test isapprox(objective_value(m), 4.45670663096; atol=1E-6) + @test isapprox(objective_value(m), 4.45670663096; atol = 1E-6) end @testset " Validation Test || AMP-CONV-FACET || basic solve || examples/nlp3.jl" begin - test_solver = optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "bilinear_convexhull" => true, - "monomial_convexhull" => true, - "presolve_bt" => false, - "presolve_bp" => true, - "convhull_formulation" => "facet", - "max_iter" => 3, - "log_level" => 100) - m = nlp3(solver = test_solver) - JuMP.optimize!(m) - - @test isapprox(objective_value(m), 7049.247897696188; atol=1e-4) - @test isapprox(objective_bound(m), 6654.6983279983; atol=1e-4) - @test MOI.get(m, Alpine.NumberOfIterations()) == 3 + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "bilinear_convexhull" => true, + "monomial_convexhull" => true, + "presolve_bt" => false, + "presolve_bp" => true, + "convhull_formulation" => "facet", + "max_iter" => 3, + "log_level" => 100, + ) + m = nlp3(solver = test_solver) + JuMP.optimize!(m) + + @test isapprox(objective_value(m), 7049.247897696188; atol = 1e-4) + @test isapprox(objective_bound(m), 6654.6983279983; atol = 1e-4) + @test MOI.get(m, Alpine.NumberOfIterations()) == 3 end @testset " Validation Test || AMP || multi4N || N = 2 || exprmode=1:11" begin - n_instances = 11 objValVec = 2.0 * ones(n_instances) - + for i in 1:n_instances - test_solver=optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "disc_abs_width_tol" => 1e-2, - "max_iter" => 4, - "disc_ratio" => 4, - "presolve_bp" => false, - "presolve_bt" => false, - "log_level" => 1) - - m = multi4N(solver = test_solver, N=2, exprmode=i) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "disc_abs_width_tol" => 1e-2, + "max_iter" => 4, + "disc_ratio" => 4, + "presolve_bp" => false, + "presolve_bt" => false, + "log_level" => 1, + ) + + m = multi4N(solver = test_solver, N = 2, exprmode = i) JuMP.optimize!(m) @test termination_status(m) == MOI.OTHER_LIMIT - @test isapprox(objective_value(m), objValVec[i]; atol=1e-3) + @test isapprox(objective_value(m), objValVec[i]; atol = 1e-3) end end @testset " Validation Test || AMP || multi2 || exprmode=1:11" begin - - test_solver=optimizer_with_attributes(Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "disc_abs_width_tol" => 1e-2, - "max_iter" => 5, - "presolve_bt" => false, - "log_level" => 1) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "disc_abs_width_tol" => 1e-2, + "max_iter" => 5, + "presolve_bt" => false, + "log_level" => 1, + ) m = multi2(solver = test_solver) JuMP.optimize!(m) @test termination_status(m) == MOI.OPTIMAL - @test isapprox(objective_value(m), 0.92906489; atol=1e-3) + @test isapprox(objective_value(m), 0.92906489; atol = 1e-3) end @testset " Validation Test || AMP || multi3N || N = 2 || exprmode=1:11" begin - n_instances = 3 objValVec = 2.0 * ones(n_instances) objBoundVec = Any[2.97186, 3.85492, 4.23375] for i in 1:n_instances - test_solver=optimizer_with_attributes(Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "disc_abs_width_tol" => 1e-2, - "max_iter" => 4, - "disc_ratio" => 4, - "presolve_bp" => false, - "presolve_bt" => false, - "log_level" => 1) - - m = multi3N(solver = test_solver, N=2, exprmode=i) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "disc_abs_width_tol" => 1e-2, + "max_iter" => 4, + "disc_ratio" => 4, + "presolve_bp" => false, + "presolve_bt" => false, + "log_level" => 1, + ) + + m = multi3N(solver = test_solver, N = 2, exprmode = i) JuMP.optimize!(m) @test termination_status(m) == MOI.OTHER_LIMIT - @test isapprox(objective_value(m), objValVec[i]; atol=1e-3) + @test isapprox(objective_value(m), objValVec[i]; atol = 1e-3) @test objective_bound(m) <= objBoundVec[i] + 1e-3 end end @testset " Validation Test || AMP || multiKND || K = 3, N = 3, D = 0 " begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "disc_abs_width_tol" => 1e-2, + "max_iter" => 3, + "disc_ratio" => 4, + "presolve_bp" => false, + "presolve_bt" => false, + "log_level" => 1, + ) - test_solver=optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "disc_abs_width_tol" => 1e-2, - "max_iter" => 3, - "disc_ratio" => 4, - "presolve_bp" => false, - "presolve_bt" => false, - "log_level" =>1) - - m = multiKND(solver = test_solver, randomub=50, K=3, N=3, D=0) + m = multiKND(solver = test_solver, randomub = 50, K = 3, N = 3, D = 0) JuMP.optimize!(m) @test termination_status(m) == MOI.OTHER_LIMIT - @test isapprox(objective_value(m),3.0000000824779454;atol=1e-3) - @test isapprox(objective_bound(m),12.054604248046875;atol=1e-3) + @test isapprox(objective_value(m), 3.0000000824779454; atol = 1e-3) + @test isapprox(objective_bound(m), 12.054604248046875; atol = 1e-3) end @testset " Validation Test || AMP-CONV-FACET || basic solve || examples/nlp3.jl" begin - test_solver = optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "bilinear_convexhull" => true, - "monomial_convexhull" => true, - "presolve_bt" => false, - "presolve_bp" => false, - "max_iter" => 3, - "disc_ratio" => 4, - "convhull_formulation" => "facet", - "log_level" =>100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "bilinear_convexhull" => true, + "monomial_convexhull" => true, + "presolve_bt" => false, + "presolve_bp" => false, + "max_iter" => 3, + "disc_ratio" => 4, + "convhull_formulation" => "facet", + "log_level" => 100, + ) m = nlp3(solver = test_solver) JuMP.optimize!(m) @test termination_status(m) == MOI.OTHER_LIMIT - @test isapprox(objective_value(m), 7049.247897696188; atol=1e-4) + @test isapprox(objective_value(m), 7049.247897696188; atol = 1e-4) @test isapprox(objective_bound(m), 5871.530692199214; atol = 1E-5) @test MOI.get(m, Alpine.NumberOfIterations()) == 3 end @testset " Validation Test || AMP || DISC-RATIO || examples/nlp3.jl " begin - test_solver=optimizer_with_attributes(Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "disc_abs_width_tol" => 1e-2, - "disc_ratio_branch" => false, - "disc_ratio" => 18, - "max_iter" => 1, - "presolve_bp" => true, - "presolve_bt" => false, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "disc_abs_width_tol" => 1e-2, + "disc_ratio_branch" => false, + "disc_ratio" => 18, + "max_iter" => 1, + "presolve_bp" => true, + "presolve_bt" => false, + "log_level" => 100, + ) m = nlp3(solver = test_solver) JuMP.optimize!(m) @@ -329,14 +361,17 @@ end end @testset " Validation Test || AMP || DISC-RATIO-BRANCH || examples/nlp3.jl " begin - test_solver=optimizer_with_attributes(Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "disc_abs_width_tol" => 1e-2, - "disc_ratio_branch" => true, - "max_iter" => 1, - "presolve_bp" => true, - "presolve_bt" => false, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "disc_abs_width_tol" => 1e-2, + "disc_ratio_branch" => true, + "max_iter" => 1, + "presolve_bp" => true, + "presolve_bt" => false, + "log_level" => 100, + ) m = nlp3(solver = test_solver) JuMP.optimize!(m) @@ -346,14 +381,17 @@ end end @testset " Validation Test || AMP || DISC-RATIO-BRANCH || examples/castro2m2.jl " begin - test_solver=optimizer_with_attributes(Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "disc_abs_width_tol" => 1e-2, - "disc_ratio_branch" => true, - "max_iter" => 1, - "presolve_bp" => true, - "presolve_bt" => false, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "disc_abs_width_tol" => 1e-2, + "disc_ratio_branch" => true, + "max_iter" => 1, + "presolve_bp" => true, + "presolve_bt" => false, + "log_level" => 100, + ) m = castro2m2(solver = test_solver) JuMP.optimize!(m) @@ -363,16 +401,19 @@ end end @testset " Validation Test || AMP || DISC-RATIO-BRANCH || examples/multi3N.jl exprmode=2" begin - test_solver=optimizer_with_attributes(Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "disc_abs_width_tol" => 1e-2, - "disc_ratio_branch" => true, - "max_iter" => 1, - "presolve_bp" => true, - "presolve_bt" => false, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "disc_abs_width_tol" => 1e-2, + "disc_ratio_branch" => true, + "max_iter" => 1, + "presolve_bp" => true, + "presolve_bt" => false, + "log_level" => 100, + ) - m = multi3N(solver = test_solver, N=3, exprmode=1) + m = multi3N(solver = test_solver, N = 3, exprmode = 1) JuMP.optimize!(m) @test MOI.get(m, Alpine.NumberOfIterations()) == 1 @@ -380,16 +421,19 @@ end end @testset " Validation Test || AMP || DISC-RATIO-BRANCH || examples/multi3N.jl exprmode=2" begin - test_solver=optimizer_with_attributes(Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "disc_abs_width_tol" => 1e-2, - "disc_ratio_branch" => true, - "max_iter" => 1, - "presolve_bp" => false, - "presolve_bt" => false, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "disc_abs_width_tol" => 1e-2, + "disc_ratio_branch" => true, + "max_iter" => 1, + "presolve_bp" => false, + "presolve_bt" => false, + "log_level" => 100, + ) - m = multi3N(solver = test_solver, N=3, exprmode=1) + m = multi3N(solver = test_solver, N = 3, exprmode = 1) JuMP.optimize!(m) @test MOI.get(m, Alpine.NumberOfIterations()) == 1 @@ -397,16 +441,19 @@ end end @testset " Validation Test || AMP || DISC-RATIO-BRANCH || examples/multi4N.jl exprmode=1" begin - test_solver=optimizer_with_attributes(Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "disc_abs_width_tol" => 1e-2, - "disc_ratio_branch" => true, - "max_iter" => 1, - "presolve_bp" => true, - "presolve_bt" => false, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "disc_abs_width_tol" => 1e-2, + "disc_ratio_branch" => true, + "max_iter" => 1, + "presolve_bp" => true, + "presolve_bt" => false, + "log_level" => 100, + ) - m = multi4N(solver = test_solver, N=2, exprmode=1) + m = multi4N(solver = test_solver, N = 2, exprmode = 1) JuMP.optimize!(m) @test MOI.get(m, Alpine.NumberOfIterations()) == 1 @@ -414,16 +461,19 @@ end end @testset " Validation Test || AMP || DISC-RATIO-BRANCH || examples/multi4N.jl exprmode=2" begin - test_solver=optimizer_with_attributes(Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "disc_abs_width_tol" => 1e-2, - "disc_ratio_branch" => true, - "max_iter" => 1, - "presolve_bp" => false, - "presolve_bt" => false, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "disc_abs_width_tol" => 1e-2, + "disc_ratio_branch" => true, + "max_iter" => 1, + "presolve_bp" => false, + "presolve_bt" => false, + "log_level" => 100, + ) - m = multi4N(solver = test_solver, N=2, exprmode=1) + m = multi4N(solver = test_solver, N = 2, exprmode = 1) JuMP.optimize!(m) @test MOI.get(m, Alpine.NumberOfIterations()) == 1 @@ -431,16 +481,19 @@ end end @testset " Validation Test || AMP || DISC-RATIO-BRANCH || examples/multi4N.jl exprmode=2" begin - test_solver=optimizer_with_attributes(Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "disc_abs_width_tol" => 1e-2, - "disc_ratio_branch" => true, - "max_iter" => 1, - "presolve_bp" => true, - "presolve_bt" => false, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "disc_abs_width_tol" => 1e-2, + "disc_ratio_branch" => true, + "max_iter" => 1, + "presolve_bp" => true, + "presolve_bt" => false, + "log_level" => 100, + ) - m = multi4N(solver = test_solver, N=2, exprmode=2) + m = multi4N(solver = test_solver, N = 2, exprmode = 2) JuMP.optimize!(m) @test MOI.get(m, Alpine.NumberOfIterations()) == 1 @@ -448,16 +501,18 @@ end end @testset "Operator :: bmpl && binlin && binprod solve test I" begin - test_solver=optimizer_with_attributes(Alpine.Optimizer, - "minlp_solver" => PAVITO, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "presolve_bt" => false, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "minlp_solver" => PAVITO, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "presolve_bt" => false, + "log_level" => 100, + ) m = bpml_lnl(solver = test_solver) JuMP.optimize!(m) - @test isapprox(objective_value(m), 0.3; atol=1e-6) + @test isapprox(objective_value(m), 0.3; atol = 1e-6) alpine = JuMP.backend(m).optimizer.model @test haskey(alpine.nonconvex_terms, Expr[:(x[1]), :(x[6])]) @test haskey(alpine.nonconvex_terms, Expr[:(x[2]), :(x[7])]) @@ -473,13 +528,15 @@ end end @testset "Operator :: bmpl && binlin && binprod solve test II" begin - test_solver=optimizer_with_attributes(Alpine.Optimizer, - "minlp_solver" => JUNIPER, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "presolve_bt" => false, - "disc_ratio" => 4, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "minlp_solver" => JUNIPER, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "presolve_bt" => false, + "disc_ratio" => 4, + "log_level" => 100, + ) m = bpml_binl(solver = test_solver) @@ -513,23 +570,25 @@ end end @testset "Embedding Test || AMP-CONV || basic solve || examples/nlp1.jl" begin - test_solver = optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => PAVITO, - "bilinear_convexhull" => true, - "monomial_convexhull" => true, - "presolve_bt" => false, - "presolve_bp" => true, - "convhull_ebd" => true, - "max_iter" => 4, - "disc_ratio" => 4, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => PAVITO, + "bilinear_convexhull" => true, + "monomial_convexhull" => true, + "presolve_bt" => false, + "presolve_bp" => true, + "convhull_ebd" => true, + "max_iter" => 4, + "disc_ratio" => 4, + "log_level" => 100, + ) m = nlp1(solver = test_solver) JuMP.optimize!(m) @test termination_status(m) == MOI.OTHER_LIMIT - @test isapprox(objective_value(m), 58.38367169858795; atol=1e-4) + @test isapprox(objective_value(m), 58.38367169858795; atol = 1e-4) @test MOI.get(m, Alpine.NumberOfIterations()) == 4 end @@ -554,109 +613,125 @@ end # end @testset "Embedding IBS Test || AMP-CONV || basic solve || examples/nlp1.jl" begin - test_solver = optimizer_with_attributes(Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => PAVITO, - "bilinear_convexhull" => true, - "monomial_convexhull" => true, - "presolve_bt" => false, - "presolve_bp" => true, - "convhull_ebd" => true, - "convhull_ebd_ibs" => true, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => PAVITO, + "bilinear_convexhull" => true, + "monomial_convexhull" => true, + "presolve_bt" => false, + "presolve_bp" => true, + "convhull_ebd" => true, + "convhull_ebd_ibs" => true, + "log_level" => 100, + ) m = nlp1(solver = test_solver) JuMP.optimize!(m) @test termination_status(m) == MOI.OPTIMAL - @test isapprox(objective_value(m), 58.38367169858795; atol=1e-4) + @test isapprox(objective_value(m), 58.38367169858795; atol = 1e-4) @test MOI.get(m, Alpine.NumberOfIterations()) == 4 end @testset "Embedding IBS Test || AMP-CONV || basic solve || examples/nlp3.jl" begin - test_solver = optimizer_with_attributes(Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "bilinear_convexhull" => true, - "monomial_convexhull" => true, - "presolve_bt" => false, - "presolve_bp" => false, - "convhull_ebd" => true, - "convhull_ebd_ibs" => true, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "bilinear_convexhull" => true, + "monomial_convexhull" => true, + "presolve_bt" => false, + "presolve_bp" => false, + "convhull_ebd" => true, + "convhull_ebd_ibs" => true, + "log_level" => 100, + ) m = nlp3(solver = test_solver) JuMP.optimize!(m) @test termination_status(m) == MOI.OPTIMAL - @test isapprox(objective_value(m), 7049.247897696188; atol=1e-4) + @test isapprox(objective_value(m), 7049.247897696188; atol = 1e-4) @test MOI.get(m, Alpine.NumberOfIterations()) == 9 end @testset "Embedding IBS Test || AMP || special problem || ... " begin - test_solver=optimizer_with_attributes(Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => PAVITO, - "disc_abs_width_tol" => 1e-3, - "disc_ratio" => 8, - "max_iter" => 6, - "presolve_bt" => false, - "presolve_bp" => true, - "presolve_bt_algo" => 1, - "presolve_bt_bound_tol" => 1e-1, - "convhull_ebd" => true, - "convhull_ebd_ibs" => true, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => PAVITO, + "disc_abs_width_tol" => 1e-3, + "disc_ratio" => 8, + "max_iter" => 6, + "presolve_bt" => false, + "presolve_bp" => true, + "presolve_bt_algo" => 1, + "presolve_bt_bound_tol" => 1e-1, + "convhull_ebd" => true, + "convhull_ebd_ibs" => true, + "log_level" => 100, + ) m = circle(solver = test_solver) # This is fixed in Alpine - TODO(odow): mixed-integer cycling detected, terminating Pavito JuMP.optimize!(m) - @test isapprox(objective_value(m), 1.41421355; atol=1e-3) + @test isapprox(objective_value(m), 1.41421355; atol = 1e-3) end @testset "Embedding LINK Test || AMP-CONV || basic solve || examples/nlp1.jl" begin - test_solver = optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => PAVITO, - "bilinear_convexhull" => true, - "monomial_convexhull" => true, - "presolve_bt" => false, - "presolve_bp" => true, - "convhull_ebd" => true, - "convhull_ebd_link" => true, - "disc_ratio" => 12, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => PAVITO, + "bilinear_convexhull" => true, + "monomial_convexhull" => true, + "presolve_bt" => false, + "presolve_bp" => true, + "convhull_ebd" => true, + "convhull_ebd_link" => true, + "disc_ratio" => 12, + "log_level" => 100, + ) m = nlp1(solver = test_solver) JuMP.optimize!(m) @test termination_status(m) == MOI.OPTIMAL - @test isapprox(objective_value(m), 58.38367169858795; atol=1e-4) + @test isapprox(objective_value(m), 58.38367169858795; atol = 1e-4) @test MOI.get(m, Alpine.NumberOfIterations()) == 3 end @testset "Embedding LINK Test || AMP-CONV || basic solve || examples/nlp3.jl" begin - test_solver = optimizer_with_attributes(Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "bilinear_convexhull" => true, - "monomial_convexhull" => true, - "presolve_bt" => false, - "presolve_bp" => false, - "convhull_ebd" => true, - "convhull_ebd_link" => true, - "disc_ratio" => 10, - "max_iter" => 3, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "bilinear_convexhull" => true, + "monomial_convexhull" => true, + "presolve_bt" => false, + "presolve_bp" => false, + "convhull_ebd" => true, + "convhull_ebd_link" => true, + "disc_ratio" => 10, + "max_iter" => 3, + "log_level" => 100, + ) m = nlp3(solver = test_solver) JuMP.optimize!(m) @test termination_status(m) == MOI.OTHER_LIMIT - @test isapprox(objective_value(m), 7049.247897696188; atol=1e-4) + @test isapprox(objective_value(m), 7049.247897696188; atol = 1e-4) @test MOI.get(m, Alpine.NumberOfIterations()) == 3 end @testset "Algorithm Logic Test || castro4m2 || 1 iteration || Error case" begin - test_solver=optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "max_iter" => 1, - "presolve_bt" => false, - "disc_ratio" => 10, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "max_iter" => 1, + "presolve_bt" => false, + "disc_ratio" => 10, + "log_level" => 100, + ) m = castro4m2(solver = test_solver) JuMP.optimize!(m) @@ -664,18 +739,19 @@ end end @testset " Algorithm Logic Test || blend029_gl || 3 iterations || Infeasible Case" begin - - test_solver=optimizer_with_attributes(Alpine.Optimizer, - "minlp_solver" => PAVITO, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "presolve_bp" => true, - "disc_var_pick" => 1, - "log_level" => 100, - "max_iter" => 3, - "disc_ratio" => 10, - "presolve_bt_width_tol" => 1e-3, - "presolve_bt" => false) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "minlp_solver" => PAVITO, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "presolve_bp" => true, + "disc_var_pick" => 1, + "log_level" => 100, + "max_iter" => 3, + "disc_ratio" => 10, + "presolve_bt_width_tol" => 1e-3, + "presolve_bt" => false, + ) m = blend029_gl(solver = test_solver) JuMP.optimize!(m) @@ -685,42 +761,49 @@ end end @testset "Convex Model Solve" begin - test_solver=optimizer_with_attributes(Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => PAVITO, - "max_iter" => 1, - "presolve_bt" => false, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => PAVITO, + "max_iter" => 1, + "presolve_bt" => false, + "log_level" => 100, + ) m = convex_solve(solver = test_solver) JuMP.optimize!(m) @test termination_status(m) == MOI.OPTIMAL end @testset "Uniform partitioning" begin - test_solver=optimizer_with_attributes(Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "disc_add_partition_method" => "uniform", - "disc_uniform_rate" => 10, - "max_iter" => 1, - "presolve_bt" => false, - "time_limit" => 100000, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "disc_add_partition_method" => "uniform", + "disc_uniform_rate" => 10, + "max_iter" => 1, + "presolve_bt" => false, + "time_limit" => 100000, + "log_level" => 100, + ) m = nlp3(solver = test_solver) JuMP.optimize!(m) - @test isapprox(objective_bound(m), 6561.7841; atol=1e-3) + @test isapprox(objective_bound(m), 6561.7841; atol = 1e-3) end @testset "Algorithm Test with binprod terms" begin - - test_solver = optimizer_with_attributes(Alpine.Optimizer, - "minlp_solver" => PAVITO, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "bilinear_convexhull" => true, - "monomial_convexhull" => true, - "presolve_bp" => true, - "presolve_bt" => false, - "disc_ratio" => 10, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "minlp_solver" => PAVITO, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "bilinear_convexhull" => true, + "monomial_convexhull" => true, + "presolve_bp" => true, + "presolve_bt" => false, + "disc_ratio" => 10, + "log_level" => 100, + ) m = binprod_nlp3(solver = test_solver) JuMP.optimize!(m) @@ -731,83 +814,104 @@ end alpine = JuMP.backend(m).optimizer.model @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4])]][:y_idx] == 19 @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4])]][:id] == 6 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4])]][:lifted_constr_ref] == :(x[19] == x[2] * x[4]) + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4])]][:lifted_constr_ref] == + :(x[19] == x[2] * x[4]) @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[8])]][:y_idx] == 25 @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[8])]][:id] == 12 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[8])]][:lifted_constr_ref] == :(x[25] == x[3] * x[8]) + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[8])]][:lifted_constr_ref] == + :(x[25] == x[3] * x[8]) @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[8])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5])]][:y_idx] == 22 @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5])]][:id] == 9 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5])]][:lifted_constr_ref] == :(x[22] == x[3] * x[5]) + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5])]][:lifted_constr_ref] == + :(x[22] == x[3] * x[5]) @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[19])]][:y_idx] == 20 @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[19])]][:id] == 7 - @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[19])]][:lifted_constr_ref] == :(x[20] == x[12] * x[19]) + @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[19])]][:lifted_constr_ref] == + :(x[20] == x[12] * x[19]) @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[19])]][:nonlinear_type] == :BINLIN @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[4])]][:y_idx] == 14 @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[4])]][:id] == 1 - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[4])]][:lifted_constr_ref] == :(x[14] == x[9] * x[4]) + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[4])]][:lifted_constr_ref] == + :(x[14] == x[9] * x[4]) @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[4])]][:nonlinear_type] == :BINLIN @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[6])]][:y_idx] == 17 @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[6])]][:id] == 4 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[6])]][:lifted_constr_ref] == :(x[17] == x[1] * x[6]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[6])]][:lifted_constr_ref] == + :(x[17] == x[1] * x[6]) @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[6])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[11]), :(x[5])]][:y_idx] == 16 @test alpine.nonconvex_terms[Expr[:(x[11]), :(x[5])]][:id] == 3 - @test alpine.nonconvex_terms[Expr[:(x[11]), :(x[5])]][:lifted_constr_ref] == :(x[16] == x[11] * x[5]) + @test alpine.nonconvex_terms[Expr[:(x[11]), :(x[5])]][:lifted_constr_ref] == + :(x[16] == x[11] * x[5]) @test alpine.nonconvex_terms[Expr[:(x[11]), :(x[5])]][:nonlinear_type] == :BINLIN @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[11])]][:y_idx] == 30 @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[11])]][:id] == 17 - @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[11])]][:lifted_constr_ref] == :(x[30] == x[10] * x[11]) + @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[11])]][:lifted_constr_ref] == + :(x[30] == x[10] * x[11]) @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[11])]][:nonlinear_type] == :BINPROD @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[11])]][:y_idx] == 29 @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[11])]][:id] == 16 - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[11])]][:lifted_constr_ref] == :(x[29] == x[9] * x[10] * x[11]) - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[11])]][:nonlinear_type] == :BINPROD + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[11])]][:lifted_constr_ref] == + :(x[29] == x[9] * x[10] * x[11]) + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[11])]][:nonlinear_type] == + :BINPROD @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[7])]][:y_idx] == 21 @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[7])]][:id] == 8 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[7])]][:lifted_constr_ref] == :(x[21] == x[2] * x[7]) + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[7])]][:lifted_constr_ref] == + :(x[21] == x[2] * x[7]) @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[7])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[13])]][:y_idx] == 32 @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[13])]][:id] == 19 - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[13])]][:lifted_constr_ref] == :(x[32] == x[9] * x[13]) + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[13])]][:lifted_constr_ref] == + :(x[32] == x[9] * x[13]) @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[13])]][:nonlinear_type] == :BINPROD @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[6])]][:y_idx] == 15 @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[6])]][:id] == 2 - @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[6])]][:lifted_constr_ref] == :(x[15] == x[10] * x[6]) + @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[6])]][:lifted_constr_ref] == + :(x[15] == x[10] * x[6]) @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[6])]][:nonlinear_type] == :BINLIN @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[12])]][:y_idx] == 33 @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[12])]][:id] == 20 - @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[12])]][:lifted_constr_ref] == :(x[33] == x[10] * x[12]) + @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[12])]][:lifted_constr_ref] == + :(x[33] == x[10] * x[12]) @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[12])]][:nonlinear_type] == :BINPROD @test alpine.nonconvex_terms[Expr[:(x[27]), :(x[5])]][:y_idx] == 28 @test alpine.nonconvex_terms[Expr[:(x[27]), :(x[5])]][:id] == 15 - @test alpine.nonconvex_terms[Expr[:(x[27]), :(x[5])]][:lifted_constr_ref] == :(x[28] == x[27] * x[5]) + @test alpine.nonconvex_terms[Expr[:(x[27]), :(x[5])]][:lifted_constr_ref] == + :(x[28] == x[27] * x[5]) @test alpine.nonconvex_terms[Expr[:(x[27]), :(x[5])]][:nonlinear_type] == :BINLIN @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[25])]][:y_idx] == 26 @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[25])]][:id] == 13 - @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[25])]][:lifted_constr_ref] == :(x[26] == x[13] * x[25]) + @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[25])]][:lifted_constr_ref] == + :(x[26] == x[13] * x[25]) @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[25])]][:nonlinear_type] == :BINLIN @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[12])]][:y_idx] == 27 @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[12])]][:id] == 14 - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[12])]][:lifted_constr_ref] == :(x[27] == x[9] * x[12]) + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[12])]][:lifted_constr_ref] == + :(x[27] == x[9] * x[12]) @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[12])]][:nonlinear_type] == :BINPROD @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[13])]][:y_idx] == 23 @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[13])]][:id] == 10 - @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[13])]][:lifted_constr_ref] == :(x[23] == x[10] * x[13]) + @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[13])]][:lifted_constr_ref] == + :(x[23] == x[10] * x[13]) @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[13])]][:nonlinear_type] == :BINPROD @test alpine.nonconvex_terms[Expr[:(x[23]), :(x[22])]][:y_idx] == 24 @test alpine.nonconvex_terms[Expr[:(x[23]), :(x[22])]][:id] == 11 - @test alpine.nonconvex_terms[Expr[:(x[23]), :(x[22])]][:lifted_constr_ref] == :(x[24] == x[23] * x[22]) + @test alpine.nonconvex_terms[Expr[:(x[23]), :(x[22])]][:lifted_constr_ref] == + :(x[24] == x[23] * x[22]) @test alpine.nonconvex_terms[Expr[:(x[23]), :(x[22])]][:nonlinear_type] == :BINLIN @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[13])]][:y_idx] == 31 @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[13])]][:id] == 18 - @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[13])]][:lifted_constr_ref] == :(x[31] == x[12] * x[13]) + @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[13])]][:lifted_constr_ref] == + :(x[31] == x[12] * x[13]) @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[13])]][:nonlinear_type] == :BINPROD @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[17])]][:y_idx] == 18 @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[17])]][:id] == 5 - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[17])]][:lifted_constr_ref] == :(x[18] == x[9] * x[17]) + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[17])]][:lifted_constr_ref] == + :(x[18] == x[9] * x[17]) @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[17])]][:nonlinear_type] == :BINLIN @test alpine.bounding_constr_mip[1][:rhs] == 1.0 @test alpine.bounding_constr_mip[1][:vars] == Any[:(x[14]), :(x[15])] @@ -829,7 +933,8 @@ end @test alpine.bounding_constr_mip[4][:sense] == :(<=) @test alpine.bounding_constr_mip[4][:cnt] == 3 @test alpine.bounding_constr_mip[5][:rhs] == 0.0 - @test alpine.bounding_constr_mip[5][:vars] == Any[:(x[20]), :(x[21]), :(x[4]), :(x[5])] + @test alpine.bounding_constr_mip[5][:vars] == + Any[:(x[20]), :(x[21]), :(x[4]), :(x[5])] @test alpine.bounding_constr_mip[5][:coefs] == Any[1.0, -1.0, -1250.0, 1250.0] @test alpine.bounding_constr_mip[5][:sense] == :(<=) @test alpine.bounding_constr_mip[5][:cnt] == 4 @@ -856,18 +961,20 @@ end end @testset "TESTS for closing the optimality gap in OBBT" begin - test_solver = JuMP.optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => PAVITO, - "presolve_bt" => true, - "presolve_bt_max_iter" => 2, - "log_level" => 1) + test_solver = JuMP.optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => PAVITO, + "presolve_bt" => true, + "presolve_bt_max_iter" => 2, + "log_level" => 1, + ) m = JuMP.Model(test_solver) # From issue #108 @variable(m, -2 <= x[1:2] <= 2) @variable(m, -10 <= y[1:3] <= 10) - @NLobjective(m, Min, y[2] + y[1]*y[2]*y[3]) + @NLobjective(m, Min, y[2] + y[1] * y[2] * y[3]) @constraint(m, y[1] == x[1]) @constraint(m, y[2] == x[2]) @NLconstraint(m, y[3] == x[2]^2) @@ -875,7 +982,7 @@ end JuMP.optimize!(m) alp = JuMP.backend(m).optimizer.model @test isapprox(JuMP.objective_value(m), -18, atol = 1E-6) - @test isapprox(value.(m[:x]), [2, -2], atol=1E-6) - @test alp.logs[:n_iter] == 0 + @test isapprox(value.(m[:x]), [2, -2], atol = 1E-6) + @test alp.logs[:n_iter] == 0 @test MOI.get(m, Alpine.NumberOfIterations()) == 0 -end \ No newline at end of file +end diff --git a/test/test_expression.jl b/test/test_expression.jl index 7cbe5ab3..35838f33 100644 --- a/test/test_expression.jl +++ b/test/test_expression.jl @@ -1,11 +1,12 @@ @testset "Expression Parsing || bilinear || Affine || exprs.jl" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "log_level" => 100, + ) - test_solver = optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "log_level" => 100) - - m=exprstest(solver = test_solver) + m = exprstest(solver = test_solver) alpine = _build(m) @@ -22,9 +23,9 @@ ex = alpine.bounding_constr_expr_mip[2] affdict = Alpine.expr_linear_to_affine(ex) - @test affdict[:coefs] == [3.0,3.0,3.0,3.0] + @test affdict[:coefs] == [3.0, 3.0, 3.0, 3.0] @test affdict[:coefs] == alpine.bounding_constr_mip[2][:coefs] - @test affdict[:vars] == [:(x[8]),:(x[9]),:(x[10]),:(x[11])] + @test affdict[:vars] == [:(x[8]), :(x[9]), :(x[10]), :(x[11])] @test affdict[:vars] == alpine.bounding_constr_mip[2][:vars] @test isapprox(affdict[:rhs], 111.0; atol = 1e-3) @test affdict[:rhs] == alpine.bounding_constr_mip[2][:rhs] @@ -33,9 +34,9 @@ ex = alpine.bounding_constr_expr_mip[3] affdict = Alpine.expr_linear_to_affine(ex) - @test affdict[:coefs] == [-1.0,20.0] + @test affdict[:coefs] == [-1.0, 20.0] @test affdict[:coefs] == alpine.bounding_constr_mip[3][:coefs] - @test affdict[:vars] == [:(x[12]),:(x[13])] + @test affdict[:vars] == [:(x[12]), :(x[13])] @test affdict[:vars] == alpine.bounding_constr_mip[3][:vars] @test isapprox(affdict[:rhs], 222.0; atol = 1e-3) @test affdict[:rhs] == alpine.bounding_constr_mip[3][:rhs] @@ -83,7 +84,7 @@ affdict = Alpine.expr_linear_to_affine(ex) @test affdict[:coefs] == [1.0, 1.0] @test affdict[:coefs] == alpine.bounding_constr_mip[7][:coefs] - @test affdict[:vars] == [:(x[1]),:(x[14])] + @test affdict[:vars] == [:(x[1]), :(x[14])] @test affdict[:vars] == alpine.bounding_constr_mip[7][:vars] @test isapprox(affdict[:rhs], 555.0; atol = 1e-3) @test affdict[:rhs] == alpine.bounding_constr_mip[7][:rhs] @@ -93,9 +94,9 @@ # ((x[8] - 7.0 * x[9]) + x[10] + x[4]) - 6666.0 <= 0.0 ex = alpine.bounding_constr_expr_mip[8] affdict = Alpine.expr_linear_to_affine(ex) - @test affdict[:coefs] == [1.0,-7.0,1.0,1.0] + @test affdict[:coefs] == [1.0, -7.0, 1.0, 1.0] @test affdict[:coefs] == alpine.bounding_constr_mip[8][:coefs] - @test affdict[:vars] == [:(x[8]),:(x[9]),:(x[10]),:(x[4])] + @test affdict[:vars] == [:(x[8]), :(x[9]), :(x[10]), :(x[4])] @test affdict[:vars] == alpine.bounding_constr_mip[8][:vars] @test isapprox(affdict[:rhs], 6666.0; atol = 1e-3) @test affdict[:rhs] == alpine.bounding_constr_mip[8][:rhs] @@ -105,9 +106,9 @@ # ((13.0 * x[1] - x[2]) + 30.0 * x[3] + x[4]) - 77.0 >= 0.0 ex = alpine.bounding_constr_expr_mip[9] affdict = Alpine.expr_linear_to_affine(ex) - @test affdict[:coefs] == [13.0,-1.0,30.0,1.0] + @test affdict[:coefs] == [13.0, -1.0, 30.0, 1.0] @test affdict[:coefs] == alpine.bounding_constr_mip[9][:coefs] - @test affdict[:vars] == [:(x[1]),:(x[2]),:(x[3]),:(x[4])] + @test affdict[:vars] == [:(x[1]), :(x[2]), :(x[3]), :(x[4])] @test affdict[:vars] == alpine.bounding_constr_mip[9][:vars] @test isapprox(affdict[:rhs], 77.0; atol = 1e-3) @test affdict[:rhs] == alpine.bounding_constr_mip[9][:rhs] @@ -116,11 +117,13 @@ end @testset "Expression Parsing || bilinear || Affine || nlp1.jl" begin - test_solver = optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "log_level" => 100) - m=nlp1(solver = test_solver) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "log_level" => 100, + ) + m = nlp1(solver = test_solver) alpine = _build(m) @@ -137,21 +140,22 @@ end end @testset "Expression Parsing || bilinear || Affine || nlp3.jl" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "log_level" => 100, + ) - test_solver = optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "log_level" => 100) - - m=nlp3(solver = test_solver) + m = nlp3(solver = test_solver) alpine = _build(m) ex = alpine.bounding_constr_expr_mip[1] affdict = Alpine.expr_linear_to_affine(ex) - @test affdict[:coefs] == [0.0025,0.0025] + @test affdict[:coefs] == [0.0025, 0.0025] @test affdict[:coefs] == alpine.bounding_constr_mip[1][:coefs] - @test affdict[:vars] == [:(x[4]),:(x[6])] + @test affdict[:vars] == [:(x[4]), :(x[6])] @test affdict[:vars] == alpine.bounding_constr_mip[1][:vars] @test isapprox(affdict[:rhs], 1.0; atol = 1e-3) @test affdict[:rhs] == alpine.bounding_constr_mip[1][:rhs] @@ -160,9 +164,9 @@ end ex = alpine.bounding_constr_expr_mip[2] affdict = Alpine.expr_linear_to_affine(ex) - @test affdict[:coefs] == [-0.0025,0.0025,0.0025] + @test affdict[:coefs] == [-0.0025, 0.0025, 0.0025] @test affdict[:coefs] == alpine.bounding_constr_mip[2][:coefs] - @test affdict[:vars] == [:(x[4]),:(x[5]),:(x[7])] + @test affdict[:vars] == [:(x[4]), :(x[5]), :(x[7])] @test affdict[:vars] == alpine.bounding_constr_mip[2][:vars] @test isapprox(affdict[:rhs], 1.0; atol = 1e-3) @test affdict[:rhs] == alpine.bounding_constr_mip[2][:rhs] @@ -173,7 +177,7 @@ end affdict = Alpine.expr_linear_to_affine(ex) @test affdict[:coefs] == [-0.01, 0.01] @test affdict[:coefs] == alpine.bounding_constr_mip[3][:coefs] - @test affdict[:vars] == [:(x[5]),:(x[8])] + @test affdict[:vars] == [:(x[5]), :(x[8])] @test affdict[:vars] == alpine.bounding_constr_mip[3][:vars] @test isapprox(affdict[:rhs], 1.0; atol = 1e-3) @test affdict[:rhs] == alpine.bounding_constr_mip[3][:rhs] @@ -184,7 +188,7 @@ end affdict = Alpine.expr_linear_to_affine(ex) @test (affdict[:coefs] .== [100.0, -1.0, 833.33252]) == [true, true, true] @test affdict[:coefs] == alpine.bounding_constr_mip[4][:coefs] - @test affdict[:vars] == [:(x[1]),:(x[9]),:(x[4])] + @test affdict[:vars] == [:(x[1]), :(x[9]), :(x[4])] @test affdict[:vars] == alpine.bounding_constr_mip[4][:vars] @test isapprox(affdict[:rhs], 83333.333; atol = 1e-3) @test affdict[:rhs] == alpine.bounding_constr_mip[4][:rhs] @@ -193,9 +197,9 @@ end ex = alpine.bounding_constr_expr_mip[5] affdict = Alpine.expr_linear_to_affine(ex) - @test affdict[:coefs] == [1.0,-1.0,-1250.0,1250.0] + @test affdict[:coefs] == [1.0, -1.0, -1250.0, 1250.0] @test affdict[:coefs] == alpine.bounding_constr_mip[5][:coefs] - @test affdict[:vars] == [:(x[10]),:(x[11]),:(x[4]),:(x[5])] + @test affdict[:vars] == [:(x[10]), :(x[11]), :(x[4]), :(x[5])] @test affdict[:vars] == alpine.bounding_constr_mip[5][:vars] @test isapprox(affdict[:rhs], 0.0; atol = 1e-3) @test affdict[:rhs] == alpine.bounding_constr_mip[5][:rhs] @@ -204,9 +208,9 @@ end ex = alpine.bounding_constr_expr_mip[6] affdict = Alpine.expr_linear_to_affine(ex) - @test affdict[:coefs] == [1.0,-1.0,-2500.0] + @test affdict[:coefs] == [1.0, -1.0, -2500.0] @test affdict[:coefs] == alpine.bounding_constr_mip[6][:coefs] - @test affdict[:vars] == [:(x[12]),:(x[13]),:(x[5])] + @test affdict[:vars] == [:(x[12]), :(x[13]), :(x[5])] @test affdict[:vars] == alpine.bounding_constr_mip[6][:vars] @test isapprox(affdict[:rhs], -1.25e6; atol = 1e-3) @test affdict[:rhs] == alpine.bounding_constr_mip[6][:rhs] @@ -215,11 +219,12 @@ end end @testset "Expression Parsing || bilinear || Simple || bi1.jl " begin - - test_solver = optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "log_level" => 100, + ) m = operator_c(solver = test_solver) @@ -236,12 +241,12 @@ end # TODO setup detailed check on this problem end @testset "Expression Parsing || bilinear || Complex || blend029.jl " begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "minlp_solver" => JUNIPER, - "mip_solver" => CBC, - "log_level" => 100) + Alpine.Optimizer, + "minlp_solver" => JUNIPER, + "mip_solver" => CBC, + "log_level" => 100, + ) m = blend029(solver = test_solver) @@ -257,19 +262,22 @@ end @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 47), Expr(:ref, :x, 36)]) @test alpine.bounding_constr_mip[1][:rhs] == 1.0 - @test alpine.bounding_constr_mip[1][:vars] == Any[:(x[1]), :(x[4]), :(x[7]), :(x[10]), :(x[49])] + @test alpine.bounding_constr_mip[1][:vars] == + Any[:(x[1]), :(x[4]), :(x[7]), :(x[10]), :(x[49])] @test alpine.bounding_constr_mip[1][:sense] == :(==) @test alpine.bounding_constr_mip[1][:coefs] == Any[1.0, 1.0, 1.0, 1.0, 1.0] @test alpine.bounding_constr_mip[1][:cnt] == 5 @test alpine.bounding_constr_mip[4][:rhs] == 0.1 - @test alpine.bounding_constr_mip[4][:vars] == Any[:(x[4]), :(x[16]), :(x[25]), :(x[34]), :(x[58])] + @test alpine.bounding_constr_mip[4][:vars] == + Any[:(x[4]), :(x[16]), :(x[25]), :(x[34]), :(x[58])] @test alpine.bounding_constr_mip[4][:sense] == :(==) @test alpine.bounding_constr_mip[4][:coefs] == Any[-1.0, -1.0, -1.0, 1.0, 1.0] @test alpine.bounding_constr_mip[4][:cnt] == 5 @test alpine.bounding_constr_mip[17][:rhs] == -0.14 - @test alpine.bounding_constr_mip[17][:vars] == Any[:(x[11]), :(x[23]), :(x[32]), :(x[64]), :(x[65])] + @test alpine.bounding_constr_mip[17][:vars] == + Any[:(x[11]), :(x[23]), :(x[32]), :(x[64]), :(x[65])] @test alpine.bounding_constr_mip[17][:sense] == :(==) @test alpine.bounding_constr_mip[17][:coefs] == Any[-1.0, -1.0, -1.0, -1.0, 1.0] @test alpine.bounding_constr_mip[17][:cnt] == 5 @@ -299,7 +307,8 @@ end @test alpine.bounding_constr_mip[187][:cnt] == 2 @test alpine.bounding_constr_mip[202][:rhs] == 0.04 - @test alpine.bounding_constr_mip[202][:vars] == Any[:(x[103]), :(x[1]), :(x[13]), :(x[25]), :(x[28]), :(x[31])] + @test alpine.bounding_constr_mip[202][:vars] == + Any[:(x[103]), :(x[1]), :(x[13]), :(x[25]), :(x[28]), :(x[31])] @test alpine.bounding_constr_mip[202][:sense] == :(==) @test alpine.bounding_constr_mip[202][:coefs] == Any[1.0, -0.6, -0.2, 0.2, 0.2, 0.2] @test alpine.bounding_constr_mip[202][:cnt] == 6 @@ -310,9 +319,11 @@ end @test alpine.nonconvex_terms[[:(x[37]), :(x[55])]][:nonlinear_type] == :BILINEAR @test alpine.bounding_constr_mip[206][:rhs] == 0.0 - @test alpine.bounding_constr_mip[206][:vars] == Any[:(x[107]), :(x[103]), :(x[108]), :(x[109]), :(x[110]), :(x[2]), :(x[14])] + @test alpine.bounding_constr_mip[206][:vars] == + Any[:(x[107]), :(x[103]), :(x[108]), :(x[109]), :(x[110]), :(x[2]), :(x[14])] @test alpine.bounding_constr_mip[206][:sense] == :(==) - @test alpine.bounding_constr_mip[206][:coefs] == Any[1.0, -1.0, 1.0, 1.0, 1.0, -0.6, -0.2] + @test alpine.bounding_constr_mip[206][:coefs] == + Any[1.0, -1.0, 1.0, 1.0, 1.0, -0.6, -0.2] @test alpine.bounding_constr_mip[206][:cnt] == 7 @test alpine.nonconvex_terms[[:(x[38]), :(x[56])]][:id] == 5 @@ -331,7 +342,8 @@ end @test alpine.nonconvex_terms[[:(x[37]), :(x[32])]][:nonlinear_type] == :BILINEAR @test alpine.bounding_constr_mip[213][:rhs] == 0.0 - @test alpine.bounding_constr_mip[213][:vars] == Any[:(x[129]), :(x[127]), :(x[124]), :(x[130]), :(x[6]), :(x[18])] + @test alpine.bounding_constr_mip[213][:vars] == + Any[:(x[129]), :(x[127]), :(x[124]), :(x[130]), :(x[6]), :(x[18])] @test alpine.bounding_constr_mip[213][:sense] == :(==) @test alpine.bounding_constr_mip[213][:coefs] == Any[1.0, -1.0, -1.0, 1.0, -0.4, -0.4] @test alpine.bounding_constr_mip[213][:cnt] == 6 @@ -353,20 +365,22 @@ end end @testset "Expression Parsing || multilinear || Simple || multi.jl " begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "log_level" => 100, + ) - test_solver = optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "log_level" => 100) - - m = multi3(solver = test_solver, exprmode=1) + m = multi3(solver = test_solver, exprmode = 1) alpine = _build(m) # Setup internal model @test length(keys(alpine.nonconvex_terms)) == 1 @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3])]][:id] == 1 @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3])]][:lifted_var_ref] == :(x[4]) - @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3])]][:nonlinear_type] == + :MULTILINEAR @test alpine.bounding_obj_mip[:rhs] == 0 @test alpine.bounding_obj_mip[:vars] == Expr[:(x[4])] @@ -380,17 +394,21 @@ end @test alpine.bounding_constr_mip[1][:coefs] == Any[1.0, 1.0, 1.0] @test alpine.bounding_constr_mip[1][:cnt] == 3 - m = multi3(solver = test_solver, exprmode=2) + m = multi3(solver = test_solver, exprmode = 2) alpine = _build(m) @test length(keys(alpine.nonconvex_terms)) == 2 @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:id] == 1 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:lifted_var_ref] == :(x[4]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:lifted_var_ref] == + :(x[4]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[[Expr(:ref, :x, 4), Expr(:ref, :x, 3)]][:id] == 2 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 4), Expr(:ref, :x, 3)]][:lifted_var_ref] == :(x[5]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 4), Expr(:ref, :x, 3)]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[[Expr(:ref, :x, 4), Expr(:ref, :x, 3)]][:lifted_var_ref] == + :(x[5]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 4), Expr(:ref, :x, 3)]][:nonlinear_type] == + :BILINEAR @test alpine.bounding_obj_mip[:rhs] == 0 @test alpine.bounding_obj_mip[:vars] == Expr[:(x[5])] @@ -398,17 +416,21 @@ end @test alpine.bounding_obj_mip[:cnt] == 1 @test alpine.bounding_obj_mip[:sense] === nothing - m = multi3(solver = test_solver, exprmode=3) + m = multi3(solver = test_solver, exprmode = 3) alpine = _build(m) @test length(keys(alpine.nonconvex_terms)) == 2 @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:id] == 1 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:lifted_var_ref] == :(x[4]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:lifted_var_ref] == + :(x[4]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 4)]][:id] == 2 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 4)]][:lifted_var_ref] == :(x[5]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 4)]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 4)]][:lifted_var_ref] == + :(x[5]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 4)]][:nonlinear_type] == + :BILINEAR @test alpine.bounding_obj_mip[:rhs] == 0 @test alpine.bounding_obj_mip[:vars] == Expr[:(x[5])] @@ -416,7 +438,7 @@ end @test alpine.bounding_obj_mip[:cnt] == 1 @test alpine.bounding_obj_mip[:sense] === nothing - m = multi4(solver = test_solver, exprmode=1) + m = multi4(solver = test_solver, exprmode = 1) alpine = _build(m) @@ -429,8 +451,10 @@ end @test alpine.bounding_obj_mip[:sense] === nothing @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:id] == 1 - @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:lifted_var_ref] == :(x[5]) - @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:lifted_var_ref] == + :(x[5]) + @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:nonlinear_type] == + :MULTILINEAR @test alpine.bounding_constr_mip[1][:rhs] == 4.0 @test alpine.bounding_constr_mip[1][:vars] == Any[:(x[1]), :(x[2]), :(x[3]), :(x[4])] @@ -438,22 +462,27 @@ end @test alpine.bounding_constr_mip[1][:coefs] == Any[1.0, 1.0, 1.0, 1.0] @test alpine.bounding_constr_mip[1][:cnt] == 4 - m = multi4(solver = test_solver, exprmode=2) + m = multi4(solver = test_solver, exprmode = 2) alpine = _build(m) @test length(keys(alpine.nonconvex_terms)) == 3 @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:id] == 1 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:lifted_var_ref] == :(x[5]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:lifted_var_ref] == + :(x[5]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:id] == 2 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:lifted_var_ref] == :(x[6]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:lifted_var_ref] == + :(x[6]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[[Expr(:ref, :x, 5), Expr(:ref, :x, 6)]][:id] == 3 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 5), Expr(:ref, :x, 6)]][:lifted_var_ref] == :(x[7]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 5), Expr(:ref, :x, 6)]][:nonlinear_type] == :BILINEAR - + @test alpine.nonconvex_terms[[Expr(:ref, :x, 5), Expr(:ref, :x, 6)]][:lifted_var_ref] == + :(x[7]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 5), Expr(:ref, :x, 6)]][:nonlinear_type] == + :BILINEAR @test alpine.bounding_obj_mip[:rhs] == 0 @test alpine.bounding_obj_mip[:vars] == Expr[:(x[7])] @@ -461,20 +490,21 @@ end @test alpine.bounding_obj_mip[:cnt] == 1 @test alpine.bounding_obj_mip[:sense] === nothing - - m = multi4(solver = test_solver, exprmode=3) + m = multi4(solver = test_solver, exprmode = 3) alpine = _build(m) @test length(keys(alpine.nonconvex_terms)) == 2 @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:id] == 1 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:lifted_var_ref] == :(x[5]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:lifted_var_ref] == + :(x[5]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[[:(x[5]), :(x[3]), :(x[4])]][:id] == 2 @test alpine.nonconvex_terms[[:(x[5]), :(x[3]), :(x[4])]][:lifted_var_ref] == :(x[6]) - @test alpine.nonconvex_terms[[:(x[5]), :(x[3]), :(x[4])]][:nonlinear_type] == :MULTILINEAR - + @test alpine.nonconvex_terms[[:(x[5]), :(x[3]), :(x[4])]][:nonlinear_type] == + :MULTILINEAR @test alpine.bounding_obj_mip[:rhs] == 0 @test alpine.bounding_obj_mip[:vars] == Expr[:(x[6])] @@ -482,18 +512,21 @@ end @test alpine.bounding_obj_mip[:cnt] == 1 @test alpine.bounding_obj_mip[:sense] === nothing - m = multi4(solver = test_solver, exprmode=4) + m = multi4(solver = test_solver, exprmode = 4) alpine = _build(m) @test length(keys(alpine.nonconvex_terms)) == 2 @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:id] == 1 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:lifted_var_ref] == :(x[5]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:lifted_var_ref] == + :(x[5]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[5])]][:id] == 2 @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[5])]][:lifted_var_ref] == :(x[6]) - @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[5])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[5])]][:nonlinear_type] == + :MULTILINEAR @test alpine.bounding_obj_mip[:rhs] == 0 @test alpine.bounding_obj_mip[:vars] == Expr[:(x[6])] @@ -507,21 +540,27 @@ end @test alpine.bounding_obj_mip[:cnt] == 1 @test alpine.bounding_obj_mip[:sense] === nothing - m = multi4(solver = test_solver, exprmode=5) + m = multi4(solver = test_solver, exprmode = 5) alpine = _build(m) @test length(keys(alpine.nonconvex_terms)) == 3 @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:id] == 1 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:lifted_var_ref] == :(x[5]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:lifted_var_ref] == + :(x[5]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 5)]][:id] == 2 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 5)]][:lifted_var_ref] == :(x[6]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 5)]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 5)]][:lifted_var_ref] == + :(x[6]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 5)]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[[Expr(:ref, :x, 6), Expr(:ref, :x, 4)]][:id] == 3 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 6), Expr(:ref, :x, 4)]][:lifted_var_ref] == :(x[7]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 6), Expr(:ref, :x, 4)]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[[Expr(:ref, :x, 6), Expr(:ref, :x, 4)]][:lifted_var_ref] == + :(x[7]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 6), Expr(:ref, :x, 4)]][:nonlinear_type] == + :BILINEAR @test alpine.bounding_obj_mip[:rhs] == 0 @test alpine.bounding_obj_mip[:vars] == Expr[:(x[7])] @@ -535,7 +574,7 @@ end @test alpine.bounding_obj_mip[:cnt] == 1 @test alpine.bounding_obj_mip[:sense] === nothing - m = multi4(solver = test_solver, exprmode=6) + m = multi4(solver = test_solver, exprmode = 6) alpine = _build(m) @@ -543,10 +582,13 @@ end @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3])]][:id] == 1 @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3])]][:lifted_var_ref] == :(x[5]) - @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[[Expr(:ref, :x, 5), Expr(:ref, :x, 4)]][:id] == 2 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 5), Expr(:ref, :x, 4)]][:lifted_var_ref] == :(x[6]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 5), Expr(:ref, :x, 4)]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[[Expr(:ref, :x, 5), Expr(:ref, :x, 4)]][:lifted_var_ref] == + :(x[6]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 5), Expr(:ref, :x, 4)]][:nonlinear_type] == + :BILINEAR @test alpine.bounding_obj_mip[:rhs] == 0 @test alpine.bounding_obj_mip[:vars] == Expr[:(x[6])] @@ -554,22 +596,27 @@ end @test alpine.bounding_obj_mip[:cnt] == 1 @test alpine.bounding_obj_mip[:sense] === nothing - m = multi4(solver = test_solver, exprmode=7) + m = multi4(solver = test_solver, exprmode = 7) alpine = _build(m) @test length(keys(alpine.nonconvex_terms)) == 3 @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:id] == 1 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:lifted_var_ref] == :(x[5]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:lifted_var_ref] == + :(x[5]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 5)]][:id] == 2 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 5)]][:lifted_var_ref] == :(x[6]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 5)]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 5)]][:lifted_var_ref] == + :(x[6]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 5)]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 6)]][:id] == 3 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 6)]][:lifted_var_ref] == :(x[7]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 6)]][:nonlinear_type] == :BILINEAR - + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 6)]][:lifted_var_ref] == + :(x[7]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 6)]][:nonlinear_type] == + :BILINEAR @test alpine.bounding_obj_mip[:rhs] == 0 @test alpine.bounding_obj_mip[:vars] == Expr[:(x[7])] @@ -577,20 +624,21 @@ end @test alpine.bounding_obj_mip[:cnt] == 1 @test alpine.bounding_obj_mip[:sense] === nothing - - m = multi4(solver = test_solver, exprmode=8) + m = multi4(solver = test_solver, exprmode = 8) alpine = _build(m) @test length(keys(alpine.nonconvex_terms)) == 2 @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:id] == 1 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:lifted_var_ref] == :(x[5]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:lifted_var_ref] == + :(x[5]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[[:(x[1]), :(x[5]), :(x[4])]][:id] == 2 @test alpine.nonconvex_terms[[:(x[1]), :(x[5]), :(x[4])]][:lifted_var_ref] == :(x[6]) - @test alpine.nonconvex_terms[[:(x[1]), :(x[5]), :(x[4])]][:nonlinear_type] == :MULTILINEAR - + @test alpine.nonconvex_terms[[:(x[1]), :(x[5]), :(x[4])]][:nonlinear_type] == + :MULTILINEAR @test alpine.bounding_obj_mip[:rhs] == 0 @test alpine.bounding_obj_mip[:vars] == Expr[:(x[6])] @@ -598,8 +646,7 @@ end @test alpine.bounding_obj_mip[:cnt] == 1 @test alpine.bounding_obj_mip[:sense] === nothing - - m = multi4(solver = test_solver, exprmode=9) + m = multi4(solver = test_solver, exprmode = 9) alpine = _build(m) @@ -607,10 +654,13 @@ end @test alpine.nonconvex_terms[[:(x[2]), :(x[3]), :(x[4])]][:id] == 1 @test alpine.nonconvex_terms[[:(x[2]), :(x[3]), :(x[4])]][:lifted_var_ref] == :(x[5]) - @test alpine.nonconvex_terms[[:(x[2]), :(x[3]), :(x[4])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[[:(x[2]), :(x[3]), :(x[4])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 5)]][:id] == 2 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 5)]][:lifted_var_ref] == :(x[6]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 5)]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 5)]][:lifted_var_ref] == + :(x[6]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 5)]][:nonlinear_type] == + :BILINEAR @test alpine.bounding_obj_mip[:rhs] == 0 @test alpine.bounding_obj_mip[:vars] == Expr[:(x[6])] @@ -618,21 +668,26 @@ end @test alpine.bounding_obj_mip[:cnt] == 1 @test alpine.bounding_obj_mip[:sense] === nothing - m = multi4(solver = test_solver, exprmode=10) + m = multi4(solver = test_solver, exprmode = 10) alpine = _build(m) @test length(keys(alpine.nonconvex_terms)) == 3 @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:id] == 1 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:lifted_var_ref] == :(x[5]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:lifted_var_ref] == + :(x[5]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[[Expr(:ref, :x, 4), Expr(:ref, :x, 5)]][:id] == 2 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 4), Expr(:ref, :x, 5)]][:lifted_var_ref] == :(x[6]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 4), Expr(:ref, :x, 5)]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[[Expr(:ref, :x, 4), Expr(:ref, :x, 5)]][:lifted_var_ref] == + :(x[6]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 4), Expr(:ref, :x, 5)]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 6)]][:id] == 3 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 6)]][:lifted_var_ref] == :(x[7]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 6)]][:nonlinear_type] == :BILINEAR - + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 6)]][:lifted_var_ref] == + :(x[7]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 6)]][:nonlinear_type] == + :BILINEAR @test alpine.bounding_obj_mip[:rhs] == 0 @test alpine.bounding_obj_mip[:vars] == Expr[:(x[7])] @@ -640,22 +695,27 @@ end @test alpine.bounding_obj_mip[:cnt] == 1 @test alpine.bounding_obj_mip[:sense] === nothing - m = multi4(solver = test_solver, exprmode=11) + m = multi4(solver = test_solver, exprmode = 11) alpine = _build(m) @test length(keys(alpine.nonconvex_terms)) == 3 @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:id] == 1 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:lifted_var_ref] == :(x[5]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:lifted_var_ref] == + :(x[5]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 5)]][:id] == 2 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 5)]][:lifted_var_ref] == :(x[6]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 5)]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 5)]][:lifted_var_ref] == + :(x[6]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 5)]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[[Expr(:ref, :x, 6), Expr(:ref, :x, 4)]][:id] == 3 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 6), Expr(:ref, :x, 4)]][:lifted_var_ref] == :(x[7]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 6), Expr(:ref, :x, 4)]][:nonlinear_type] == :BILINEAR - + @test alpine.nonconvex_terms[[Expr(:ref, :x, 6), Expr(:ref, :x, 4)]][:lifted_var_ref] == + :(x[7]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 6), Expr(:ref, :x, 4)]][:nonlinear_type] == + :BILINEAR @test alpine.bounding_obj_mip[:rhs] == 0 @test alpine.bounding_obj_mip[:vars] == Expr[:(x[7])] @@ -665,10 +725,12 @@ end end @testset "Expression Parsing || bilinear || Complex-div || div.jl" begin - test_solver = optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "log_level" => 100, + ) m = div(solver = test_solver) @@ -676,23 +738,29 @@ end @test length(keys(alpine.nonconvex_terms)) == 3 @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 1)]][:id] == 1 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 1)]][:lifted_var_ref] == :(x[3]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 1)]][:nonlinear_type] == :MONOMIAL + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 1)]][:lifted_var_ref] == + :(x[3]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 1)]][:nonlinear_type] == + :MONOMIAL @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 2)]][:id] == 2 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 2)]][:lifted_var_ref] == :(x[4]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 2)]][:nonlinear_type] == :MONOMIAL + @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 2)]][:lifted_var_ref] == + :(x[4]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 2)]][:nonlinear_type] == + :MONOMIAL @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:id] == 3 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:lifted_var_ref] == :(x[5]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:lifted_var_ref] == + :(x[5]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:nonlinear_type] == + :BILINEAR aff_mip = alpine.bounding_constr_mip @test aff_mip[1][:rhs] == 0.0 @test aff_mip[1][:vars] == Any[:(x[1])] @test aff_mip[1][:sense] == :(>=) - @test round(aff_mip[1][:coefs][1]; digits=1) == -3.0 + @test round(aff_mip[1][:coefs][1]; digits = 1) == -3.0 @test aff_mip[1][:cnt] == 1 @test aff_mip[2][:rhs] == 0.0 @@ -732,49 +800,53 @@ end @test aff_mip[7][:cnt] == 1 @test aff_mip[8][:rhs] == 0.0 - @test aff_mip[8][:vars] == Any[:(x[2]),:(x[5])] + @test aff_mip[8][:vars] == Any[:(x[2]), :(x[5])] @test aff_mip[8][:sense] == :(>=) - @test aff_mip[8][:coefs] == Any[5.6,-72000.0] + @test aff_mip[8][:coefs] == Any[5.6, -72000.0] @test aff_mip[8][:cnt] == 2 @test aff_mip[9][:rhs] == 0.0 - @test aff_mip[9][:vars] == Any[:(x[2]),:(x[5])] + @test aff_mip[9][:vars] == Any[:(x[2]), :(x[5])] @test aff_mip[9][:sense] == :(>=) - @test aff_mip[9][:coefs] == Any[5.6,-36000.0] + @test aff_mip[9][:coefs] == Any[5.6, -36000.0] @test aff_mip[9][:cnt] == 2 @test aff_mip[10][:rhs] == 0.0 - @test aff_mip[10][:vars] == Any[:(x[2]),:(x[5]),:(x[2])] + @test aff_mip[10][:vars] == Any[:(x[2]), :(x[5]), :(x[2])] @test aff_mip[10][:sense] == :(>=) @test aff_mip[10][:coefs] == Any[5.6, -300.0, -1.75] @test aff_mip[10][:cnt] == 3 @test aff_mip[11][:rhs] == 0.0 - @test aff_mip[11][:vars] == Any[:(x[2]),:(x[1]),:(x[5])] + @test aff_mip[11][:vars] == Any[:(x[2]), :(x[1]), :(x[5])] @test aff_mip[11][:sense] == :(>=) @test aff_mip[11][:coefs] == Any[5.6, -0.5, 0.5] @test aff_mip[11][:cnt] == 3 end @testset "Expression Parsing || part1 " begin - m = Model(optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "log_level" => 100)) - @variable(m, x[1:4]>=0) - @NLconstraint(m, x[1]^2 >= 1) # Basic monomial x[5]=x[1]^2 - @NLconstraint(m, x[1]*x[2] <= 1) # x[6] <= 1 : x[6] = x[1]*x[2] + m = Model( + optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "log_level" => 100, + ), + ) + @variable(m, x[1:4] >= 0) + @NLconstraint(m, x[1]^2 >= 1) # Basic monomial x[5]=x[1]^2 + @NLconstraint(m, x[1] * x[2] <= 1) # x[6] <= 1 : x[6] = x[1]*x[2] @NLconstraint(m, x[1]^2 * x[2]^2 <= 1) # x[5] + x[7] <= 1 : x[7] = x[2]^2 - @NLconstraint(m, x[1]*(x[2]*x[3]) >= 1) # x[9] >= 1 : x[8] = x[2] * x[3] && x[9] = x[1]*x[8] - @NLconstraint(m, x[1]^2*(x[2]^2 * x[3]^2) <= 1) # x[12] <= 1 : x[10] = x[3] ^ 2 && x[11] = x[7] * x[10] && x[12] = x[11]*[5] + @NLconstraint(m, x[1] * (x[2] * x[3]) >= 1) # x[9] >= 1 : x[8] = x[2] * x[3] && x[9] = x[1]*x[8] + @NLconstraint(m, x[1]^2 * (x[2]^2 * x[3]^2) <= 1) # x[12] <= 1 : x[10] = x[3] ^ 2 && x[11] = x[7] * x[10] && x[12] = x[11]*[5] alpine = _build(m) - @test alpine.bounding_constr_expr_mip[1] == :(x[5]-1.0>=0.0) - @test alpine.bounding_constr_expr_mip[2] == :(x[6]-1.0<=0.0) - @test alpine.bounding_constr_expr_mip[3] == :(x[8]-1.0<=0.0) - @test alpine.bounding_constr_expr_mip[4] == :(x[10]-1.0>=0.0) - @test alpine.bounding_constr_expr_mip[5] == :(x[13]-1.0<=0.0) + @test alpine.bounding_constr_expr_mip[1] == :(x[5] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[2] == :(x[6] - 1.0 <= 0.0) + @test alpine.bounding_constr_expr_mip[3] == :(x[8] - 1.0 <= 0.0) + @test alpine.bounding_constr_expr_mip[4] == :(x[10] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[5] == :(x[13] - 1.0 <= 0.0) @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[1])]) @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2])]) @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[2])]) @@ -797,13 +869,17 @@ end end @testset "Expression Parsing || part2" begin - m = Model(optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "log_level" => 100)) - - @variable(m, x[1:4]>=0) - @NLconstraint(m, (x[1]*x[2]) * x[3] >= 1) + m = Model( + optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "log_level" => 100, + ), + ) + + @variable(m, x[1:4] >= 0) + @NLconstraint(m, (x[1] * x[2]) * x[3] >= 1) @NLconstraint(m, (x[1]^2 * x[2]^2) * x[3]^2 <= 1) @NLconstraint(m, x[1] * (x[2]^2 * x[3]^2) >= 1) @@ -813,12 +889,12 @@ end alpine = _build(m) - @test alpine.bounding_constr_expr_mip[1] == :(x[6]-1.0>=0.0) - @test alpine.bounding_constr_expr_mip[2] == :(x[11]-1.0<=0.0) - @test alpine.bounding_constr_expr_mip[3] == :(x[13]-1.0>=0.0) - @test alpine.bounding_constr_expr_mip[4] == :(x[15]-1.0<=0.0) - @test alpine.bounding_constr_expr_mip[5] == :(x[17]-1.0>=0.0) - @test alpine.bounding_constr_expr_mip[6] == :(x[19]-1.0<=0.0) + @test alpine.bounding_constr_expr_mip[1] == :(x[6] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[2] == :(x[11] - 1.0 <= 0.0) + @test alpine.bounding_constr_expr_mip[3] == :(x[13] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[4] == :(x[15] - 1.0 <= 0.0) + @test alpine.bounding_constr_expr_mip[5] == :(x[17] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[6] == :(x[19] - 1.0 <= 0.0) @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2])]) #5 @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[5])]) #6 @@ -854,27 +930,31 @@ end end @testset "Expression Parsing || part3" begin - m = Model(optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "log_level" => 100)) - - @variable(m, x[1:4]>=0) - @NLconstraint(m, ((x[1]*x[2])*x[3])*x[4] >= 1) - @NLconstraint(m, ((x[1]^2*x[2])*x[3])*x[4] <= 1) - @NLconstraint(m, ((x[1]*x[2]^2)*x[3])*x[4] >= 1) - @NLconstraint(m, ((x[1]*x[2])*x[3]^2)*x[4] <= 1) - @NLconstraint(m, ((x[1]*x[2])*x[3])*x[4]^2 >= 1) - @NLconstraint(m, ((x[1]^2*x[2]^2)*x[3]^2)*x[4]^2 <= 1) + m = Model( + optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "log_level" => 100, + ), + ) + + @variable(m, x[1:4] >= 0) + @NLconstraint(m, ((x[1] * x[2]) * x[3]) * x[4] >= 1) + @NLconstraint(m, ((x[1]^2 * x[2]) * x[3]) * x[4] <= 1) + @NLconstraint(m, ((x[1] * x[2]^2) * x[3]) * x[4] >= 1) + @NLconstraint(m, ((x[1] * x[2]) * x[3]^2) * x[4] <= 1) + @NLconstraint(m, ((x[1] * x[2]) * x[3]) * x[4]^2 >= 1) + @NLconstraint(m, ((x[1]^2 * x[2]^2) * x[3]^2) * x[4]^2 <= 1) alpine = _build(m) - @test alpine.bounding_constr_expr_mip[1] == :(x[7]-1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[2] == :(x[11]-1.0 <= 0.0) - @test alpine.bounding_constr_expr_mip[3] == :(x[15]-1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[4] == :(x[18]-1.0 <= 0.0) - @test alpine.bounding_constr_expr_mip[5] == :(x[20]-1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[6] == :(x[23]-1.0 <= 0.0) + @test alpine.bounding_constr_expr_mip[1] == :(x[7] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[2] == :(x[11] - 1.0 <= 0.0) + @test alpine.bounding_constr_expr_mip[3] == :(x[15] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[4] == :(x[18] - 1.0 <= 0.0) + @test alpine.bounding_constr_expr_mip[5] == :(x[20] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[6] == :(x[23] - 1.0 <= 0.0) @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2])]) #5 @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[5])]) #6 @@ -918,114 +998,122 @@ end end @testset "Expression Parsing || part7" begin - m = Model(optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "log_level" => 100)) - @variable(m, x[1:4]>=0) - - @NLconstraint(m, x[1]*x[2]*x[3]*x[4] >= 1) - @NLconstraint(m, x[1]^2*x[2]*x[3]*x[4] >= 1) - @NLconstraint(m, x[1]*x[2]^2*x[3]*x[4] >= 1) - @NLconstraint(m, x[1]*x[2]*x[3]^2*x[4]^2 >= 1) - @NLconstraint(m, x[1]*x[2]^2*x[3]^2*x[4] >= 1) - @NLconstraint(m, x[1]^2*x[2]*x[3]*x[4]^2 >= 1) - @NLconstraint(m, x[1]^2*x[2]^2*x[3]^2*x[4]^2 >= 1) + m = Model( + optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "log_level" => 100, + ), + ) + @variable(m, x[1:4] >= 0) + + @NLconstraint(m, x[1] * x[2] * x[3] * x[4] >= 1) + @NLconstraint(m, x[1]^2 * x[2] * x[3] * x[4] >= 1) + @NLconstraint(m, x[1] * x[2]^2 * x[3] * x[4] >= 1) + @NLconstraint(m, x[1] * x[2] * x[3]^2 * x[4]^2 >= 1) + @NLconstraint(m, x[1] * x[2]^2 * x[3]^2 * x[4] >= 1) + @NLconstraint(m, x[1]^2 * x[2] * x[3] * x[4]^2 >= 1) + @NLconstraint(m, x[1]^2 * x[2]^2 * x[3]^2 * x[4]^2 >= 1) alpine = _build(m) - @test alpine.bounding_constr_expr_mip[1] == :(x[5]-1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[2] == :(x[7]-1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[3] == :(x[9]-1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[4] == :(x[12]-1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[5] == :(x[13]-1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[6] == :(x[14]-1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[7] == :(x[15]-1.0 >= 0.0) - - @test haskey(alpine.nonconvex_terms, [:(x[1]),:(x[2]),:(x[3]),:(x[4])]) #5 - @test haskey(alpine.nonconvex_terms, [:(x[1]),:(x[1])]) #6 - @test haskey(alpine.nonconvex_terms, [:(x[2]),:(x[3]),:(x[4]),:(x[6])]) #7 - @test haskey(alpine.nonconvex_terms, [:(x[2]),:(x[2])]) #8 - @test haskey(alpine.nonconvex_terms, [:(x[1]),:(x[3]),:(x[4]),:(x[8])]) #9 - @test haskey(alpine.nonconvex_terms, [:(x[3]),:(x[3])]) #10 - @test haskey(alpine.nonconvex_terms, [:(x[4]),:(x[4])]) #11 - @test haskey(alpine.nonconvex_terms, [:(x[1]),:(x[2]),:(x[10]),:(x[11])]) #12 - @test haskey(alpine.nonconvex_terms, [:(x[1]),:(x[4]),:(x[8]),:(x[10])]) #13 - @test haskey(alpine.nonconvex_terms, [:(x[2]),:(x[3]),:(x[6]),:(x[11])]) #14 - @test haskey(alpine.nonconvex_terms, [:(x[6]),:(x[8]),:(x[10]),:(x[11])]) #15 - - @test alpine.nonconvex_terms[[:(x[1]),:(x[2]),:(x[3]),:(x[4])]][:id] == 1 #5 - @test alpine.nonconvex_terms[[:(x[1]),:(x[1])]][:id] == 2 #6 - @test alpine.nonconvex_terms[[:(x[2]),:(x[3]),:(x[4]),:(x[6])]][:id] == 3 #7 - @test alpine.nonconvex_terms[[:(x[2]),:(x[2])]][:id] == 4 #8 - @test alpine.nonconvex_terms[[:(x[1]),:(x[3]),:(x[4]),:(x[8])]][:id] == 5 #9 - @test alpine.nonconvex_terms[[:(x[3]),:(x[3])]][:id] == 6 #10 - @test alpine.nonconvex_terms[[:(x[4]),:(x[4])]][:id] == 7 #11 - @test alpine.nonconvex_terms[[:(x[1]),:(x[2]),:(x[10]),:(x[11])]][:id] == 8 #12 - @test alpine.nonconvex_terms[[:(x[1]),:(x[4]),:(x[8]),:(x[10])]][:id] == 9 #13 - @test alpine.nonconvex_terms[[:(x[2]),:(x[3]),:(x[6]),:(x[11])]][:id] == 10 #14 - @test alpine.nonconvex_terms[[:(x[6]),:(x[8]),:(x[10]),:(x[11])]][:id] == 11 #15 + @test alpine.bounding_constr_expr_mip[1] == :(x[5] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[2] == :(x[7] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[3] == :(x[9] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[4] == :(x[12] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[5] == :(x[13] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[6] == :(x[14] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[7] == :(x[15] - 1.0 >= 0.0) + + @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2]), :(x[3]), :(x[4])]) #5 + @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[1])]) #6 + @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[3]), :(x[4]), :(x[6])]) #7 + @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[2])]) #8 + @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[3]), :(x[4]), :(x[8])]) #9 + @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[3])]) #10 + @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[4])]) #11 + @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2]), :(x[10]), :(x[11])]) #12 + @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[4]), :(x[8]), :(x[10])]) #13 + @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[3]), :(x[6]), :(x[11])]) #14 + @test haskey(alpine.nonconvex_terms, [:(x[6]), :(x[8]), :(x[10]), :(x[11])]) #15 + + @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:id] == 1 #5 + @test alpine.nonconvex_terms[[:(x[1]), :(x[1])]][:id] == 2 #6 + @test alpine.nonconvex_terms[[:(x[2]), :(x[3]), :(x[4]), :(x[6])]][:id] == 3 #7 + @test alpine.nonconvex_terms[[:(x[2]), :(x[2])]][:id] == 4 #8 + @test alpine.nonconvex_terms[[:(x[1]), :(x[3]), :(x[4]), :(x[8])]][:id] == 5 #9 + @test alpine.nonconvex_terms[[:(x[3]), :(x[3])]][:id] == 6 #10 + @test alpine.nonconvex_terms[[:(x[4]), :(x[4])]][:id] == 7 #11 + @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[10]), :(x[11])]][:id] == 8 #12 + @test alpine.nonconvex_terms[[:(x[1]), :(x[4]), :(x[8]), :(x[10])]][:id] == 9 #13 + @test alpine.nonconvex_terms[[:(x[2]), :(x[3]), :(x[6]), :(x[11])]][:id] == 10 #14 + @test alpine.nonconvex_terms[[:(x[6]), :(x[8]), :(x[10]), :(x[11])]][:id] == 11 #15 end @testset "Expression Parsing || part8" begin - m = Model(optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "log_level" => 100)) - @variable(m, x[1:4]>=0) - - @NLconstraint(m, (x[1]*x[2]*x[3])*x[4] >= 1) - @NLconstraint(m, (x[1]^2*x[2]*x[3])*x[4] >= 1) - @NLconstraint(m, x[1]*(x[2]^2*x[3])*x[4] >= 1) - @NLconstraint(m, x[1]*(x[2]*x[3]^2)*x[4] >= 1) - @NLconstraint(m, (x[1]*x[2]^2)*x[3]*x[4] >= 1) - @NLconstraint(m, (x[1]*x[2])*x[3]^2*x[4] >= 1) - @NLconstraint(m, (x[1]*x[2])*x[3]*x[4]^2 >= 1) - @NLconstraint(m, (x[1]*x[2])*x[3]^2*x[4]^2 >= 1) - @NLconstraint(m, (x[1]^2*x[2]^2*x[3]^2)*x[4]^2 >= 1) + m = Model( + optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "log_level" => 100, + ), + ) + @variable(m, x[1:4] >= 0) + + @NLconstraint(m, (x[1] * x[2] * x[3]) * x[4] >= 1) + @NLconstraint(m, (x[1]^2 * x[2] * x[3]) * x[4] >= 1) + @NLconstraint(m, x[1] * (x[2]^2 * x[3]) * x[4] >= 1) + @NLconstraint(m, x[1] * (x[2] * x[3]^2) * x[4] >= 1) + @NLconstraint(m, (x[1] * x[2]^2) * x[3] * x[4] >= 1) + @NLconstraint(m, (x[1] * x[2]) * x[3]^2 * x[4] >= 1) + @NLconstraint(m, (x[1] * x[2]) * x[3] * x[4]^2 >= 1) + @NLconstraint(m, (x[1] * x[2]) * x[3]^2 * x[4]^2 >= 1) + @NLconstraint(m, (x[1]^2 * x[2]^2 * x[3]^2) * x[4]^2 >= 1) alpine = _build(m) - @test alpine.bounding_constr_expr_mip[1] == :(x[6]-1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[2] == :(x[9]-1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[3] == :(x[12]-1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[4] == :(x[15]-1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[5] == :(x[17]-1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[6] == :(x[19]-1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[7] == :(x[21]-1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[8] == :(x[22]-1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[9] == :(x[24]-1.0 >= 0.0) - - @test haskey(alpine.nonconvex_terms, [:(x[1]),:(x[2]),:(x[3])]) #5 - @test haskey(alpine.nonconvex_terms, [:(x[4]),:(x[5])]) #6 - @test haskey(alpine.nonconvex_terms, [:(x[1]),:(x[1])]) #7 - @test haskey(alpine.nonconvex_terms, [:(x[2]),:(x[3]),:(x[7])]) #8 - @test haskey(alpine.nonconvex_terms, [:(x[4]),:(x[8])]) #9 - @test haskey(alpine.nonconvex_terms, [:(x[2]),:(x[2])]) #10 - @test haskey(alpine.nonconvex_terms, [:(x[3]),:(x[10])]) #11 - @test haskey(alpine.nonconvex_terms, [:(x[1]),:(x[4]),:(x[11])]) #12 - @test haskey(alpine.nonconvex_terms, [:(x[3]),:(x[3])]) #13 - @test haskey(alpine.nonconvex_terms, [:(x[2]),:(x[13])]) #14 - @test haskey(alpine.nonconvex_terms, [:(x[1]),:(x[4]),:(x[14])]) #15 - @test haskey(alpine.nonconvex_terms, [:(x[1]),:(x[10])]) #16 - @test haskey(alpine.nonconvex_terms, [:(x[3]),:(x[4]),:(x[16])]) #17 - @test haskey(alpine.nonconvex_terms, [:(x[1]),:(x[2])]) #18 - @test haskey(alpine.nonconvex_terms, [:(x[4]),:(x[18]),:(x[13])]) #19 - @test haskey(alpine.nonconvex_terms, [:(x[4]),:(x[4])]) #20 - @test haskey(alpine.nonconvex_terms, [:(x[3]),:(x[18]),:(x[20])]) #21 - @test haskey(alpine.nonconvex_terms, [:(x[18]),:(x[13]),:(x[20])]) #22 - @test haskey(alpine.nonconvex_terms, [:(x[7]),:(x[10]),:(x[13])]) #23 - @test haskey(alpine.nonconvex_terms, [:(x[23]),:(x[20])]) #24 + @test alpine.bounding_constr_expr_mip[1] == :(x[6] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[2] == :(x[9] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[3] == :(x[12] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[4] == :(x[15] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[5] == :(x[17] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[6] == :(x[19] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[7] == :(x[21] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[8] == :(x[22] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[9] == :(x[24] - 1.0 >= 0.0) + + @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2]), :(x[3])]) #5 + @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[5])]) #6 + @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[1])]) #7 + @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[3]), :(x[7])]) #8 + @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[8])]) #9 + @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[2])]) #10 + @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[10])]) #11 + @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[4]), :(x[11])]) #12 + @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[3])]) #13 + @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[13])]) #14 + @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[4]), :(x[14])]) #15 + @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[10])]) #16 + @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[4]), :(x[16])]) #17 + @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2])]) #18 + @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[18]), :(x[13])]) #19 + @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[4])]) #20 + @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[18]), :(x[20])]) #21 + @test haskey(alpine.nonconvex_terms, [:(x[18]), :(x[13]), :(x[20])]) #22 + @test haskey(alpine.nonconvex_terms, [:(x[7]), :(x[10]), :(x[13])]) #23 + @test haskey(alpine.nonconvex_terms, [:(x[23]), :(x[20])]) #24 end @testset "Expression Parsing || Convex" begin - @testset "Convex Parsing :: PART I" begin - - test_solver = optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "log_level" => 100, + ) m = convex_test(solver = test_solver) alpine = _build(m) @@ -1196,7 +1284,8 @@ end @test alpine.nonlinear_constrs[22][:convexified] == :false @test alpine.bounding_constr_mip[22][:sense] == :(<=) @test alpine.bounding_constr_mip[22][:coefs] == [3.0, 4.0, 5.0, 6.0] - @test alpine.bounding_constr_mip[22][:vars] == [:(x[1]), :(x[2]), :(x[3]), :(x[4])] + @test alpine.bounding_constr_mip[22][:vars] == + [:(x[1]), :(x[2]), :(x[3]), :(x[4])] @test alpine.bounding_constr_mip[22][:rhs] == 15.0 @test alpine.bounding_constr_mip[22][:powers] == [2, 2, 2, 2] @test alpine.bounding_constr_mip[22][:cnt] == 4 @@ -1208,7 +1297,8 @@ end @test alpine.nonlinear_constrs[25][:convexified] == :false @test alpine.bounding_constr_mip[25][:sense] == :(<=) @test alpine.bounding_constr_mip[25][:coefs] == [1.0, 1.0, 1.0, 1.0, 1.0] - @test alpine.bounding_constr_mip[25][:vars] == [:(x[1]), :(x[2]), :(x[3]), :(x[4]), :(x[5])] + @test alpine.bounding_constr_mip[25][:vars] == + [:(x[1]), :(x[2]), :(x[3]), :(x[4]), :(x[5])] @test alpine.bounding_constr_mip[25][:rhs] == 99999.0 @test alpine.bounding_constr_mip[25][:powers] == [2, 2, 2, 2, 2] @test alpine.bounding_constr_mip[25][:cnt] == 5 @@ -1228,13 +1318,14 @@ end end @testset "Expression Prasing || Linear Lifting" begin - @testset "Expression Parsing || Linear Lifting || nlp2" begin - test_solver = optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "disc_ratio" => 8, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "disc_ratio" => 8, + "log_level" => 100, + ) m = nlp2(solver = test_solver) @@ -1244,11 +1335,19 @@ end @test length(alpine.nonconvex_terms) == 4 lk = Vector{Any}(undef, 2) - lk[1] = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, -1.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3)]))) - lk[2] = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, -2.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6)]))) + lk[1] = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, -1.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3)])), + ) + lk[2] = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, -2.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6)])), + ) @test length(keys(alpine.linear_terms)) == 2 - yids = [4,7] + yids = [4, 7] for i in 1:length(keys(alpine.linear_terms)) for j in keys(alpine.linear_terms) if alpine.linear_terms[j][:id] == i @@ -1264,7 +1363,6 @@ end @test haskey(alpine.linear_terms, lk[1]) @test haskey(alpine.linear_terms, lk[2]) - @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[2])]) @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[4])]) @test haskey(alpine.nonconvex_terms, [:(x[7]), :(x[7])]) @@ -1280,23 +1378,46 @@ end end @testset "Expression Parsing || Linear Lifting || general" begin - test_solver = optimizer_with_attributes(Alpine.Optimizer,"nlp_solver" => IPOPT, - "mip_solver" => CBC, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "log_level" => 100, + ) m = basic_linear_lift(solver = test_solver) alpine = _build(m) # Setup internal model lk = Vector{Any}(undef, 5) - lk[1] = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1), (-1.0, 2)]))) - lk[2] = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(3.0, 2), (-1.0, 3)]))) - lk[3] = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1), (1.0, 3)]))) - lk[4] = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 2), (1.0, 1)]))) - lk[5] = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 3.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 2), (1.0, 1), (1.0, 3)]))) + lk[1] = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1), (-1.0, 2)])), + ) + lk[2] = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(3.0, 2), (-1.0, 3)])), + ) + lk[3] = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1), (1.0, 3)])), + ) + lk[4] = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 2), (1.0, 1)])), + ) + lk[5] = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 3.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 2), (1.0, 1), (1.0, 3)])), + ) @test length(keys(alpine.linear_terms)) == 5 - yids = [8,9,12,14,16] + yids = [8, 9, 12, 14, 16] for i in 1:length(keys(alpine.linear_terms)) for j in keys(alpine.linear_terms) if alpine.linear_terms[j][:id] == i @@ -1349,24 +1470,25 @@ end @test alpine.nonconvex_terms[nlk8][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[nlk9][:nonlinear_type] == :MONOMIAL - @test alpine.nonconvex_terms[nlk1][:var_idxs] == [8,9,12] - @test alpine.nonconvex_terms[nlk2][:var_idxs] == [2,2] - @test alpine.nonconvex_terms[nlk3][:var_idxs] == [2,3] + @test alpine.nonconvex_terms[nlk1][:var_idxs] == [8, 9, 12] + @test alpine.nonconvex_terms[nlk2][:var_idxs] == [2, 2] + @test alpine.nonconvex_terms[nlk3][:var_idxs] == [2, 3] @test alpine.nonconvex_terms[nlk4][:var_idxs] == [8] - @test alpine.nonconvex_terms[nlk5][:var_idxs] == [1,3] - @test alpine.nonconvex_terms[nlk6][:var_idxs] == [8,9] - @test alpine.nonconvex_terms[nlk7][:var_idxs] == [1,2] + @test alpine.nonconvex_terms[nlk5][:var_idxs] == [1, 3] + @test alpine.nonconvex_terms[nlk6][:var_idxs] == [8, 9] + @test alpine.nonconvex_terms[nlk7][:var_idxs] == [1, 2] @test alpine.nonconvex_terms[nlk8][:var_idxs] == [16, 15] @test alpine.nonconvex_terms[nlk9][:var_idxs] == [14] end @testset "Expression Parsing || Linear Lifting || brainpc3" begin - - test_solver = optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "disc_ratio" => 8, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "disc_ratio" => 8, + "log_level" => 100, + ) m = brainpc3(solver = test_solver) @@ -1374,642 +1496,1192 @@ end @test alpine.nonconvex_terms[Expr[:(x[6912]), :(x[6912])]][:y_idx] == 6913 @test alpine.nonconvex_terms[Expr[:(x[6912]), :(x[6912])]][:id] == 2 - @test alpine.nonconvex_terms[Expr[:(x[6912]), :(x[6912])]][:lifted_constr_ref] == :(x[6913] == (*)(x[6912])) - @test alpine.nonconvex_terms[Expr[:(x[6912]), :(x[6912])]][:nonlinear_type] == :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[6912]), :(x[6912])]][:lifted_constr_ref] == + :(x[6913] == (*)(x[6912])) + @test alpine.nonconvex_terms[Expr[:(x[6912]), :(x[6912])]][:nonlinear_type] == + :MONOMIAL @test alpine.nonconvex_terms[Expr[:(x[6912]), :(x[6912])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6912]), :(x[6912])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6912]), :(x[6912])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6969])]][:y_idx] == 6970 @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6969])]][:id] == 25 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6969])]][:lifted_constr_ref] == :(x[6970] == x[6903] * x[6969]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6969])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6969])]][:lifted_constr_ref] == + :(x[6970] == x[6903] * x[6969]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6969])]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6969])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6969])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6969])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6914])]][:y_idx] == 6915 @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6914])]][:id] == 3 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6914])]][:lifted_constr_ref] == :(x[6915] == x[6903] * x[6914]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6914])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6914])]][:lifted_constr_ref] == + :(x[6915] == x[6903] * x[6914]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6914])]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6914])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6914])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6914])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6919])]][:y_idx] == 6920 @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6919])]][:id] == 5 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6919])]][:lifted_constr_ref] == :(x[6920] == x[6903] * x[6919]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6919])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6919])]][:lifted_constr_ref] == + :(x[6920] == x[6903] * x[6919]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6919])]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6919])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6919])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6919])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6927]), :(x[6927])]][:y_idx] == 6928 @test alpine.nonconvex_terms[Expr[:(x[6927]), :(x[6927])]][:id] == 8 - @test alpine.nonconvex_terms[Expr[:(x[6927]), :(x[6927])]][:lifted_constr_ref] == :(x[6928] == (*)(x[6927])) - @test alpine.nonconvex_terms[Expr[:(x[6927]), :(x[6927])]][:nonlinear_type] == :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[6927]), :(x[6927])]][:lifted_constr_ref] == + :(x[6928] == (*)(x[6927])) + @test alpine.nonconvex_terms[Expr[:(x[6927]), :(x[6927])]][:nonlinear_type] == + :MONOMIAL @test alpine.nonconvex_terms[Expr[:(x[6927]), :(x[6927])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6927]), :(x[6927])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6927]), :(x[6927])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6952]), :(x[6952])]][:y_idx] == 6953 @test alpine.nonconvex_terms[Expr[:(x[6952]), :(x[6952])]][:id] == 18 - @test alpine.nonconvex_terms[Expr[:(x[6952]), :(x[6952])]][:lifted_constr_ref] == :(x[6953] == (*)(x[6952])) - @test alpine.nonconvex_terms[Expr[:(x[6952]), :(x[6952])]][:nonlinear_type] == :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[6952]), :(x[6952])]][:lifted_constr_ref] == + :(x[6953] == (*)(x[6952])) + @test alpine.nonconvex_terms[Expr[:(x[6952]), :(x[6952])]][:nonlinear_type] == + :MONOMIAL @test alpine.nonconvex_terms[Expr[:(x[6952]), :(x[6952])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6952]), :(x[6952])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6952]), :(x[6952])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6962]), :(x[6962])]][:y_idx] == 6963 @test alpine.nonconvex_terms[Expr[:(x[6962]), :(x[6962])]][:id] == 22 - @test alpine.nonconvex_terms[Expr[:(x[6962]), :(x[6962])]][:lifted_constr_ref] == :(x[6963] == (*)(x[6962])) - @test alpine.nonconvex_terms[Expr[:(x[6962]), :(x[6962])]][:nonlinear_type] == :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[6962]), :(x[6962])]][:lifted_constr_ref] == + :(x[6963] == (*)(x[6962])) + @test alpine.nonconvex_terms[Expr[:(x[6962]), :(x[6962])]][:nonlinear_type] == + :MONOMIAL @test alpine.nonconvex_terms[Expr[:(x[6962]), :(x[6962])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6962]), :(x[6962])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6962]), :(x[6962])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6974])]][:y_idx] == 6975 @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6974])]][:id] == 27 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6974])]][:lifted_constr_ref] == :(x[6975] == x[6903] * x[6974]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6974])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6974])]][:lifted_constr_ref] == + :(x[6975] == x[6903] * x[6974]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6974])]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6974])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6974])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6974])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6934])]][:y_idx] == 6935 @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6934])]][:id] == 11 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6934])]][:lifted_constr_ref] == :(x[6935] == x[6903] * x[6934]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6934])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6934])]][:lifted_constr_ref] == + :(x[6935] == x[6903] * x[6934]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6934])]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6934])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6934])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6934])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6959])]][:y_idx] == 6960 @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6959])]][:id] == 21 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6959])]][:lifted_constr_ref] == :(x[6960] == x[6903] * x[6959]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6959])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6959])]][:lifted_constr_ref] == + :(x[6960] == x[6903] * x[6959]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6959])]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6959])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6959])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6959])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7014])]][:y_idx] == 7015 @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7014])]][:id] == 43 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7014])]][:lifted_constr_ref] == :(x[7015] == x[6903] * x[7014]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7014])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7014])]][:lifted_constr_ref] == + :(x[7015] == x[6903] * x[7014]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7014])]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7014])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7014])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7014])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6939])]][:y_idx] == 6940 @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6939])]][:id] == 13 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6939])]][:lifted_constr_ref] == :(x[6940] == x[6903] * x[6939]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6939])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6939])]][:lifted_constr_ref] == + :(x[6940] == x[6903] * x[6939]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6939])]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6939])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6939])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6939])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[7017]), :(x[7017])]][:y_idx] == 7018 @test alpine.nonconvex_terms[Expr[:(x[7017]), :(x[7017])]][:id] == 44 - @test alpine.nonconvex_terms[Expr[:(x[7017]), :(x[7017])]][:lifted_constr_ref] == :(x[7018] == (*)(x[7017])) - @test alpine.nonconvex_terms[Expr[:(x[7017]), :(x[7017])]][:nonlinear_type] == :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[7017]), :(x[7017])]][:lifted_constr_ref] == + :(x[7018] == (*)(x[7017])) + @test alpine.nonconvex_terms[Expr[:(x[7017]), :(x[7017])]][:nonlinear_type] == + :MONOMIAL @test alpine.nonconvex_terms[Expr[:(x[7017]), :(x[7017])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[7017]), :(x[7017])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[7017]), :(x[7017])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6929])]][:y_idx] == 6930 @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6929])]][:id] == 9 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6929])]][:lifted_constr_ref] == :(x[6930] == x[6903] * x[6929]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6929])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6929])]][:lifted_constr_ref] == + :(x[6930] == x[6903] * x[6929]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6929])]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6929])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6929])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6929])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[7012]), :(x[7012])]][:y_idx] == 7013 @test alpine.nonconvex_terms[Expr[:(x[7012]), :(x[7012])]][:id] == 42 - @test alpine.nonconvex_terms[Expr[:(x[7012]), :(x[7012])]][:lifted_constr_ref] == :(x[7013] == (*)(x[7012])) - @test alpine.nonconvex_terms[Expr[:(x[7012]), :(x[7012])]][:nonlinear_type] == :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[7012]), :(x[7012])]][:lifted_constr_ref] == + :(x[7013] == (*)(x[7012])) + @test alpine.nonconvex_terms[Expr[:(x[7012]), :(x[7012])]][:nonlinear_type] == + :MONOMIAL @test alpine.nonconvex_terms[Expr[:(x[7012]), :(x[7012])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[7012]), :(x[7012])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[7012]), :(x[7012])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6947]), :(x[6947])]][:y_idx] == 6948 @test alpine.nonconvex_terms[Expr[:(x[6947]), :(x[6947])]][:id] == 16 - @test alpine.nonconvex_terms[Expr[:(x[6947]), :(x[6947])]][:lifted_constr_ref] == :(x[6948] == (*)(x[6947])) - @test alpine.nonconvex_terms[Expr[:(x[6947]), :(x[6947])]][:nonlinear_type] == :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[6947]), :(x[6947])]][:lifted_constr_ref] == + :(x[6948] == (*)(x[6947])) + @test alpine.nonconvex_terms[Expr[:(x[6947]), :(x[6947])]][:nonlinear_type] == + :MONOMIAL @test alpine.nonconvex_terms[Expr[:(x[6947]), :(x[6947])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6947]), :(x[6947])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6947]), :(x[6947])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[7032]), :(x[7032])]][:y_idx] == 7033 @test alpine.nonconvex_terms[Expr[:(x[7032]), :(x[7032])]][:id] == 50 - @test alpine.nonconvex_terms[Expr[:(x[7032]), :(x[7032])]][:lifted_constr_ref] == :(x[7033] == (*)(x[7032])) - @test alpine.nonconvex_terms[Expr[:(x[7032]), :(x[7032])]][:nonlinear_type] == :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[7032]), :(x[7032])]][:lifted_constr_ref] == + :(x[7033] == (*)(x[7032])) + @test alpine.nonconvex_terms[Expr[:(x[7032]), :(x[7032])]][:nonlinear_type] == + :MONOMIAL @test alpine.nonconvex_terms[Expr[:(x[7032]), :(x[7032])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[7032]), :(x[7032])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[7032]), :(x[7032])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6997]), :(x[6997])]][:y_idx] == 6998 @test alpine.nonconvex_terms[Expr[:(x[6997]), :(x[6997])]][:id] == 36 - @test alpine.nonconvex_terms[Expr[:(x[6997]), :(x[6997])]][:lifted_constr_ref] == :(x[6998] == (*)(x[6997])) - @test alpine.nonconvex_terms[Expr[:(x[6997]), :(x[6997])]][:nonlinear_type] == :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[6997]), :(x[6997])]][:lifted_constr_ref] == + :(x[6998] == (*)(x[6997])) + @test alpine.nonconvex_terms[Expr[:(x[6997]), :(x[6997])]][:nonlinear_type] == + :MONOMIAL @test alpine.nonconvex_terms[Expr[:(x[6997]), :(x[6997])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6997]), :(x[6997])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6997]), :(x[6997])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[7027]), :(x[7027])]][:y_idx] == 7028 @test alpine.nonconvex_terms[Expr[:(x[7027]), :(x[7027])]][:id] == 48 - @test alpine.nonconvex_terms[Expr[:(x[7027]), :(x[7027])]][:lifted_constr_ref] == :(x[7028] == (*)(x[7027])) - @test alpine.nonconvex_terms[Expr[:(x[7027]), :(x[7027])]][:nonlinear_type] == :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[7027]), :(x[7027])]][:lifted_constr_ref] == + :(x[7028] == (*)(x[7027])) + @test alpine.nonconvex_terms[Expr[:(x[7027]), :(x[7027])]][:nonlinear_type] == + :MONOMIAL @test alpine.nonconvex_terms[Expr[:(x[7027]), :(x[7027])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[7027]), :(x[7027])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[7027]), :(x[7027])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[7037]), :(x[7037])]][:y_idx] == 7038 @test alpine.nonconvex_terms[Expr[:(x[7037]), :(x[7037])]][:id] == 52 - @test alpine.nonconvex_terms[Expr[:(x[7037]), :(x[7037])]][:lifted_constr_ref] == :(x[7038] == (*)(x[7037])) - @test alpine.nonconvex_terms[Expr[:(x[7037]), :(x[7037])]][:nonlinear_type] == :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[7037]), :(x[7037])]][:lifted_constr_ref] == + :(x[7038] == (*)(x[7037])) + @test alpine.nonconvex_terms[Expr[:(x[7037]), :(x[7037])]][:nonlinear_type] == + :MONOMIAL @test alpine.nonconvex_terms[Expr[:(x[7037]), :(x[7037])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[7037]), :(x[7037])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[7037]), :(x[7037])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[7007]), :(x[7007])]][:y_idx] == 7008 @test alpine.nonconvex_terms[Expr[:(x[7007]), :(x[7007])]][:id] == 40 - @test alpine.nonconvex_terms[Expr[:(x[7007]), :(x[7007])]][:lifted_constr_ref] == :(x[7008] == (*)(x[7007])) - @test alpine.nonconvex_terms[Expr[:(x[7007]), :(x[7007])]][:nonlinear_type] == :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[7007]), :(x[7007])]][:lifted_constr_ref] == + :(x[7008] == (*)(x[7007])) + @test alpine.nonconvex_terms[Expr[:(x[7007]), :(x[7007])]][:nonlinear_type] == + :MONOMIAL @test alpine.nonconvex_terms[Expr[:(x[7007]), :(x[7007])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[7007]), :(x[7007])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[7007]), :(x[7007])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6964])]][:y_idx] == 6965 @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6964])]][:id] == 23 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6964])]][:lifted_constr_ref] == :(x[6965] == x[6903] * x[6964]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6964])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6964])]][:lifted_constr_ref] == + :(x[6965] == x[6903] * x[6964]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6964])]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6964])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6964])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6964])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6924])]][:y_idx] == 6925 @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6924])]][:id] == 7 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6924])]][:lifted_constr_ref] == :(x[6925] == x[6903] * x[6924]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6924])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6924])]][:lifted_constr_ref] == + :(x[6925] == x[6903] * x[6924]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6924])]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6924])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6924])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6924])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6979])]][:y_idx] == 6980 @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6979])]][:id] == 29 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6979])]][:lifted_constr_ref] == :(x[6980] == x[6903] * x[6979]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6979])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6979])]][:lifted_constr_ref] == + :(x[6980] == x[6903] * x[6979]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6979])]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6979])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6979])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6979])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6994])]][:y_idx] == 6995 @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6994])]][:id] == 35 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6994])]][:lifted_constr_ref] == :(x[6995] == x[6903] * x[6994]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6994])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6994])]][:lifted_constr_ref] == + :(x[6995] == x[6903] * x[6994]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6994])]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6994])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6994])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6994])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6972]), :(x[6972])]][:y_idx] == 6973 @test alpine.nonconvex_terms[Expr[:(x[6972]), :(x[6972])]][:id] == 26 - @test alpine.nonconvex_terms[Expr[:(x[6972]), :(x[6972])]][:lifted_constr_ref] == :(x[6973] == (*)(x[6972])) - @test alpine.nonconvex_terms[Expr[:(x[6972]), :(x[6972])]][:nonlinear_type] == :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[6972]), :(x[6972])]][:lifted_constr_ref] == + :(x[6973] == (*)(x[6972])) + @test alpine.nonconvex_terms[Expr[:(x[6972]), :(x[6972])]][:nonlinear_type] == + :MONOMIAL @test alpine.nonconvex_terms[Expr[:(x[6972]), :(x[6972])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6972]), :(x[6972])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6972]), :(x[6972])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7019])]][:y_idx] == 7020 @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7019])]][:id] == 45 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7019])]][:lifted_constr_ref] == :(x[7020] == x[6903] * x[7019]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7019])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7019])]][:lifted_constr_ref] == + :(x[7020] == x[6903] * x[7019]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7019])]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7019])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7019])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7019])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6992]), :(x[6992])]][:y_idx] == 6993 @test alpine.nonconvex_terms[Expr[:(x[6992]), :(x[6992])]][:id] == 34 - @test alpine.nonconvex_terms[Expr[:(x[6992]), :(x[6992])]][:lifted_constr_ref] == :(x[6993] == (*)(x[6992])) - @test alpine.nonconvex_terms[Expr[:(x[6992]), :(x[6992])]][:nonlinear_type] == :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[6992]), :(x[6992])]][:lifted_constr_ref] == + :(x[6993] == (*)(x[6992])) + @test alpine.nonconvex_terms[Expr[:(x[6992]), :(x[6992])]][:nonlinear_type] == + :MONOMIAL @test alpine.nonconvex_terms[Expr[:(x[6992]), :(x[6992])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6992]), :(x[6992])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6992]), :(x[6992])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[7002]), :(x[7002])]][:y_idx] == 7003 @test alpine.nonconvex_terms[Expr[:(x[7002]), :(x[7002])]][:id] == 38 - @test alpine.nonconvex_terms[Expr[:(x[7002]), :(x[7002])]][:lifted_constr_ref] == :(x[7003] == (*)(x[7002])) - @test alpine.nonconvex_terms[Expr[:(x[7002]), :(x[7002])]][:nonlinear_type] == :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[7002]), :(x[7002])]][:lifted_constr_ref] == + :(x[7003] == (*)(x[7002])) + @test alpine.nonconvex_terms[Expr[:(x[7002]), :(x[7002])]][:nonlinear_type] == + :MONOMIAL @test alpine.nonconvex_terms[Expr[:(x[7002]), :(x[7002])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[7002]), :(x[7002])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[7002]), :(x[7002])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[7022]), :(x[7022])]][:y_idx] == 7023 @test alpine.nonconvex_terms[Expr[:(x[7022]), :(x[7022])]][:id] == 46 - @test alpine.nonconvex_terms[Expr[:(x[7022]), :(x[7022])]][:lifted_constr_ref] == :(x[7023] == (*)(x[7022])) - @test alpine.nonconvex_terms[Expr[:(x[7022]), :(x[7022])]][:nonlinear_type] == :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[7022]), :(x[7022])]][:lifted_constr_ref] == + :(x[7023] == (*)(x[7022])) + @test alpine.nonconvex_terms[Expr[:(x[7022]), :(x[7022])]][:nonlinear_type] == + :MONOMIAL @test alpine.nonconvex_terms[Expr[:(x[7022]), :(x[7022])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[7022]), :(x[7022])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[7022]), :(x[7022])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6908])]][:y_idx] == 6909 @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6908])]][:id] == 1 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6908])]][:lifted_constr_ref] == :(x[6909] == x[6903] * x[6908]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6908])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6908])]][:lifted_constr_ref] == + :(x[6909] == x[6903] * x[6908]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6908])]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6908])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6908])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6908])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6949])]][:y_idx] == 6950 @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6949])]][:id] == 17 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6949])]][:lifted_constr_ref] == :(x[6950] == x[6903] * x[6949]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6949])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6949])]][:lifted_constr_ref] == + :(x[6950] == x[6903] * x[6949]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6949])]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6949])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6949])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6949])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7004])]][:y_idx] == 7005 @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7004])]][:id] == 39 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7004])]][:lifted_constr_ref] == :(x[7005] == x[6903] * x[7004]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7004])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7004])]][:lifted_constr_ref] == + :(x[7005] == x[6903] * x[7004]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7004])]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7004])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7004])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7004])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6917]), :(x[6917])]][:y_idx] == 6918 @test alpine.nonconvex_terms[Expr[:(x[6917]), :(x[6917])]][:id] == 4 - @test alpine.nonconvex_terms[Expr[:(x[6917]), :(x[6917])]][:lifted_constr_ref] == :(x[6918] == (*)(x[6917])) - @test alpine.nonconvex_terms[Expr[:(x[6917]), :(x[6917])]][:nonlinear_type] == :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[6917]), :(x[6917])]][:lifted_constr_ref] == + :(x[6918] == (*)(x[6917])) + @test alpine.nonconvex_terms[Expr[:(x[6917]), :(x[6917])]][:nonlinear_type] == + :MONOMIAL @test alpine.nonconvex_terms[Expr[:(x[6917]), :(x[6917])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6917]), :(x[6917])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6917]), :(x[6917])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6937]), :(x[6937])]][:y_idx] == 6938 @test alpine.nonconvex_terms[Expr[:(x[6937]), :(x[6937])]][:id] == 12 - @test alpine.nonconvex_terms[Expr[:(x[6937]), :(x[6937])]][:lifted_constr_ref] == :(x[6938] == (*)(x[6937])) - @test alpine.nonconvex_terms[Expr[:(x[6937]), :(x[6937])]][:nonlinear_type] == :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[6937]), :(x[6937])]][:lifted_constr_ref] == + :(x[6938] == (*)(x[6937])) + @test alpine.nonconvex_terms[Expr[:(x[6937]), :(x[6937])]][:nonlinear_type] == + :MONOMIAL @test alpine.nonconvex_terms[Expr[:(x[6937]), :(x[6937])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6937]), :(x[6937])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6937]), :(x[6937])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6932]), :(x[6932])]][:y_idx] == 6933 @test alpine.nonconvex_terms[Expr[:(x[6932]), :(x[6932])]][:id] == 10 - @test alpine.nonconvex_terms[Expr[:(x[6932]), :(x[6932])]][:lifted_constr_ref] == :(x[6933] == (*)(x[6932])) - @test alpine.nonconvex_terms[Expr[:(x[6932]), :(x[6932])]][:nonlinear_type] == :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[6932]), :(x[6932])]][:lifted_constr_ref] == + :(x[6933] == (*)(x[6932])) + @test alpine.nonconvex_terms[Expr[:(x[6932]), :(x[6932])]][:nonlinear_type] == + :MONOMIAL @test alpine.nonconvex_terms[Expr[:(x[6932]), :(x[6932])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6932]), :(x[6932])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6932]), :(x[6932])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6989])]][:y_idx] == 6990 @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6989])]][:id] == 33 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6989])]][:lifted_constr_ref] == :(x[6990] == x[6903] * x[6989]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6989])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6989])]][:lifted_constr_ref] == + :(x[6990] == x[6903] * x[6989]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6989])]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6989])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6989])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6989])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6977]), :(x[6977])]][:y_idx] == 6978 @test alpine.nonconvex_terms[Expr[:(x[6977]), :(x[6977])]][:id] == 28 - @test alpine.nonconvex_terms[Expr[:(x[6977]), :(x[6977])]][:lifted_constr_ref] == :(x[6978] == (*)(x[6977])) - @test alpine.nonconvex_terms[Expr[:(x[6977]), :(x[6977])]][:nonlinear_type] == :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[6977]), :(x[6977])]][:lifted_constr_ref] == + :(x[6978] == (*)(x[6977])) + @test alpine.nonconvex_terms[Expr[:(x[6977]), :(x[6977])]][:nonlinear_type] == + :MONOMIAL @test alpine.nonconvex_terms[Expr[:(x[6977]), :(x[6977])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6977]), :(x[6977])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6977]), :(x[6977])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6987]), :(x[6987])]][:y_idx] == 6988 @test alpine.nonconvex_terms[Expr[:(x[6987]), :(x[6987])]][:id] == 32 - @test alpine.nonconvex_terms[Expr[:(x[6987]), :(x[6987])]][:lifted_constr_ref] == :(x[6988] == (*)(x[6987])) - @test alpine.nonconvex_terms[Expr[:(x[6987]), :(x[6987])]][:nonlinear_type] == :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[6987]), :(x[6987])]][:lifted_constr_ref] == + :(x[6988] == (*)(x[6987])) + @test alpine.nonconvex_terms[Expr[:(x[6987]), :(x[6987])]][:nonlinear_type] == + :MONOMIAL @test alpine.nonconvex_terms[Expr[:(x[6987]), :(x[6987])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6987]), :(x[6987])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6987]), :(x[6987])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7034])]][:y_idx] == 7035 @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7034])]][:id] == 51 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7034])]][:lifted_constr_ref] == :(x[7035] == x[6903] * x[7034]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7034])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7034])]][:lifted_constr_ref] == + :(x[7035] == x[6903] * x[7034]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7034])]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7034])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7034])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7034])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6967]), :(x[6967])]][:y_idx] == 6968 @test alpine.nonconvex_terms[Expr[:(x[6967]), :(x[6967])]][:id] == 24 - @test alpine.nonconvex_terms[Expr[:(x[6967]), :(x[6967])]][:lifted_constr_ref] == :(x[6968] == (*)(x[6967])) - @test alpine.nonconvex_terms[Expr[:(x[6967]), :(x[6967])]][:nonlinear_type] == :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[6967]), :(x[6967])]][:lifted_constr_ref] == + :(x[6968] == (*)(x[6967])) + @test alpine.nonconvex_terms[Expr[:(x[6967]), :(x[6967])]][:nonlinear_type] == + :MONOMIAL @test alpine.nonconvex_terms[Expr[:(x[6967]), :(x[6967])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6967]), :(x[6967])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6967]), :(x[6967])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6957]), :(x[6957])]][:y_idx] == 6958 @test alpine.nonconvex_terms[Expr[:(x[6957]), :(x[6957])]][:id] == 20 - @test alpine.nonconvex_terms[Expr[:(x[6957]), :(x[6957])]][:lifted_constr_ref] == :(x[6958] == (*)(x[6957])) - @test alpine.nonconvex_terms[Expr[:(x[6957]), :(x[6957])]][:nonlinear_type] == :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[6957]), :(x[6957])]][:lifted_constr_ref] == + :(x[6958] == (*)(x[6957])) + @test alpine.nonconvex_terms[Expr[:(x[6957]), :(x[6957])]][:nonlinear_type] == + :MONOMIAL @test alpine.nonconvex_terms[Expr[:(x[6957]), :(x[6957])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6957]), :(x[6957])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6957]), :(x[6957])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7009])]][:y_idx] == 7010 @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7009])]][:id] == 41 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7009])]][:lifted_constr_ref] == :(x[7010] == x[6903] * x[7009]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7009])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7009])]][:lifted_constr_ref] == + :(x[7010] == x[6903] * x[7009]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7009])]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7009])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7009])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7009])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6942]), :(x[6942])]][:y_idx] == 6943 @test alpine.nonconvex_terms[Expr[:(x[6942]), :(x[6942])]][:id] == 14 - @test alpine.nonconvex_terms[Expr[:(x[6942]), :(x[6942])]][:lifted_constr_ref] == :(x[6943] == (*)(x[6942])) - @test alpine.nonconvex_terms[Expr[:(x[6942]), :(x[6942])]][:nonlinear_type] == :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[6942]), :(x[6942])]][:lifted_constr_ref] == + :(x[6943] == (*)(x[6942])) + @test alpine.nonconvex_terms[Expr[:(x[6942]), :(x[6942])]][:nonlinear_type] == + :MONOMIAL @test alpine.nonconvex_terms[Expr[:(x[6942]), :(x[6942])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6942]), :(x[6942])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6942]), :(x[6942])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6982]), :(x[6982])]][:y_idx] == 6983 @test alpine.nonconvex_terms[Expr[:(x[6982]), :(x[6982])]][:id] == 30 - @test alpine.nonconvex_terms[Expr[:(x[6982]), :(x[6982])]][:lifted_constr_ref] == :(x[6983] == (*)(x[6982])) - @test alpine.nonconvex_terms[Expr[:(x[6982]), :(x[6982])]][:nonlinear_type] == :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[6982]), :(x[6982])]][:lifted_constr_ref] == + :(x[6983] == (*)(x[6982])) + @test alpine.nonconvex_terms[Expr[:(x[6982]), :(x[6982])]][:nonlinear_type] == + :MONOMIAL @test alpine.nonconvex_terms[Expr[:(x[6982]), :(x[6982])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6982]), :(x[6982])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6982]), :(x[6982])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6999])]][:y_idx] == 7000 @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6999])]][:id] == 37 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6999])]][:lifted_constr_ref] == :(x[7000] == x[6903] * x[6999]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6999])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6999])]][:lifted_constr_ref] == + :(x[7000] == x[6903] * x[6999]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6999])]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6999])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6999])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6999])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6944])]][:y_idx] == 6945 @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6944])]][:id] == 15 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6944])]][:lifted_constr_ref] == :(x[6945] == x[6903] * x[6944]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6944])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6944])]][:lifted_constr_ref] == + :(x[6945] == x[6903] * x[6944]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6944])]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6944])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6944])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6944])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7024])]][:y_idx] == 7025 @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7024])]][:id] == 47 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7024])]][:lifted_constr_ref] == :(x[7025] == x[6903] * x[7024]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7024])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7024])]][:lifted_constr_ref] == + :(x[7025] == x[6903] * x[7024]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7024])]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7024])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7024])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7024])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6954])]][:y_idx] == 6955 @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6954])]][:id] == 19 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6954])]][:lifted_constr_ref] == :(x[6955] == x[6903] * x[6954]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6954])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6954])]][:lifted_constr_ref] == + :(x[6955] == x[6903] * x[6954]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6954])]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6954])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6954])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6954])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6922]), :(x[6922])]][:y_idx] == 6923 @test alpine.nonconvex_terms[Expr[:(x[6922]), :(x[6922])]][:id] == 6 - @test alpine.nonconvex_terms[Expr[:(x[6922]), :(x[6922])]][:lifted_constr_ref] == :(x[6923] == (*)(x[6922])) - @test alpine.nonconvex_terms[Expr[:(x[6922]), :(x[6922])]][:nonlinear_type] == :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[6922]), :(x[6922])]][:lifted_constr_ref] == + :(x[6923] == (*)(x[6922])) + @test alpine.nonconvex_terms[Expr[:(x[6922]), :(x[6922])]][:nonlinear_type] == + :MONOMIAL @test alpine.nonconvex_terms[Expr[:(x[6922]), :(x[6922])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6922]), :(x[6922])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6922]), :(x[6922])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6984])]][:y_idx] == 6985 @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6984])]][:id] == 31 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6984])]][:lifted_constr_ref] == :(x[6985] == x[6903] * x[6984]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6984])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6984])]][:lifted_constr_ref] == + :(x[6985] == x[6903] * x[6984]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6984])]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6984])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6984])]][:constr_id] == Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6984])]][:constr_id] == + Set(Any[0]) @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7029])]][:y_idx] == 7030 @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7029])]][:id] == 49 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7029])]][:lifted_constr_ref] == :(x[7030] == x[6903] * x[7029]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7029])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7029])]][:lifted_constr_ref] == + :(x[7030] == x[6903] * x[7029]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7029])]][:nonlinear_type] == + :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7029])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7029])]][:constr_id] == Set(Any[0]) - lk1 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6910), (-1.0, 6909)]))) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7029])]][:constr_id] == + Set(Any[0]) + lk1 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6910), (-1.0, 6909)])), + ) @test alpine.linear_terms[lk1][:y_idx] == 6911 @test alpine.linear_terms[lk1][:id] == 3 @test alpine.linear_terms[lk1][:y_type] == :(Cont) - lk2 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3467), (1.0, 16)]))) + lk2 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3467), (1.0, 16)])), + ) @test alpine.linear_terms[lk2][:y_idx] == 6908 @test alpine.linear_terms[lk2][:id] == 1 @test alpine.linear_terms[lk2][:y_type] == :(Cont) - lk3 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(0.001548, 6903), (1.0, 7016), (1.0, 5702)]))) + lk3 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(0.001548, 6903), (1.0, 7016), (1.0, 5702)]), + ), + ) @test alpine.linear_terms[lk3][:y_idx] == 7017 @test alpine.linear_terms[lk3][:id] == 67 @test alpine.linear_terms[lk3][:y_type] == :(Cont) - lk4 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 5162), (1.0, 1711)]))) + lk4 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 5162), (1.0, 1711)])), + ) @test alpine.linear_terms[lk4][:y_idx] == 7004 @test alpine.linear_terms[lk4][:id] == 59 @test alpine.linear_terms[lk4][:y_type] == :(Cont) - lk5 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 7021), (0.001435, 6903), (1.0, 6002)]))) + lk5 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 7021), (0.001435, 6903), (1.0, 6002)]), + ), + ) @test alpine.linear_terms[lk5][:y_idx] == 7022 @test alpine.linear_terms[lk5][:id] == 70 @test alpine.linear_terms[lk5][:y_type] == :(Cont) - lk6 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6935), (1.0, 166)]))) + lk6 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6935), (1.0, 166)])), + ) @test alpine.linear_terms[lk6][:y_idx] == 6936 @test alpine.linear_terms[lk6][:id] == 18 @test alpine.linear_terms[lk6][:y_type] == :(Cont) - lk7 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 4262), (0.00247, 6903), (1.0, 6981)]))) + lk7 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 4262), (0.00247, 6903), (1.0, 6981)]), + ), + ) @test alpine.linear_terms[lk7][:y_idx] == 6982 @test alpine.linear_terms[lk7][:id] == 46 @test alpine.linear_terms[lk7][:y_type] == :(Cont) - lk8 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 7005), (1.0, 1711)]))) + lk8 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 7005), (1.0, 1711)])), + ) @test alpine.linear_terms[lk8][:y_idx] == 7006 @test alpine.linear_terms[lk8][:id] == 60 @test alpine.linear_terms[lk8][:y_type] == :(Cont) - lk9 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1951), (1.0, 5402)]))) + lk9 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1951), (1.0, 5402)])), + ) @test alpine.linear_terms[lk9][:y_idx] == 7009 @test alpine.linear_terms[lk9][:id] == 62 @test alpine.linear_terms[lk9][:y_type] == :(Cont) - lk10 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 226), (-1.0, 6945)]))) + lk10 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 226), (-1.0, 6945)])), + ) @test alpine.linear_terms[lk10][:y_idx] == 6946 @test alpine.linear_terms[lk10][:id] == 24 @test alpine.linear_terms[lk10][:y_type] == :(Cont) - lk11 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 7030), (1.0, 3151)]))) + lk11 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 7030), (1.0, 3151)])), + ) @test alpine.linear_terms[lk11][:y_idx] == 7031 @test alpine.linear_terms[lk11][:id] == 75 @test alpine.linear_terms[lk11][:y_type] == :(Cont) - lk12 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6991), (1.0, 4622), (0.002066, 6903)]))) + lk12 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 6991), (1.0, 4622), (0.002066, 6903)]), + ), + ) @test alpine.linear_terms[lk12][:y_idx] == 6992 @test alpine.linear_terms[lk12][:id] == 52 @test alpine.linear_terms[lk12][:y_type] == :(Cont) - lk13 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 7026), (1.0, 6302), (0.001323, 6903)]))) + lk13 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 7026), (1.0, 6302), (0.001323, 6903)]), + ), + ) @test alpine.linear_terms[lk13][:y_idx] == 7027 @test alpine.linear_terms[lk13][:id] == 73 @test alpine.linear_terms[lk13][:y_type] == :(Cont) - lk14 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 46), (1.0, 3497)]))) + lk14 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 46), (1.0, 3497)])), + ) @test alpine.linear_terms[lk14][:y_idx] == 6914 @test alpine.linear_terms[lk14][:id] == 5 @test alpine.linear_terms[lk14][:y_type] == :(Cont) - lk15 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6960), (1.0, 391)]))) + lk15 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6960), (1.0, 391)])), + ) @test alpine.linear_terms[lk15][:y_idx] == 6961 @test alpine.linear_terms[lk15][:id] == 33 @test alpine.linear_terms[lk15][:y_type] == :(Cont) - lk16 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 631), (-1.0, 6975)]))) + lk16 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 631), (-1.0, 6975)])), + ) @test alpine.linear_terms[lk16][:y_idx] == 6976 @test alpine.linear_terms[lk16][:id] == 42 @test alpine.linear_terms[lk16][:y_type] == :(Cont) - lk17 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1351), (-1.0, 6995)]))) + lk17 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1351), (-1.0, 6995)])), + ) @test alpine.linear_terms[lk17][:y_idx] == 6996 @test alpine.linear_terms[lk17][:id] == 54 @test alpine.linear_terms[lk17][:y_type] == :(Cont) - lk18 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3557), (1.0, 106)]))) + lk18 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3557), (1.0, 106)])), + ) @test alpine.linear_terms[lk18][:y_idx] == 6924 @test alpine.linear_terms[lk18][:id] == 11 @test alpine.linear_terms[lk18][:y_type] == :(Cont) - lk19 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3647), (1.0, 6941), (0.004795, 6903)]))) + lk19 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 3647), (1.0, 6941), (0.004795, 6903)]), + ), + ) @test alpine.linear_terms[lk19][:y_idx] == 6942 @test alpine.linear_terms[lk19][:id] == 22 @test alpine.linear_terms[lk19][:y_type] == :(Cont) - lk20 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3722), (1.0, 271)]))) + lk20 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3722), (1.0, 271)])), + ) @test alpine.linear_terms[lk20][:y_idx] == 6949 @test alpine.linear_terms[lk20][:id] == 26 @test alpine.linear_terms[lk20][:y_type] == :(Cont) - lk21 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3647), (1.0, 196)]))) + lk21 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3647), (1.0, 196)])), + ) @test alpine.linear_terms[lk21][:y_idx] == 6939 @test alpine.linear_terms[lk21][:id] == 20 @test alpine.linear_terms[lk21][:y_type] == :(Cont) - lk22 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3467), (1.0, 6911), (6.34e-6, 6903)]))) + lk22 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 3467), (1.0, 6911), (6.34e-6, 6903)]), + ), + ) @test alpine.linear_terms[lk22][:y_idx] == 6912 @test alpine.linear_terms[lk22][:id] == 4 @test alpine.linear_terms[lk22][:y_type] == :(Cont) - lk23 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1531), (1.0, 4982)]))) + lk23 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1531), (1.0, 4982)])), + ) @test alpine.linear_terms[lk23][:y_idx] == 6999 @test alpine.linear_terms[lk23][:id] == 56 @test alpine.linear_terms[lk23][:y_type] == :(Cont) - lk24 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 106), (-1.0, 6925)]))) + lk24 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 106), (-1.0, 6925)])), + ) @test alpine.linear_terms[lk24][:y_idx] == 6926 @test alpine.linear_terms[lk24][:id] == 12 @test alpine.linear_terms[lk24][:y_type] == :(Cont) - lk25 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 2251), (-1.0, 7015)]))) + lk25 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 2251), (-1.0, 7015)])), + ) @test alpine.linear_terms[lk25][:y_idx] == 7016 @test alpine.linear_terms[lk25][:id] == 66 @test alpine.linear_terms[lk25][:y_type] == :(Cont) - lk26 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6936), (0.004985, 6903), (1.0, 3617)]))) + lk26 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 6936), (0.004985, 6903), (1.0, 3617)]), + ), + ) @test alpine.linear_terms[lk26][:y_idx] == 6937 @test alpine.linear_terms[lk26][:id] == 19 @test alpine.linear_terms[lk26][:y_type] == :(Cont) - lk27 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6915), (1.0, 46)]))) + lk27 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6915), (1.0, 46)])), + ) @test alpine.linear_terms[lk27][:y_idx] == 6916 @test alpine.linear_terms[lk27][:id] == 6 @test alpine.linear_terms[lk27][:y_type] == :(Cont) - lk28 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3557), (0.005968, 6903), (1.0, 6926)]))) + lk28 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 3557), (0.005968, 6903), (1.0, 6926)]), + ), + ) @test alpine.linear_terms[lk28][:y_idx] == 6927 @test alpine.linear_terms[lk28][:id] == 13 @test alpine.linear_terms[lk28][:y_type] == :(Cont) - lk29 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 271), (-1.0, 6950)]))) + lk29 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 271), (-1.0, 6950)])), + ) @test alpine.linear_terms[lk29][:y_idx] == 6951 @test alpine.linear_terms[lk29][:id] == 27 @test alpine.linear_terms[lk29][:y_type] == :(Cont) - lk30 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(0.002971, 6903), (1.0, 6971), (1.0, 3962)]))) + lk30 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(0.002971, 6903), (1.0, 6971), (1.0, 3962)]), + ), + ) @test alpine.linear_terms[lk30][:y_idx] == 6972 @test alpine.linear_terms[lk30][:id] == 40 @test alpine.linear_terms[lk30][:y_type] == :(Cont) - lk31 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 511), (-1.0, 6970)]))) + lk31 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 511), (-1.0, 6970)])), + ) @test alpine.linear_terms[lk31][:y_idx] == 6971 @test alpine.linear_terms[lk31][:id] == 39 @test alpine.linear_terms[lk31][:y_type] == :(Cont) - lk32 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 7031), (1.0, 6602), (0.00121, 6903)]))) + lk32 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 7031), (1.0, 6602), (0.00121, 6903)]), + ), + ) @test alpine.linear_terms[lk32][:y_idx] == 7032 @test alpine.linear_terms[lk32][:id] == 76 @test alpine.linear_terms[lk32][:y_type] == :(Cont) - lk33 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(0.00166, 6903), (1.0, 7011), (1.0, 5402)]))) + lk33 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(0.00166, 6903), (1.0, 7011), (1.0, 5402)]), + ), + ) @test alpine.linear_terms[lk33][:y_idx] == 7012 @test alpine.linear_terms[lk33][:id] == 64 @test alpine.linear_terms[lk33][:y_type] == :(Cont) - lk34 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, -0.003214),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 16)]))) + lk34 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, -0.003214), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 16)])), + ) @test alpine.linear_terms[lk34][:y_idx] == 6910 @test alpine.linear_terms[lk34][:id] == 2 @test alpine.linear_terms[lk34][:y_type] == :(Cont) - lk35 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 7035), (1.0, 3451)]))) + lk35 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 7035), (1.0, 3451)])), + ) @test alpine.linear_terms[lk35][:y_idx] == 7036 @test alpine.linear_terms[lk35][:id] == 78 @test alpine.linear_terms[lk35][:y_type] == :(Cont) - lk36 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 2551), (1.0, 6002)]))) + lk36 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 2551), (1.0, 6002)])), + ) @test alpine.linear_terms[lk36][:y_idx] == 7019 @test alpine.linear_terms[lk36][:id] == 68 @test alpine.linear_terms[lk36][:y_type] == :(Cont) - lk37 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3842), (1.0, 391)]))) + lk37 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3842), (1.0, 391)])), + ) @test alpine.linear_terms[lk37][:y_idx] == 6959 @test alpine.linear_terms[lk37][:id] == 32 @test alpine.linear_terms[lk37][:y_type] == :(Cont) - lk38 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6966), (0.00307, 6903), (1.0, 3902)]))) + lk38 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 6966), (0.00307, 6903), (1.0, 3902)]), + ), + ) @test alpine.linear_terms[lk38][:y_idx] == 6967 @test alpine.linear_terms[lk38][:id] == 37 @test alpine.linear_terms[lk38][:y_type] == :(Cont) - lk39 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3722), (0.003829, 6903), (1.0, 6951)]))) + lk39 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 3722), (0.003829, 6903), (1.0, 6951)]), + ), + ) @test alpine.linear_terms[lk39][:y_idx] == 6952 @test alpine.linear_terms[lk39][:id] == 28 @test alpine.linear_terms[lk39][:y_type] == :(Cont) - lk40 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 451), (1.0, 3902)]))) + lk40 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 451), (1.0, 3902)])), + ) @test alpine.linear_terms[lk40][:y_idx] == 6964 @test alpine.linear_terms[lk40][:id] == 35 @test alpine.linear_terms[lk40][:y_type] == :(Cont) - lk41 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 7006), (1.0, 5162), (0.001713, 6903)]))) + lk41 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 7006), (1.0, 5162), (0.001713, 6903)]), + ), + ) @test alpine.linear_terms[lk41][:y_idx] == 7007 @test alpine.linear_terms[lk41][:id] == 61 @test alpine.linear_terms[lk41][:y_type] == :(Cont) - lk42 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 811), (-1.0, 6980)]))) + lk42 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 811), (-1.0, 6980)])), + ) @test alpine.linear_terms[lk42][:y_idx] == 6981 @test alpine.linear_terms[lk42][:id] == 45 @test alpine.linear_terms[lk42][:y_type] == :(Cont) - lk43 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 7001), (1.0, 4982), (0.00173, 6903)]))) + lk43 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 7001), (1.0, 4982), (0.00173, 6903)]), + ), + ) @test alpine.linear_terms[lk43][:y_idx] == 7002 @test alpine.linear_terms[lk43][:id] == 58 @test alpine.linear_terms[lk43][:y_type] == :(Cont) - lk44 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6920), (1.0, 76)]))) + lk44 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6920), (1.0, 76)])), + ) @test alpine.linear_terms[lk44][:y_idx] == 6921 @test alpine.linear_terms[lk44][:id] == 9 @test alpine.linear_terms[lk44][:y_type] == :(Cont) - lk45 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 4622), (1.0, 1171)]))) + lk45 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 4622), (1.0, 1171)])), + ) @test alpine.linear_terms[lk45][:y_idx] == 6989 @test alpine.linear_terms[lk45][:id] == 50 @test alpine.linear_terms[lk45][:y_type] == :(Cont) - lk46 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 991), (1.0, 4442)]))) + lk46 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 991), (1.0, 4442)])), + ) @test alpine.linear_terms[lk46][:y_idx] == 6984 @test alpine.linear_terms[lk46][:id] == 47 @test alpine.linear_terms[lk46][:y_type] == :(Cont) - lk47 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6930), (1.0, 136)]))) + lk47 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6930), (1.0, 136)])), + ) @test alpine.linear_terms[lk47][:y_idx] == 6931 @test alpine.linear_terms[lk47][:id] == 15 @test alpine.linear_terms[lk47][:y_type] == :(Cont) - lk48 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 4802), (0.001891, 6903), (1.0, 6996)]))) + lk48 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 4802), (0.001891, 6903), (1.0, 6996)]), + ), + ) @test alpine.linear_terms[lk48][:y_idx] == 6997 @test alpine.linear_terms[lk48][:id] == 55 @test alpine.linear_terms[lk48][:y_type] == :(Cont) - lk49 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 511), (1.0, 3962)]))) + lk49 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 511), (1.0, 3962)])), + ) @test alpine.linear_terms[lk49][:y_idx] == 6969 @test alpine.linear_terms[lk49][:id] == 38 @test alpine.linear_terms[lk49][:y_type] == :(Cont) - lk50 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 811), (1.0, 4262)]))) + lk50 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 811), (1.0, 4262)])), + ) @test alpine.linear_terms[lk50][:y_idx] == 6979 @test alpine.linear_terms[lk50][:id] == 44 @test alpine.linear_terms[lk50][:y_type] == :(Cont) - lk51 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(0.01551, 6903), (1.0, 6916), (1.0, 3497)]))) + lk51 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(0.01551, 6903), (1.0, 6916), (1.0, 3497)]), + ), + ) @test alpine.linear_terms[lk51][:y_idx] == 6917 @test alpine.linear_terms[lk51][:id] == 7 @test alpine.linear_terms[lk51][:y_type] == :(Cont) - lk52 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 451), (-1.0, 6965)]))) + lk52 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 451), (-1.0, 6965)])), + ) @test alpine.linear_terms[lk52][:y_idx] == 6966 @test alpine.linear_terms[lk52][:id] == 36 @test alpine.linear_terms[lk52][:y_type] == :(Cont) - lk53 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(0.005773, 6903), (1.0, 3587), (1.0, 6931)]))) + lk53 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(0.005773, 6903), (1.0, 3587), (1.0, 6931)]), + ), + ) @test alpine.linear_terms[lk53][:y_idx] == 6932 @test alpine.linear_terms[lk53][:id] == 16 @test alpine.linear_terms[lk53][:y_type] == :(Cont) - lk54 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 631), (1.0, 4082)]))) + lk54 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 631), (1.0, 4082)])), + ) @test alpine.linear_terms[lk54][:y_idx] == 6974 @test alpine.linear_terms[lk54][:id] == 41 @test alpine.linear_terms[lk54][:y_type] == :(Cont) - lk55 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 991), (-1.0, 6985)]))) + lk55 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 991), (-1.0, 6985)])), + ) @test alpine.linear_terms[lk55][:y_idx] == 6986 @test alpine.linear_terms[lk55][:id] == 48 @test alpine.linear_terms[lk55][:y_type] == :(Cont) - lk56 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 4802), (1.0, 1351)]))) + lk56 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 4802), (1.0, 1351)])), + ) @test alpine.linear_terms[lk56][:y_idx] == 6994 @test alpine.linear_terms[lk56][:id] == 53 @test alpine.linear_terms[lk56][:y_type] == :(Cont) - lk57 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6946), (0.004409, 6903), (1.0, 3677)]))) + lk57 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 6946), (0.004409, 6903), (1.0, 3677)]), + ), + ) @test alpine.linear_terms[lk57][:y_idx] == 6947 @test alpine.linear_terms[lk57][:id] == 25 @test alpine.linear_terms[lk57][:y_type] == :(Cont) - lk58 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 2251), (1.0, 5702)]))) + lk58 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 2251), (1.0, 5702)])), + ) @test alpine.linear_terms[lk58][:y_idx] == 7014 @test alpine.linear_terms[lk58][:id] == 65 @test alpine.linear_terms[lk58][:y_type] == :(Cont) - lk59 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 7020), (1.0, 2551)]))) + lk59 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 7020), (1.0, 2551)])), + ) @test alpine.linear_terms[lk59][:y_idx] == 7021 @test alpine.linear_terms[lk59][:id] == 69 @test alpine.linear_terms[lk59][:y_type] == :(Cont) - lk60 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6940), (1.0, 196)]))) + lk60 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6940), (1.0, 196)])), + ) @test alpine.linear_terms[lk60][:y_idx] == 6941 @test alpine.linear_terms[lk60][:id] == 21 @test alpine.linear_terms[lk60][:y_type] == :(Cont) - lk61 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3527), (1.0, 6921), (0.008919, 6903)]))) + lk61 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 3527), (1.0, 6921), (0.008919, 6903)]), + ), + ) @test alpine.linear_terms[lk61][:y_idx] == 6922 @test alpine.linear_terms[lk61][:id] == 10 @test alpine.linear_terms[lk61][:y_type] == :(Cont) - lk62 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 7025), (1.0, 2851)]))) + lk62 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 7025), (1.0, 2851)])), + ) @test alpine.linear_terms[lk62][:y_idx] == 7026 @test alpine.linear_terms[lk62][:id] == 72 @test alpine.linear_terms[lk62][:y_type] == :(Cont) - lk63 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6986), (1.0, 4442), (0.002252, 6903)]))) + lk63 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 6986), (1.0, 4442), (0.002252, 6903)]), + ), + ) @test alpine.linear_terms[lk63][:y_idx] == 6987 @test alpine.linear_terms[lk63][:id] == 49 @test alpine.linear_terms[lk63][:y_type] == :(Cont) - lk64 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(0.002765, 6903), (1.0, 6976), (1.0, 4082)]))) + lk64 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(0.002765, 6903), (1.0, 6976), (1.0, 4082)]), + ), + ) @test alpine.linear_terms[lk64][:y_idx] == 6977 @test alpine.linear_terms[lk64][:id] == 43 @test alpine.linear_terms[lk64][:y_type] == :(Cont) - lk65 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6956), (0.003269, 6903), (1.0, 3782)]))) + lk65 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 6956), (0.003269, 6903), (1.0, 3782)]), + ), + ) @test alpine.linear_terms[lk65][:y_idx] == 6957 @test alpine.linear_terms[lk65][:id] == 31 @test alpine.linear_terms[lk65][:y_type] == :(Cont) - lk66 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3587), (1.0, 136)]))) + lk66 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3587), (1.0, 136)])), + ) @test alpine.linear_terms[lk66][:y_idx] == 6929 @test alpine.linear_terms[lk66][:id] == 14 @test alpine.linear_terms[lk66][:y_type] == :(Cont) - lk67 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 166), (1.0, 3617)]))) + lk67 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 166), (1.0, 3617)])), + ) @test alpine.linear_terms[lk67][:y_idx] == 6934 @test alpine.linear_terms[lk67][:id] == 17 @test alpine.linear_terms[lk67][:y_type] == :(Cont) - lk68 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 7010), (1.0, 1951)]))) + lk68 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 7010), (1.0, 1951)])), + ) @test alpine.linear_terms[lk68][:y_idx] == 7011 @test alpine.linear_terms[lk68][:id] == 63 @test alpine.linear_terms[lk68][:y_type] == :(Cont) - lk69 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 7036), (0.001098, 6903), (1.0, 6902)]))) + lk69 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 7036), (0.001098, 6903), (1.0, 6902)]), + ), + ) @test alpine.linear_terms[lk69][:y_idx] == 7037 @test alpine.linear_terms[lk69][:id] == 79 @test alpine.linear_terms[lk69][:y_type] == :(Cont) - lk70 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3527), (1.0, 76)]))) + lk70 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3527), (1.0, 76)])), + ) @test alpine.linear_terms[lk70][:y_idx] == 6919 @test alpine.linear_terms[lk70][:id] == 8 @test alpine.linear_terms[lk70][:y_type] == :(Cont) - lk71 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6961), (1.0, 3842), (0.00317, 6903)]))) + lk71 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 6961), (1.0, 3842), (0.00317, 6903)]), + ), + ) @test alpine.linear_terms[lk71][:y_idx] == 6962 @test alpine.linear_terms[lk71][:id] == 34 @test alpine.linear_terms[lk71][:y_type] == :(Cont) - lk72 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6990), (1.0, 1171)]))) + lk72 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6990), (1.0, 1171)])), + ) @test alpine.linear_terms[lk72][:y_idx] == 6991 @test alpine.linear_terms[lk72][:id] == 51 @test alpine.linear_terms[lk72][:y_type] == :(Cont) - lk73 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3451), (1.0, 6902)]))) + lk73 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3451), (1.0, 6902)])), + ) @test alpine.linear_terms[lk73][:y_idx] == 7034 @test alpine.linear_terms[lk73][:id] == 77 @test alpine.linear_terms[lk73][:y_type] == :(Cont) - lk74 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6302), (1.0, 2851)]))) + lk74 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6302), (1.0, 2851)])), + ) @test alpine.linear_terms[lk74][:y_idx] == 7024 @test alpine.linear_terms[lk74][:id] == 71 @test alpine.linear_terms[lk74][:y_type] == :(Cont) - lk75 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1531), (-1.0, 7000)]))) + lk75 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1531), (-1.0, 7000)])), + ) @test alpine.linear_terms[lk75][:y_idx] == 7001 @test alpine.linear_terms[lk75][:id] == 57 @test alpine.linear_terms[lk75][:y_type] == :(Cont) - lk76 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3151), (1.0, 6602)]))) + lk76 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3151), (1.0, 6602)])), + ) @test alpine.linear_terms[lk76][:y_idx] == 7029 @test alpine.linear_terms[lk76][:id] == 74 @test alpine.linear_terms[lk76][:y_type] == :(Cont) - lk77 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3782), (1.0, 331)]))) + lk77 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3782), (1.0, 331)])), + ) @test alpine.linear_terms[lk77][:y_idx] == 6954 @test alpine.linear_terms[lk77][:id] == 29 @test alpine.linear_terms[lk77][:y_type] == :(Cont) - lk78 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6955), (1.0, 331)]))) + lk78 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6955), (1.0, 331)])), + ) @test alpine.linear_terms[lk78][:y_idx] == 6956 @test alpine.linear_terms[lk78][:id] == 30 @test alpine.linear_terms[lk78][:y_type] == :(Cont) - lk79 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+),Pair{Symbol,Any}(:scalar, 0.0),Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 226), (1.0, 3677)]))) + lk79 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 226), (1.0, 3677)])), + ) @test alpine.linear_terms[lk79][:y_idx] == 6944 @test alpine.linear_terms[lk79][:id] == 23 @test alpine.linear_terms[lk79][:y_type] == :(Cont) end end - @testset "Expression Parsing || Basic Multiplication Operators (Machine Generated for diffs)" begin - - test_solver=optimizer_with_attributes(Alpine.Optimizer, - "minlp_solver" => JUNIPER, - "mip_solver" => CBC, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "minlp_solver" => JUNIPER, + "mip_solver" => CBC, + "log_level" => 100, + ) m = operator_basic(solver = test_solver) JuMP.set_optimize_hook(m, MOI.Utilities.attach_optimizer) @@ -2020,423 +2692,570 @@ end @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4])]][:y_idx] == 31 @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4])]][:id] == 27 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4])]][:lifted_constr_ref] == :(x[31] == x[3] * x[4]) + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4])]][:lifted_constr_ref] == + :(x[31] == x[3] * x[4]) @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[76])]][:y_idx] == 83 @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[76])]][:id] == 79 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[76])]][:lifted_constr_ref] == :(x[83] == x[4] * x[5] * x[76]) - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[76])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[76])]][:lifted_constr_ref] == + :(x[83] == x[4] * x[5] * x[76]) + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[76])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[2])]][:y_idx] == 9 @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[2])]][:id] == 5 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[2])]][:lifted_constr_ref] == :(x[9] == (*)(x[2])) + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[2])]][:lifted_constr_ref] == + :(x[9] == (*)(x[2])) @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[2])]][:nonlinear_type] == :MONOMIAL @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7])]][:y_idx] == 19 @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7])]][:id] == 15 - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7])]][:lifted_constr_ref] == :(x[19] == x[5] * x[7]) + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7])]][:lifted_constr_ref] == + :(x[19] == x[5] * x[7]) @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[31])]][:y_idx] == 32 @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[31])]][:id] == 28 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[31])]][:lifted_constr_ref] == :(x[32] == x[2] * x[31]) + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[31])]][:lifted_constr_ref] == + :(x[32] == x[2] * x[31]) @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[31])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10])]][:y_idx] == 49 @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10])]][:id] == 45 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10])]][:lifted_constr_ref] == :(x[49] == x[1] * x[2] * x[10]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10])]][:lifted_constr_ref] == + :(x[49] == x[1] * x[2] * x[10]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5]), :(x[9])]][:y_idx] == 50 @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5]), :(x[9])]][:id] == 46 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5]), :(x[9])]][:lifted_constr_ref] == :(x[50] == x[3] * x[5] * x[9]) - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5]), :(x[9])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5]), :(x[9])]][:lifted_constr_ref] == + :(x[50] == x[3] * x[5] * x[9]) + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5]), :(x[9])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[47])]][:y_idx] == 69 @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[47])]][:id] == 65 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[47])]][:lifted_constr_ref] == :(x[69] == x[4] * x[47]) + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[47])]][:lifted_constr_ref] == + :(x[69] == x[4] * x[47]) @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[47])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[4])]][:y_idx] == 28 @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[4])]][:id] == 24 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[4])]][:lifted_constr_ref] == :(x[28] == (*)(x[4])) + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[4])]][:lifted_constr_ref] == + :(x[28] == (*)(x[4])) @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[4])]][:nonlinear_type] == :MONOMIAL @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[10])]][:y_idx] == 37 @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[10])]][:id] == 33 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[10])]][:lifted_constr_ref] == :(x[37] == x[4] * x[10]) + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[10])]][:lifted_constr_ref] == + :(x[37] == x[4] * x[10]) @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[10])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[1])]][:y_idx] == 5 @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[1])]][:id] == 1 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[1])]][:lifted_constr_ref] == :(x[5] == (*)(x[1])) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[1])]][:lifted_constr_ref] == + :(x[5] == (*)(x[1])) @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[1])]][:nonlinear_type] == :MONOMIAL @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[95])]][:y_idx] == 96 @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[95])]][:id] == 92 - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[95])]][:lifted_constr_ref] == :(x[96] == x[5] * x[95]) + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[95])]][:lifted_constr_ref] == + :(x[96] == x[5] * x[95]) @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[95])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[40])]][:y_idx] == 41 @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[40])]][:id] == 37 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[40])]][:lifted_constr_ref] == :(x[41] == x[2] * x[40]) + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[40])]][:lifted_constr_ref] == + :(x[41] == x[2] * x[40]) @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[40])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10])]][:y_idx] == 26 @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10])]][:id] == 22 - @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10])]][:lifted_constr_ref] == :(x[26] == x[6] * x[10]) + @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10])]][:lifted_constr_ref] == + :(x[26] == x[6] * x[10]) @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[78]), :(x[28])]][:y_idx] == 84 @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[78]), :(x[28])]][:id] == 80 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[78]), :(x[28])]][:lifted_constr_ref] == :(x[84] == x[1] * x[78] * x[28]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[78]), :(x[28])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[78]), :(x[28])]][:lifted_constr_ref] == + :(x[84] == x[1] * x[78] * x[28]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[78]), :(x[28])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[43])]][:y_idx] == 58 @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[43])]][:id] == 54 - @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[43])]][:lifted_constr_ref] == :(x[58] == x[6] * x[43]) + @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[43])]][:lifted_constr_ref] == + :(x[58] == x[6] * x[43]) @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[43])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[6]), :(x[10])]][:y_idx] == 106 @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[6]), :(x[10])]][:id] == 102 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[6]), :(x[10])]][:lifted_constr_ref] == :(x[106] == x[4] * x[6] * x[10]) - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[6]), :(x[10])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[6]), :(x[10])]][:lifted_constr_ref] == + :(x[106] == x[4] * x[6] * x[10]) + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[6]), :(x[10])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4]), :(x[10])]][:y_idx] == 90 @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4]), :(x[10])]][:id] == 86 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4]), :(x[10])]][:lifted_constr_ref] == :(x[90] == x[2] * x[4] * x[10]) - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4]), :(x[10])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4]), :(x[10])]][:lifted_constr_ref] == + :(x[90] == x[2] * x[4] * x[10]) + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4]), :(x[10])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[41])]][:y_idx] == 42 @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[41])]][:id] == 38 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[41])]][:lifted_constr_ref] == :(x[42] == x[1] * x[41]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[41])]][:lifted_constr_ref] == + :(x[42] == x[1] * x[41]) @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[41])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[37])]][:y_idx] == 38 @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[37])]][:id] == 34 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[37])]][:lifted_constr_ref] == :(x[38] == x[2] * x[37]) + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[37])]][:lifted_constr_ref] == + :(x[38] == x[2] * x[37]) @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[37])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[85])]][:y_idx] == 87 @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[85])]][:id] == 83 - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[85])]][:lifted_constr_ref] == :(x[87] == x[5] * x[85]) + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[85])]][:lifted_constr_ref] == + :(x[87] == x[5] * x[85]) @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[85])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5]), :(x[28])]][:y_idx] == 66 @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5]), :(x[28])]][:id] == 62 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5]), :(x[28])]][:lifted_constr_ref] == :(x[66] == x[2] * x[3] * x[5] * x[28]) - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5]), :(x[28])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5]), :(x[28])]][:lifted_constr_ref] == + :(x[66] == x[2] * x[3] * x[5] * x[28]) + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5]), :(x[28])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10])]][:y_idx] == 53 @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10])]][:id] == 49 - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10])]][:lifted_constr_ref] == :(x[53] == x[5] * x[9] * x[10]) - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10])]][:lifted_constr_ref] == + :(x[53] == x[5] * x[9] * x[10]) + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6]), :(x[28])]][:y_idx] == 107 @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6]), :(x[28])]][:id] == 103 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6]), :(x[28])]][:lifted_constr_ref] == :(x[107] == x[3] * x[6] * x[28]) - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6]), :(x[28])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6]), :(x[28])]][:lifted_constr_ref] == + :(x[107] == x[3] * x[6] * x[28]) + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6]), :(x[28])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5])]][:y_idx] == 17 @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5])]][:id] == 13 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5])]][:lifted_constr_ref] == :(x[17] == x[2] * x[5]) + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5])]][:lifted_constr_ref] == + :(x[17] == x[2] * x[5]) @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[37])]][:y_idx] == 57 @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[37])]][:id] == 53 - @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[37])]][:lifted_constr_ref] == :(x[57] == x[6] * x[37]) + @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[37])]][:lifted_constr_ref] == + :(x[57] == x[6] * x[37]) @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[37])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7]), :(x[28])]][:y_idx] == 81 @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7]), :(x[28])]][:id] == 77 - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7]), :(x[28])]][:lifted_constr_ref] == :(x[81] == x[5] * x[7] * x[28]) - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7]), :(x[28])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7]), :(x[28])]][:lifted_constr_ref] == + :(x[81] == x[5] * x[7] * x[28]) + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7]), :(x[28])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[38])]][:y_idx] == 39 @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[38])]][:id] == 35 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[38])]][:lifted_constr_ref] == :(x[39] == x[1] * x[38]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[38])]][:lifted_constr_ref] == + :(x[39] == x[1] * x[38]) @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[38])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[9])]][:y_idx] == 48 @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[9])]][:id] == 44 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[9])]][:lifted_constr_ref] == :(x[48] == x[1] * x[3] * x[9]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[9])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[9])]][:lifted_constr_ref] == + :(x[48] == x[1] * x[3] * x[9]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[9])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[23])]][:y_idx] == 24 @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[23])]][:id] == 20 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[23])]][:lifted_constr_ref] == :(x[24] == x[4] * x[23]) + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[23])]][:lifted_constr_ref] == + :(x[24] == x[4] * x[23]) @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[23])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[17])]][:y_idx] == 23 @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[17])]][:id] == 19 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[17])]][:lifted_constr_ref] == :(x[23] == x[3] * x[17]) + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[17])]][:lifted_constr_ref] == + :(x[23] == x[3] * x[17]) @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[17])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[10])]][:y_idx] == 51 @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[10])]][:id] == 47 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[10])]][:lifted_constr_ref] == :(x[51] == x[1] * x[9] * x[10]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[10])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[10])]][:lifted_constr_ref] == + :(x[51] == x[1] * x[9] * x[10]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[10])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[7])]][:y_idx] == 75 @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[7])]][:id] == 71 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[7])]][:lifted_constr_ref] == :(x[75] == x[4] * x[5] * x[7]) - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[7])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[7])]][:lifted_constr_ref] == + :(x[75] == x[4] * x[5] * x[7]) + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[7])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[28])]][:y_idx] == 95 @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[28])]][:id] == 91 - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[28])]][:lifted_constr_ref] == :(x[95] == x[9] * x[10] * x[28]) - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[28])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[28])]][:lifted_constr_ref] == + :(x[95] == x[9] * x[10] * x[28]) + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[28])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10])]][:y_idx] == 11 @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10])]][:id] == 7 - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10])]][:lifted_constr_ref] == :(x[11] == x[9] * x[10]) + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10])]][:lifted_constr_ref] == + :(x[11] == x[9] * x[10]) @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[37])]][:y_idx] == 100 @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[37])]][:id] == 96 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[37])]][:lifted_constr_ref] == :(x[100] == x[1] * x[2] * x[37]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[37])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[37])]][:lifted_constr_ref] == + :(x[100] == x[1] * x[2] * x[37]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[37])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4]), :(x[5])]][:y_idx] == 62 @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4]), :(x[5])]][:id] == 58 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4]), :(x[5])]][:lifted_constr_ref] == :(x[62] == x[2] * x[3] * x[4] * x[5]) - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4]), :(x[5])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4]), :(x[5])]][:lifted_constr_ref] == + :(x[62] == x[2] * x[3] * x[4] * x[5]) + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4]), :(x[5])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[9]), :(x[10])]][:y_idx] == 65 @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[9]), :(x[10])]][:id] == 61 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[9]), :(x[10])]][:lifted_constr_ref] == :(x[65] == x[1] * x[4] * x[9] * x[10]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[9]), :(x[10])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[9]), :(x[10])]][:lifted_constr_ref] == + :(x[65] == x[1] * x[4] * x[9] * x[10]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[9]), :(x[10])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7]), :(x[28])]][:y_idx] == 80 @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7]), :(x[28])]][:id] == 76 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7]), :(x[28])]][:lifted_constr_ref] == :(x[80] == x[1] * x[7] * x[28]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7]), :(x[28])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7]), :(x[28])]][:lifted_constr_ref] == + :(x[80] == x[1] * x[7] * x[28]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7]), :(x[28])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3])]][:y_idx] == 46 @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3])]][:id] == 42 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3])]][:lifted_constr_ref] == :(x[46] == x[1] * x[2] * x[3]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3])]][:lifted_constr_ref] == + :(x[46] == x[1] * x[2] * x[3]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[40])]][:y_idx] == 59 @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[40])]][:id] == 55 - @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[40])]][:lifted_constr_ref] == :(x[59] == x[17] * x[40]) + @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[40])]][:lifted_constr_ref] == + :(x[59] == x[17] * x[40]) @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[40])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[85])]][:y_idx] == 86 @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[85])]][:id] == 82 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[85])]][:lifted_constr_ref] == :(x[86] == x[1] * x[85]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[85])]][:lifted_constr_ref] == + :(x[86] == x[1] * x[85]) @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[85])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[31])]][:y_idx] == 97 @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[31])]][:id] == 93 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[31])]][:lifted_constr_ref] == :(x[97] == x[1] * x[2] * x[31]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[31])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[31])]][:lifted_constr_ref] == + :(x[97] == x[1] * x[2] * x[31]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[31])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[28])]][:y_idx] == 29 @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[28])]][:id] == 25 - @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[28])]][:lifted_constr_ref] == :(x[29] == x[13] * x[28]) + @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[28])]][:lifted_constr_ref] == + :(x[29] == x[13] * x[28]) @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[28])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[28])]][:y_idx] == 92 @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[28])]][:id] == 88 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[28])]][:lifted_constr_ref] == :(x[92] == x[2] * x[3] * x[28]) - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[28])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[28])]][:lifted_constr_ref] == + :(x[92] == x[2] * x[3] * x[28]) + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[28])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9])]][:y_idx] == 20 @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9])]][:id] == 16 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9])]][:lifted_constr_ref] == :(x[20] == x[1] * x[9]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9])]][:lifted_constr_ref] == + :(x[20] == x[1] * x[9]) @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10]), :(x[28])]][:y_idx] == 109 @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10]), :(x[28])]][:id] == 105 - @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10]), :(x[28])]][:lifted_constr_ref] == :(x[109] == x[14] * x[10] * x[28]) - @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10]), :(x[28])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10]), :(x[28])]][:lifted_constr_ref] == + :(x[109] == x[14] * x[10] * x[28]) + @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10]), :(x[28])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[92])]][:y_idx] == 93 @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[92])]][:id] == 89 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[92])]][:lifted_constr_ref] == :(x[93] == x[1] * x[92]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[92])]][:lifted_constr_ref] == + :(x[93] == x[1] * x[92]) @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[92])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4])]][:y_idx] == 85 @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4])]][:id] == 81 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4])]][:lifted_constr_ref] == :(x[85] == x[2] * x[3] * x[4]) - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4])]][:lifted_constr_ref] == + :(x[85] == x[2] * x[3] * x[4]) + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[11])]][:y_idx] == 16 @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[11])]][:id] == 12 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[11])]][:lifted_constr_ref] == :(x[16] == x[1] * x[11]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[11])]][:lifted_constr_ref] == + :(x[16] == x[1] * x[11]) @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[11])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[21])]][:y_idx] == 25 @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[21])]][:id] == 21 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[21])]][:lifted_constr_ref] == :(x[25] == x[4] * x[21]) + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[21])]][:lifted_constr_ref] == + :(x[25] == x[4] * x[21]) @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[21])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[53]), :(x[28])]][:y_idx] == 73 @test alpine.nonconvex_terms[Expr[:(x[53]), :(x[28])]][:id] == 69 - @test alpine.nonconvex_terms[Expr[:(x[53]), :(x[28])]][:lifted_constr_ref] == :(x[73] == x[53] * x[28]) + @test alpine.nonconvex_terms[Expr[:(x[53]), :(x[28])]][:lifted_constr_ref] == + :(x[73] == x[53] * x[28]) @test alpine.nonconvex_terms[Expr[:(x[53]), :(x[28])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[32])]][:y_idx] == 34 @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[32])]][:id] == 30 - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[32])]][:lifted_constr_ref] == :(x[34] == x[5] * x[32]) + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[32])]][:lifted_constr_ref] == + :(x[34] == x[5] * x[32]) @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[32])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[28])]][:y_idx] == 40 @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[28])]][:id] == 36 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[28])]][:lifted_constr_ref] == :(x[40] == x[3] * x[28]) + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[28])]][:lifted_constr_ref] == + :(x[40] == x[3] * x[28]) @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[28])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10]), :(x[28])]][:y_idx] == 67 @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10]), :(x[28])]][:id] == 63 - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10]), :(x[28])]][:lifted_constr_ref] == :(x[67] == x[5] * x[9] * x[10] * x[28]) - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10]), :(x[28])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10]), :(x[28])]][:lifted_constr_ref] == + :(x[67] == x[5] * x[9] * x[10] * x[28]) + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10]), :(x[28])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[43])]][:y_idx] == 102 @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[43])]][:id] == 98 - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[43])]][:lifted_constr_ref] == :(x[102] == x[5] * x[9] * x[43]) - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[43])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[43])]][:lifted_constr_ref] == + :(x[102] == x[5] * x[9] * x[43]) + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[43])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[26])]][:y_idx] == 27 @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[26])]][:id] == 23 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[26])]][:lifted_constr_ref] == :(x[27] == x[4] * x[26]) + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[26])]][:lifted_constr_ref] == + :(x[27] == x[4] * x[26]) @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[26])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[20]), :(x[31])]][:y_idx] == 56 @test alpine.nonconvex_terms[Expr[:(x[20]), :(x[31])]][:id] == 52 - @test alpine.nonconvex_terms[Expr[:(x[20]), :(x[31])]][:lifted_constr_ref] == :(x[56] == x[20] * x[31]) + @test alpine.nonconvex_terms[Expr[:(x[20]), :(x[31])]][:lifted_constr_ref] == + :(x[56] == x[20] * x[31]) @test alpine.nonconvex_terms[Expr[:(x[20]), :(x[31])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[4]), :(x[9])]][:y_idx] == 63 @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[4]), :(x[9])]][:id] == 59 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[4]), :(x[9])]][:lifted_constr_ref] == :(x[63] == x[1] * x[3] * x[4] * x[9]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[4]), :(x[9])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[4]), :(x[9])]][:lifted_constr_ref] == + :(x[63] == x[1] * x[3] * x[4] * x[9]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[4]), :(x[9])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10])]][:y_idx] == 15 @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10])]][:id] == 11 - @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10])]][:lifted_constr_ref] == :(x[15] == x[14] * x[10]) + @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10])]][:lifted_constr_ref] == + :(x[15] == x[14] * x[10]) @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[76])]][:y_idx] == 77 @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[76])]][:id] == 73 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[76])]][:lifted_constr_ref] == :(x[77] == x[1] * x[4] * x[76]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[76])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[76])]][:lifted_constr_ref] == + :(x[77] == x[1] * x[4] * x[76]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[76])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[88])]][:y_idx] == 89 @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[88])]][:id] == 85 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[88])]][:lifted_constr_ref] == :(x[89] == x[1] * x[88]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[88])]][:lifted_constr_ref] == + :(x[89] == x[1] * x[88]) @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[88])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[90])]][:y_idx] == 94 @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[90])]][:id] == 90 - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[90])]][:lifted_constr_ref] == :(x[94] == x[5] * x[90]) + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[90])]][:lifted_constr_ref] == + :(x[94] == x[5] * x[90]) @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[90])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10]), :(x[28])]][:y_idx] == 108 @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10]), :(x[28])]][:id] == 104 - @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10]), :(x[28])]][:lifted_constr_ref] == :(x[108] == x[6] * x[10] * x[28]) - @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10]), :(x[28])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10]), :(x[28])]][:lifted_constr_ref] == + :(x[108] == x[6] * x[10] * x[28]) + @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10]), :(x[28])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[48])]][:y_idx] == 70 @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[48])]][:id] == 66 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[48])]][:lifted_constr_ref] == :(x[70] == x[4] * x[48]) + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[48])]][:lifted_constr_ref] == + :(x[70] == x[4] * x[48]) @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[48])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[31])]][:y_idx] == 54 @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[31])]][:id] == 50 - @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[31])]][:lifted_constr_ref] == :(x[54] == x[6] * x[31]) + @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[31])]][:lifted_constr_ref] == + :(x[54] == x[6] * x[31]) @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[31])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[31])]][:y_idx] == 99 @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[31])]][:id] == 95 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[31])]][:lifted_constr_ref] == :(x[99] == x[1] * x[9] * x[31]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[31])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[31])]][:lifted_constr_ref] == + :(x[99] == x[1] * x[9] * x[31]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[31])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[35])]][:y_idx] == 36 @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[35])]][:id] == 32 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[35])]][:lifted_constr_ref] == :(x[36] == x[1] * x[35]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[35])]][:lifted_constr_ref] == + :(x[36] == x[1] * x[35]) @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[35])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9])]][:y_idx] == 14 @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9])]][:id] == 10 - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9])]][:lifted_constr_ref] == :(x[14] == x[5] * x[9]) + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9])]][:lifted_constr_ref] == + :(x[14] == x[5] * x[9]) @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[13])]][:y_idx] == 22 @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[13])]][:id] == 18 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[13])]][:lifted_constr_ref] == :(x[22] == x[4] * x[13]) + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[13])]][:lifted_constr_ref] == + :(x[22] == x[4] * x[13]) @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[13])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10]), :(x[28])]][:y_idx] == 64 @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10]), :(x[28])]][:id] == 60 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10]), :(x[28])]][:lifted_constr_ref] == :(x[64] == x[1] * x[2] * x[10] * x[28]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10]), :(x[28])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10]), :(x[28])]][:lifted_constr_ref] == + :(x[64] == x[1] * x[2] * x[10] * x[28]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10]), :(x[28])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[46]), :(x[28])]][:y_idx] == 72 @test alpine.nonconvex_terms[Expr[:(x[46]), :(x[28])]][:id] == 68 - @test alpine.nonconvex_terms[Expr[:(x[46]), :(x[28])]][:lifted_constr_ref] == :(x[72] == x[46] * x[28]) + @test alpine.nonconvex_terms[Expr[:(x[46]), :(x[28])]][:lifted_constr_ref] == + :(x[72] == x[46] * x[28]) @test alpine.nonconvex_terms[Expr[:(x[46]), :(x[28])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[31])]][:y_idx] == 55 @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[31])]][:id] == 51 - @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[31])]][:lifted_constr_ref] == :(x[55] == x[17] * x[31]) + @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[31])]][:lifted_constr_ref] == + :(x[55] == x[17] * x[31]) @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[31])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[31])]][:y_idx] == 98 @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[31])]][:id] == 94 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[31])]][:lifted_constr_ref] == :(x[98] == x[2] * x[5] * x[31]) - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[31])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[31])]][:lifted_constr_ref] == + :(x[98] == x[2] * x[5] * x[31]) + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[31])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[28])]][:y_idx] == 43 @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[28])]][:id] == 39 - @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[28])]][:lifted_constr_ref] == :(x[43] == x[10] * x[28]) + @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[28])]][:lifted_constr_ref] == + :(x[43] == x[10] * x[28]) @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[28])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[10])]][:y_idx] == 78 @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[10])]][:id] == 74 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[10])]][:lifted_constr_ref] == :(x[78] == x[2] * x[10]) + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[10])]][:lifted_constr_ref] == + :(x[78] == x[2] * x[10]) @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[10])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[10])]][:y_idx] == 52 @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[10])]][:id] == 48 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[10])]][:lifted_constr_ref] == :(x[52] == x[2] * x[5] * x[10]) - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[10])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[10])]][:lifted_constr_ref] == + :(x[52] == x[2] * x[5] * x[10]) + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[10])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[90])]][:y_idx] == 91 @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[90])]][:id] == 87 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[90])]][:lifted_constr_ref] == :(x[91] == x[1] * x[90]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[90])]][:lifted_constr_ref] == + :(x[91] == x[1] * x[90]) @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[90])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[17])]][:y_idx] == 104 @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[17])]][:id] == 100 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[17])]][:lifted_constr_ref] == :(x[104] == x[3] * x[4] * x[17]) - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[17])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[17])]][:lifted_constr_ref] == + :(x[104] == x[3] * x[4] * x[17]) + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[17])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[9])]][:y_idx] == 76 @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[9])]][:id] == 72 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[9])]][:lifted_constr_ref] == :(x[76] == x[3] * x[9]) + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[9])]][:lifted_constr_ref] == + :(x[76] == x[3] * x[9]) @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[9])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[78])]][:y_idx] == 79 @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[78])]][:id] == 75 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[78])]][:lifted_constr_ref] == :(x[79] == x[1] * x[4] * x[78]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[78])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[78])]][:lifted_constr_ref] == + :(x[79] == x[1] * x[4] * x[78]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[78])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[3])]][:y_idx] == 10 @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[3])]][:id] == 6 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[3])]][:lifted_constr_ref] == :(x[10] == (*)(x[3])) + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[3])]][:lifted_constr_ref] == + :(x[10] == (*)(x[3])) @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[3])]][:nonlinear_type] == :MONOMIAL @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[49])]][:y_idx] == 71 @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[49])]][:id] == 67 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[49])]][:lifted_constr_ref] == :(x[71] == x[4] * x[49]) + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[49])]][:lifted_constr_ref] == + :(x[71] == x[4] * x[49]) @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[49])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[9])]][:y_idx] == 88 @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[9])]][:id] == 84 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[9])]][:lifted_constr_ref] == :(x[88] == x[3] * x[4] * x[9]) - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[9])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[9])]][:lifted_constr_ref] == + :(x[88] == x[3] * x[4] * x[9]) + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[9])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[15]), :(x[28])]][:y_idx] == 30 @test alpine.nonconvex_terms[Expr[:(x[15]), :(x[28])]][:id] == 26 - @test alpine.nonconvex_terms[Expr[:(x[15]), :(x[28])]][:lifted_constr_ref] == :(x[30] == x[15] * x[28]) + @test alpine.nonconvex_terms[Expr[:(x[15]), :(x[28])]][:lifted_constr_ref] == + :(x[30] == x[15] * x[28]) @test alpine.nonconvex_terms[Expr[:(x[15]), :(x[28])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[46])]][:y_idx] == 68 @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[46])]][:id] == 64 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[46])]][:lifted_constr_ref] == :(x[68] == x[4] * x[46]) + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[46])]][:lifted_constr_ref] == + :(x[68] == x[4] * x[46]) @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[46])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[11])]][:y_idx] == 12 @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[11])]][:id] == 8 - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[11])]][:lifted_constr_ref] == :(x[12] == x[5] * x[11]) + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[11])]][:lifted_constr_ref] == + :(x[12] == x[5] * x[11]) @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[11])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[7])]][:y_idx] == 74 @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[7])]][:id] == 70 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[7])]][:lifted_constr_ref] == :(x[74] == x[1] * x[4] * x[7]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[7])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[7])]][:lifted_constr_ref] == + :(x[74] == x[1] * x[4] * x[7]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[7])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[20])]][:y_idx] == 105 @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[20])]][:id] == 101 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[20])]][:lifted_constr_ref] == :(x[105] == x[3] * x[4] * x[20]) - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[20])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[20])]][:lifted_constr_ref] == + :(x[105] == x[3] * x[4] * x[20]) + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[20])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[11])]][:y_idx] == 82 @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[11])]][:id] == 78 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[11])]][:lifted_constr_ref] == :(x[82] == x[1] * x[4] * x[11]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[11])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[11])]][:lifted_constr_ref] == + :(x[82] == x[1] * x[4] * x[11]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[11])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[43])]][:y_idx] == 44 @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[43])]][:id] == 40 - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[43])]][:lifted_constr_ref] == :(x[44] == x[9] * x[43]) + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[43])]][:lifted_constr_ref] == + :(x[44] == x[9] * x[43]) @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[43])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:y_idx] == 61 @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:id] == 57 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:lifted_constr_ref] == :(x[61] == x[1] * x[2] * x[3] * x[4]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:lifted_constr_ref] == + :(x[61] == x[1] * x[2] * x[3] * x[4]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[10])]][:y_idx] == 18 @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[10])]][:id] == 14 - @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[10])]][:lifted_constr_ref] == :(x[18] == x[17] * x[10]) + @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[10])]][:lifted_constr_ref] == + :(x[18] == x[17] * x[10]) @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[10])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7])]][:y_idx] == 8 @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7])]][:id] == 4 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7])]][:lifted_constr_ref] == :(x[8] == x[1] * x[7]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7])]][:lifted_constr_ref] == + :(x[8] == x[1] * x[7]) @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2])]][:y_idx] == 6 @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2])]][:id] == 2 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2])]][:lifted_constr_ref] == :(x[6] == x[1] * x[2]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2])]][:lifted_constr_ref] == + :(x[6] == x[1] * x[2]) @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[40])]][:y_idx] == 101 @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[40])]][:id] == 97 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[40])]][:lifted_constr_ref] == :(x[101] == x[1] * x[2] * x[40]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[40])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[40])]][:lifted_constr_ref] == + :(x[101] == x[1] * x[2] * x[40]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[40])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[37])]][:y_idx] == 60 @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[37])]][:id] == 56 - @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[37])]][:lifted_constr_ref] == :(x[60] == x[17] * x[37]) + @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[37])]][:lifted_constr_ref] == + :(x[60] == x[17] * x[37]) @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[37])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[6])]][:y_idx] == 103 @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[6])]][:id] == 99 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[6])]][:lifted_constr_ref] == :(x[103] == x[3] * x[4] * x[6]) - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[6])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[6])]][:lifted_constr_ref] == + :(x[103] == x[3] * x[4] * x[6]) + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[6])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3])]][:y_idx] == 7 @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3])]][:id] == 3 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3])]][:lifted_constr_ref] == :(x[7] == x[2] * x[3]) + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3])]][:lifted_constr_ref] == + :(x[7] == x[2] * x[3]) @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5])]][:y_idx] == 47 @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5])]][:id] == 43 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5])]][:lifted_constr_ref] == :(x[47] == x[2] * x[3] * x[5]) - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5])]][:lifted_constr_ref] == + :(x[47] == x[2] * x[3] * x[5]) + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6])]][:y_idx] == 13 @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6])]][:id] == 9 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6])]][:lifted_constr_ref] == :(x[13] == x[3] * x[6]) + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6])]][:lifted_constr_ref] == + :(x[13] == x[3] * x[6]) @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[31])]][:y_idx] == 35 @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[31])]][:id] == 31 - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[31])]][:lifted_constr_ref] == :(x[35] == x[9] * x[31]) + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[31])]][:lifted_constr_ref] == + :(x[35] == x[9] * x[31]) @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[31])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[32])]][:y_idx] == 33 @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[32])]][:id] == 29 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[32])]][:lifted_constr_ref] == :(x[33] == x[1] * x[32]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[32])]][:lifted_constr_ref] == + :(x[33] == x[1] * x[32]) @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[32])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[20])]][:y_idx] == 21 @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[20])]][:id] == 17 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[20])]][:lifted_constr_ref] == :(x[21] == x[3] * x[20]) + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[20])]][:lifted_constr_ref] == + :(x[21] == x[3] * x[20]) @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[20])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[44])]][:y_idx] == 45 @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[44])]][:id] == 41 - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[44])]][:lifted_constr_ref] == :(x[45] == x[5] * x[44]) + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[44])]][:lifted_constr_ref] == + :(x[45] == x[5] * x[44]) @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[44])]][:nonlinear_type] == :BILINEAR @test alpine.bounding_constr_mip[1][:rhs] == 1.0 @@ -2518,16 +3337,18 @@ end @testset "Expression Parsing || corner cases" begin @testset "Corner Cases - 1 : sign convertor special case" begin - test_solver = optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "minlp_solver" => JUNIPER, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "minlp_solver" => JUNIPER, + "log_level" => 100, + ) m = Model(test_solver) @variable(m, 0 <= x[1:5] <= 1, Bin) @NLconstraint(m, x[1] + -x[2] >= 2) - @objective(m, Min, x[1]+x[2]) + @objective(m, Min, x[1] + x[2]) alpine = _build(m) @test alpine.bounding_constr_mip[1][:rhs] == 2.0 @@ -2538,16 +3359,18 @@ end end @testset "Corner Cases - 2 : full sub-expression" begin - test_solver = optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "log_level" => 100, + ) m = Model(test_solver) - @variable(m, x[1:5]>=0) + @variable(m, x[1:5] >= 0) @NLconstraint(m, (x[1] + 10 + 4 * x[2] + 200) * 5 >= 2 * 5) @constraint(m, x[1] + x[2] + 200 >= 2) - @objective(m, Min, x[1]+x[2]) + @objective(m, Min, x[1] + x[2]) alpine = _build(m) @test alpine.bounding_constr_mip[1][:rhs] == -198.0 @@ -2563,16 +3386,18 @@ end end @testset "Corner Cases - 2 : full sub-expression" begin - test_solver = optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "log_level" => 100, + ) m = Model(test_solver) - @variable(m, x[1:5]>=0) + @variable(m, x[1:5] >= 0) @NLconstraint(m, (x[1] + 10 + 4 * x[2] + 200) * 5 >= 2 * 5) @constraint(m, x[1] + x[2] + 200 >= 2) - @objective(m, Min, x[1]+x[2]) + @objective(m, Min, x[1] + x[2]) alpine = _build(m) @test alpine.bounding_constr_mip[1][:rhs] == -198.0 @@ -2589,14 +3414,14 @@ end end @testset "Expression Parsing || Discrete Multilinear" begin - @testset "Expression Parsing || bmpl && binlin && binprod" begin - - test_solver=optimizer_with_attributes(Alpine.Optimizer, - "minlp_solver" => JUNIPER, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "minlp_solver" => JUNIPER, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "log_level" => 100, + ) m = bpml(solver = test_solver) @@ -2614,21 +3439,47 @@ end @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[7]), :(x[8])]][:y_idx] == 18 @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[18])]][:y_idx] == 19 @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[18])]][:y_idx] == 20 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3]), :(x[4]), :(x[5])]][:y_idx] == 21 - @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[7]), :(x[9]), :(x[10]), :(x[6])]][:y_idx] == 22 + @test alpine.nonconvex_terms[Expr[ + :(x[1]), + :(x[2]), + :(x[3]), + :(x[4]), + :(x[5]), + ]][:y_idx] == 21 + @test alpine.nonconvex_terms[Expr[ + :(x[6]), + :(x[7]), + :(x[9]), + :(x[10]), + :(x[6]), + ]][:y_idx] == 22 @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[6])]][:nonlinear_type] == :BINLIN @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2])]][:nonlinear_type] == :BINPROD @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[6])]][:nonlinear_type] == :BINLIN - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3])]][:nonlinear_type] == :BINPROD + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3])]][:nonlinear_type] == + :BINPROD @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[6])]][:nonlinear_type] == :BINLIN @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[7])]][:nonlinear_type] == :BILINEAR @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[16])]][:nonlinear_type] == :BINLIN - @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[7]), :(x[8])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[7]), :(x[8])]][:nonlinear_type] == + :MULTILINEAR @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[18])]][:nonlinear_type] == :BINLIN @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[18])]][:nonlinear_type] == :BINLIN - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3]), :(x[4]), :(x[5])]][:nonlinear_type] == :BINPROD - @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[7]), :(x[9]), :(x[10]), :(x[6])]][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[Expr[ + :(x[1]), + :(x[2]), + :(x[3]), + :(x[4]), + :(x[5]), + ]][:nonlinear_type] == :BINPROD + @test alpine.nonconvex_terms[Expr[ + :(x[6]), + :(x[7]), + :(x[9]), + :(x[10]), + :(x[6]), + ]][:nonlinear_type] == :MULTILINEAR @test length(alpine.var_type) == 22 @test alpine.var_type[11] == :Cont @@ -2646,32 +3497,43 @@ end end @testset "Expression Parsing || bmpl && binlin && binprod with linear lifting and coefficients" begin - - test_solver=optimizer_with_attributes(Alpine.Optimizer, - "minlp_solver" => JUNIPER, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "minlp_solver" => JUNIPER, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "log_level" => 100, + ) m = bmpl_linearlifting(solver = test_solver) alpine = _build(m) - lk1 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1), (1.0, 17)]))) - lk2 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 11), (1.0, 12)]))) - lk3 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 7), (2.0, 6)]))) - lk4 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6), (1.0, 19)]))) - lk5 = Dict{Symbol,Any}(Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6), (1.0, 25)]))) + lk1 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1), (1.0, 17)])), + ) + lk2 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 11), (1.0, 12)])), + ) + lk3 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 7), (2.0, 6)])), + ) + lk4 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6), (1.0, 19)])), + ) + lk5 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6), (1.0, 25)])), + ) @test haskey(alpine.linear_terms, lk1) @test haskey(alpine.linear_terms, lk2) @@ -2681,7 +3543,7 @@ end @test alpine.linear_terms[lk1][:lifted_constr_ref] == :(x[20] == x[1] + x[17]) @test alpine.linear_terms[lk2][:lifted_constr_ref] == :(x[13] == x[11] + x[12]) - @test alpine.linear_terms[lk3][:lifted_constr_ref] == :(x[15] == 2*x[6] + x[7]) + @test alpine.linear_terms[lk3][:lifted_constr_ref] == :(x[15] == 2 * x[6] + x[7]) @test alpine.linear_terms[lk4][:lifted_constr_ref] == :(x[21] == x[6] + x[19]) @test alpine.linear_terms[lk5][:lifted_constr_ref] == :(x[26] == x[6] + x[25]) @@ -2779,11 +3641,13 @@ end @testset "Expr dereferencing for @NLexpression" begin # Taken from Juniper.jl - test_solver = JuMP.optimizer_with_attributes(Alpine.Optimizer, - "minlp_solver" => JUNIPER, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "presolve_bt" => true) + test_solver = JuMP.optimizer_with_attributes( + Alpine.Optimizer, + "minlp_solver" => JUNIPER, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "presolve_bt" => true, + ) m = Model(test_solver) @variable(m, 0 <= x <= 1) diff --git a/test/test_solver.jl b/test/test_solver.jl index 196614ca..c4546cbe 100644 --- a/test/test_solver.jl +++ b/test/test_solver.jl @@ -1,8 +1,11 @@ @testset "Optimizer loading tests" begin # Random Model 1 - test_solver = optimizer_with_attributes(Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "log_level" => 100, + ) m = operator_c(solver = test_solver) alpine = _build(m) @@ -16,81 +19,89 @@ end @testset "Partitioning variable selection tests :: nlp3" begin # Select all NL variable - test_solver = optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "disc_var_pick" => 0, - "disc_uniform_rate" => 10, - "presolve_bp" => false, - "presolve_bt" => false, - "max_iter" => 1, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "disc_var_pick" => 0, + "disc_uniform_rate" => 10, + "presolve_bp" => false, + "presolve_bt" => false, + "max_iter" => 1, + "log_level" => 100, + ) m = nlp3(solver = test_solver) JuMP.optimize!(m) alpine = JuMP.backend(m).optimizer.model @test JuMP.termination_status(m) == MOI.OTHER_LIMIT - @test isapprox(JuMP.objective_value(m), 7049.2478976; atol=1e-3) + @test isapprox(JuMP.objective_value(m), 7049.2478976; atol = 1e-3) @test length(alpine.candidate_disc_vars) == 8 @test length(alpine.disc_vars) == 8 @test MOI.get(m, MOI.RawOptimizerAttribute("disc_var_pick")) == 0 # Select all NL variable - test_solver = optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "disc_var_pick" => 2, - "disc_uniform_rate" => 10, - "presolve_bp" => false, - "presolve_bt" => false, - "max_iter" => 1, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "disc_var_pick" => 2, + "disc_uniform_rate" => 10, + "presolve_bp" => false, + "presolve_bt" => false, + "max_iter" => 1, + "log_level" => 100, + ) m = nlp3(solver = test_solver) JuMP.optimize!(m) alpine = JuMP.backend(m).optimizer.model @test JuMP.termination_status(m) == MOI.OTHER_LIMIT - @test isapprox(JuMP.objective_value(m), 7049.2478976; atol=1e-3) + @test isapprox(JuMP.objective_value(m), 7049.2478976; atol = 1e-3) @test length(alpine.candidate_disc_vars) == 8 @test length(alpine.disc_vars) == 8 @test MOI.get(m, MOI.RawOptimizerAttribute("disc_var_pick")) == 2 # Minimum vertex cover algorithm - test_solver = optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "disc_var_pick" => 1, - "disc_uniform_rate" => 10, - "presolve_bp" => false, - "presolve_bt" => false, - "max_iter" => 1, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "disc_var_pick" => 1, + "disc_uniform_rate" => 10, + "presolve_bp" => false, + "presolve_bt" => false, + "max_iter" => 1, + "log_level" => 100, + ) m = nlp3(solver = test_solver) JuMP.optimize!(m) alpine = JuMP.backend(m).optimizer.model @test JuMP.termination_status(m) == MOI.OTHER_LIMIT - @test isapprox(JuMP.objective_value(m), 7049.2478976; atol=1e-3) + @test isapprox(JuMP.objective_value(m), 7049.2478976; atol = 1e-3) @test length(alpine.candidate_disc_vars) == 8 @test length(alpine.disc_vars) == 3 @test MOI.get(m, MOI.RawOptimizerAttribute("disc_var_pick")) == 1 # Adaptive variable selection scheme :: disc_var_pick = 3 - test_solver = optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "disc_var_pick" => 3, - "presolve_bp" => false, - "presolve_bt" => false, - "max_iter" => 2, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "disc_var_pick" => 3, + "presolve_bp" => false, + "presolve_bt" => false, + "max_iter" => 2, + "log_level" => 100, + ) m = nlp3(solver = test_solver) JuMP.optimize!(m) alpine = JuMP.backend(m).optimizer.model @test JuMP.termination_status(m) == MOI.OTHER_LIMIT - @test isapprox(JuMP.objective_value(m), 7049.2478976; atol=1e-3) + @test isapprox(JuMP.objective_value(m), 7049.2478976; atol = 1e-3) @test length(alpine.candidate_disc_vars) == 8 @test length(alpine.disc_vars) == 8 @test MOI.get(m, MOI.RawOptimizerAttribute("disc_var_pick")) == 3 @@ -99,15 +110,17 @@ end @testset "Partitioning variable selection tests :: castro2m2" begin # Select all NL variable - test_solver = optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "disc_var_pick" => 0, - "disc_uniform_rate" => 10, - "presolve_bp" => false, - "presolve_bt" => false, - "max_iter" => 1, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "disc_var_pick" => 0, + "disc_uniform_rate" => 10, + "presolve_bp" => false, + "presolve_bt" => false, + "max_iter" => 1, + "log_level" => 100, + ) m = castro2m2(solver = test_solver) JuMP.optimize!(m) @@ -121,15 +134,17 @@ end @test MOI.get(m, MOI.RawOptimizerAttribute("disc_var_pick")) == 0 # Select minimum vertex cover - test_solver = optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "disc_var_pick" => 1, - "disc_uniform_rate" => 10, - "presolve_bp" => false, - "presolve_bt" => false, - "max_iter" => 1, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "disc_var_pick" => 1, + "disc_uniform_rate" => 10, + "presolve_bp" => false, + "presolve_bt" => false, + "max_iter" => 1, + "log_level" => 100, + ) m = castro2m2(solver = test_solver) JuMP.optimize!(m) @@ -142,15 +157,17 @@ end @test MOI.get(m, MOI.RawOptimizerAttribute("disc_var_pick")) == 1 # Criteria 15 static selection - test_solver = optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "disc_var_pick" => 2, - "disc_uniform_rate" => 15, - "presolve_bp" => false, - "presolve_bt" => false, - "max_iter" => 1, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "disc_var_pick" => 2, + "disc_uniform_rate" => 15, + "presolve_bp" => false, + "presolve_bt" => false, + "max_iter" => 1, + "log_level" => 100, + ) m = castro2m2(solver = test_solver) JuMP.optimize!(m) @@ -167,55 +184,115 @@ end @testset "Partitioning variable selection tests :: blend029" begin # Select all NL variable - test_solver = optimizer_with_attributes(Alpine.Optimizer, - "minlp_solver" => PAVITO, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "disc_var_pick" => 0, - "disc_uniform_rate" => 10, - "presolve_bt" => false, - "max_iter" => 1, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "minlp_solver" => PAVITO, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "disc_var_pick" => 0, + "disc_uniform_rate" => 10, + "presolve_bt" => false, + "max_iter" => 1, + "log_level" => 100, + ) m = blend029_gl(solver = test_solver) alpine = _build(m) @test length(alpine.candidate_disc_vars) == 26 - @test Set(alpine.candidate_disc_vars) == Set([26, 27, 29, 30, 32, 33, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 55, 56, 57, 58, 59, 60]) + @test Set(alpine.candidate_disc_vars) == Set([ + 26, + 27, + 29, + 30, + 32, + 33, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 55, + 56, + 57, + 58, + 59, + 60, + ]) @test length(alpine.disc_vars) == 26 @test MOI.get(m, MOI.RawOptimizerAttribute("disc_var_pick")) == 0 # Minimum vertex cover - test_solver = optimizer_with_attributes(Alpine.Optimizer, - "minlp_solver" => PAVITO, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "disc_var_pick" => 1, - "disc_uniform_rate" => 10, - "presolve_bp" => false, - "presolve_bt" => false, - "max_iter" => 1, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "minlp_solver" => PAVITO, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "disc_var_pick" => 1, + "disc_uniform_rate" => 10, + "presolve_bp" => false, + "presolve_bt" => false, + "max_iter" => 1, + "log_level" => 100, + ) m = blend029_gl(solver = test_solver) alpine = _build(m) @test length(alpine.candidate_disc_vars) == 26 - @test Set(alpine.candidate_disc_vars) == Set([26, 27, 29, 30, 32, 33, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 55, 56, 57, 58, 59, 60]) + @test Set(alpine.candidate_disc_vars) == Set([ + 26, + 27, + 29, + 30, + 32, + 33, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 55, + 56, + 57, + 58, + 59, + 60, + ]) @test length(alpine.disc_vars) == 10 @test MOI.get(m, MOI.RawOptimizerAttribute("disc_var_pick")) == 1 # Adaptive Scheme vertex cover - test_solver = optimizer_with_attributes(Alpine.Optimizer, - "minlp_solver" => PAVITO, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "disc_var_pick" => 2, - "disc_uniform_rate" => 10, - "presolve_bp" => false, - "presolve_bt" => false, - "max_iter" => 1, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "minlp_solver" => PAVITO, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "disc_var_pick" => 2, + "disc_uniform_rate" => 10, + "presolve_bp" => false, + "presolve_bt" => false, + "max_iter" => 1, + "log_level" => 100, + ) m = blend029_gl(solver = test_solver) alpine = _build(m) @@ -230,14 +307,16 @@ end @testset "Partitioning variable selection tests :: castro6m2" begin # Dynamic Scheme step 2 - test_solver = optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "disc_var_pick" => 3, - "presolve_bp" => true, - "presolve_bt" => false, - "max_iter" => 1, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "disc_var_pick" => 3, + "presolve_bp" => true, + "presolve_bt" => false, + "max_iter" => 1, + "log_level" => 100, + ) m = castro6m2(solver = test_solver) JuMP.optimize!(m) @@ -253,14 +332,16 @@ end @test MOI.get(m, MOI.RawOptimizerAttribute("disc_var_pick")) == 3 # Dynamic Scheme step 2 - test_solver = optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "disc_var_pick" => 3, - "presolve_bp" => true, - "presolve_bt" => false, - "max_iter" => 2, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "disc_var_pick" => 3, + "presolve_bp" => true, + "presolve_bt" => false, + "max_iter" => 2, + "log_level" => 100, + ) m = castro6m2(solver = test_solver) JuMP.optimize!(m) @@ -277,15 +358,17 @@ end end @testset "Test getsolvetime for time tracking" begin - test_solver = optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "disc_var_pick" => 0, - "disc_uniform_rate" => 10, - "presolve_bp" => false, - "presolve_bt" => false, - "max_iter" => 1, - "log_level" => 100) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "disc_var_pick" => 0, + "disc_uniform_rate" => 10, + "presolve_bp" => false, + "presolve_bt" => false, + "max_iter" => 1, + "log_level" => 100, + ) m = castro2m2(solver = test_solver) JuMP.optimize!(m) @@ -293,10 +376,12 @@ end end @testset "Hessians disabled with user-defined multivariate functions" begin - test_solver = JuMP.optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "log_level" => 100) + test_solver = JuMP.optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "log_level" => 100, + ) m = Model(test_solver) my_f(x, y) = (x - 1)^2 + (y - 2)^2 JuMP.register(m, :my_f, 2, my_f, autodiff = true) diff --git a/test/test_utility.jl b/test/test_utility.jl index 2c73e251..0650bcd7 100644 --- a/test/test_utility.jl +++ b/test/test_utility.jl @@ -1,13 +1,14 @@ @testset "Utility Function Tests: Solver identifier fetch" begin - - test_solver=optimizer_with_attributes(Alpine.Optimizer, - "minlp_solver" => PAVITO, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "presolve_bp" => true, - "disc_var_pick" => 1, - "log_level" => 100, - "max_iter" => 2) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "minlp_solver" => PAVITO, + "nlp_solver" => IPOPT, + "mip_solver" => CBC, + "presolve_bp" => true, + "disc_var_pick" => 1, + "log_level" => 100, + "max_iter" => 2, + ) m = blend029_gl(solver = test_solver) @@ -17,79 +18,146 @@ # @test termination_status(m) == MOI.OTHER_LIMIT # @test alpine.logs[:n_iter] == 2 - Alpine.fetch_mip_solver_identifier(alpine;override="Pajarito.PajaritoSolver(0, Inf, 1.0e-5, false, Cbc.CbcMathProgSolverInterface.CbcSolver(Any[(:log_level, 0)]), Pajarito.UnsetSolver(), 0, false, true, Ipopt.IpoptSolver(Any[(:print_level, 0)]), true, true, false, false, true, false, false, true, false, true, true, true, true, false, true, 2.0, false, false, false, true, 1.0e-12, 1.0e-6, false, \"\")") + Alpine.fetch_mip_solver_identifier( + alpine; + override = "Pajarito.PajaritoSolver(0, Inf, 1.0e-5, false, Cbc.CbcMathProgSolverInterface.CbcSolver(Any[(:log_level, 0)]), Pajarito.UnsetSolver(), 0, false, true, Ipopt.IpoptSolver(Any[(:print_level, 0)]), true, true, false, false, true, false, false, true, false, true, true, true, true, false, true, 2.0, false, false, false, true, 1.0e-12, 1.0e-6, false, \"\")", + ) @test alpine.mip_solver_id == "Pajarito" - Alpine.fetch_mip_solver_identifier(alpine;override="Gurobi.GurobiSolver(nothing, Any[])") + Alpine.fetch_mip_solver_identifier( + alpine; + override = "Gurobi.GurobiSolver(nothing, Any[])", + ) @test alpine.mip_solver_id == "Gurobi" - Alpine.fetch_mip_solver_identifier(alpine;override="CPLEX.CplexSolver(Any[])") + Alpine.fetch_mip_solver_identifier(alpine; override = "CPLEX.CplexSolver(Any[])") @test alpine.mip_solver_id == "Cplex" - Alpine.fetch_mip_solver_identifier(alpine;override="Cbc.CbcMathProgSolverInterface.CbcSolver(Any[])") + Alpine.fetch_mip_solver_identifier( + alpine; + override = "Cbc.CbcMathProgSolverInterface.CbcSolver(Any[])", + ) @test alpine.mip_solver_id == "Cbc" - Alpine.fetch_mip_solver_identifier(alpine;override="GLPKMathProgInterface.GLPKInterfaceMIP.GLPKSolverMIP(false, Any[])") + Alpine.fetch_mip_solver_identifier( + alpine; + override = "GLPKMathProgInterface.GLPKInterfaceMIP.GLPKSolverMIP(false, Any[])", + ) @test alpine.mip_solver_id == "GLPK" - Alpine.fetch_mip_solver_identifier(alpine;override="Xpress.Optimizer") + Alpine.fetch_mip_solver_identifier(alpine; override = "Xpress.Optimizer") @test alpine.mip_solver_id == "Xpress" - Alpine.fetch_nlp_solver_identifier(alpine;override="Pajarito.PajaritoSolver(0, Inf, 1.0e-5, false, Cbc.CbcMathProgSolverInterface.CbcSolver(Any[(:log_level, 0)]), Pajarito.UnsetSolver(), 0, false, true, Ipopt.IpoptSolver(Any[(:print_level, 0)]), true, true, false, false, true, false, false, true, false, true, true, true, true, false, true, 2.0, false, false, false, true, 1.0e-12, 1.0e-6, false, \"\")") + Alpine.fetch_nlp_solver_identifier( + alpine; + override = "Pajarito.PajaritoSolver(0, Inf, 1.0e-5, false, Cbc.CbcMathProgSolverInterface.CbcSolver(Any[(:log_level, 0)]), Pajarito.UnsetSolver(), 0, false, true, Ipopt.IpoptSolver(Any[(:print_level, 0)]), true, true, false, false, true, false, false, true, false, true, true, true, true, false, true, 2.0, false, false, false, true, 1.0e-12, 1.0e-6, false, \"\")", + ) @test alpine.nlp_solver_id == "Pajarito" - Alpine.fetch_nlp_solver_identifier(alpine;override="Ipopt.IpoptSolver(Any[])") + Alpine.fetch_nlp_solver_identifier(alpine; override = "Ipopt.IpoptSolver(Any[])") @test alpine.nlp_solver_id == "Ipopt" - Alpine.fetch_nlp_solver_identifier(alpine;override="AmplNLWriter.AmplNLSolver(\"bonmin\", String[], \"\")") + Alpine.fetch_nlp_solver_identifier( + alpine; + override = "AmplNLWriter.AmplNLSolver(\"bonmin\", String[], \"\")", + ) @test alpine.nlp_solver_id == "Bonmin" - Alpine.fetch_nlp_solver_identifier(alpine;override="KNITRO.KnitroSolver(Any[])") + Alpine.fetch_nlp_solver_identifier(alpine; override = "KNITRO.KnitroSolver(Any[])") @test alpine.nlp_solver_id == "Knitro" - Alpine.fetch_minlp_solver_identifier(alpine;override="Pajarito.PajaritoSolver(0, Inf, 1.0e-5, false, Cbc.CbcMathProgSolverInterface.CbcSolver(Any[(:log_level, 0)]), Pajarito.UnsetSolver(), 0, false, true, Ipopt.IpoptSolver(Any[(:print_level, 0)]), true, true, false, false, true, false, false, true, false, true, true, true, true, false, true, 2.0, false, false, false, true, 1.0e-12, 1.0e-6, false, \"\")") + Alpine.fetch_minlp_solver_identifier( + alpine; + override = "Pajarito.PajaritoSolver(0, Inf, 1.0e-5, false, Cbc.CbcMathProgSolverInterface.CbcSolver(Any[(:log_level, 0)]), Pajarito.UnsetSolver(), 0, false, true, Ipopt.IpoptSolver(Any[(:print_level, 0)]), true, true, false, false, true, false, false, true, false, true, true, true, true, false, true, 2.0, false, false, false, true, 1.0e-12, 1.0e-6, false, \"\")", + ) @test alpine.minlp_solver_id == "Pajarito" - Alpine.fetch_minlp_solver_identifier(alpine;override="AmplNLWriter.AmplNLSolver(\"bonmin\", String[], \"\")") + Alpine.fetch_minlp_solver_identifier( + alpine; + override = "AmplNLWriter.AmplNLSolver(\"bonmin\", String[], \"\")", + ) @test alpine.minlp_solver_id == "Bonmin" - Alpine.fetch_minlp_solver_identifier(alpine;override="KNITRO.KnitroSolver(Any[])") + Alpine.fetch_minlp_solver_identifier(alpine; override = "KNITRO.KnitroSolver(Any[])") @test alpine.minlp_solver_id == "Knitro" - end @testset "Solver Funtion Tests :: Embedding" begin ebdmap = Alpine.embedding_map(5) @test ebdmap[:L] == 2 @test ebdmap[:H] == [[0, 0], [0, 1], [1, 1], [1, 0]] - @test ebdmap[1] == Set([4,5]) + @test ebdmap[1] == Set([4, 5]) @test ebdmap[2] == Set([3]) - @test ebdmap[3] == Set([2,1]) - @test ebdmap[4] == Set([5,1]) + @test ebdmap[3] == Set([2, 1]) + @test ebdmap[4] == Set([5, 1]) ebdmap = Alpine.embedding_map(9) @test ebdmap[:L] == 3 @test ebdmap[:H_orig] == ["000", "001", "011", "010", "110", "111", "101", "100"] - @test ebdmap[:H] == [[0, 0, 0], [0, 0, 1], [0, 1, 1], [0, 1, 0], [1, 1, 0], [1, 1, 1], [1, 0, 1], [1, 0, 0]] - @test ebdmap[1] == Set([7,9,8,6]) - @test ebdmap[2] == Set([4,5,6]) - @test ebdmap[3] == Set([7,3]) - @test ebdmap[4] == Set([4,3,2,1]) - @test ebdmap[5] == Set([9,2,8,1]) - @test ebdmap[6] == Set([9,5,1]) + @test ebdmap[:H] == [ + [0, 0, 0], + [0, 0, 1], + [0, 1, 1], + [0, 1, 0], + [1, 1, 0], + [1, 1, 1], + [1, 0, 1], + [1, 0, 0], + ] + @test ebdmap[1] == Set([7, 9, 8, 6]) + @test ebdmap[2] == Set([4, 5, 6]) + @test ebdmap[3] == Set([7, 3]) + @test ebdmap[4] == Set([4, 3, 2, 1]) + @test ebdmap[5] == Set([9, 2, 8, 1]) + @test ebdmap[6] == Set([9, 5, 1]) ebdmap = Alpine.embedding_map(12) @test ebdmap[:L] == 4 - @test ebdmap[:H_orig] == ["0000", "0001", "0011", "0010", "0110", "0111", "0101", "0100", "1100", "1101", "1111", "1110", "1010", "1011", "1001", "1000"] - @test ebdmap[:H] == [[0, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 1], [0, 0, 1, 0], [0, 1, 1, 0], [0, 1, 1, 1], [0, 1, 0, 1], [0, 1, 0, 0], [1, 1, 0, 0], [1, 1, 0, 1], [1, 1, 1, 1], [1, 1, 1, 0], [1, 0, 1, 0], [1, 0, 1, 1], [1, 0, 0, 1], [1, 0, 0, 0]] - @test ebdmap[1] == Set([10,11,12]) - @test ebdmap[2] == Set([7,9,10,11,8,6,12]) - @test ebdmap[3] == Set([4,5,6,12]) - @test ebdmap[4] == Set([7,3,11,12]) - @test ebdmap[5] == Set([7,4,2,3,5,8,6,1]) - @test ebdmap[6] == Set([4,2,3,1]) - @test ebdmap[7] == Set([9,10,2,8,1]) - @test ebdmap[8] == Set([9,5,1]) + @test ebdmap[:H_orig] == [ + "0000", + "0001", + "0011", + "0010", + "0110", + "0111", + "0101", + "0100", + "1100", + "1101", + "1111", + "1110", + "1010", + "1011", + "1001", + "1000", + ] + @test ebdmap[:H] == [ + [0, 0, 0, 0], + [0, 0, 0, 1], + [0, 0, 1, 1], + [0, 0, 1, 0], + [0, 1, 1, 0], + [0, 1, 1, 1], + [0, 1, 0, 1], + [0, 1, 0, 0], + [1, 1, 0, 0], + [1, 1, 0, 1], + [1, 1, 1, 1], + [1, 1, 1, 0], + [1, 0, 1, 0], + [1, 0, 1, 1], + [1, 0, 0, 1], + [1, 0, 0, 0], + ] + @test ebdmap[1] == Set([10, 11, 12]) + @test ebdmap[2] == Set([7, 9, 10, 11, 8, 6, 12]) + @test ebdmap[3] == Set([4, 5, 6, 12]) + @test ebdmap[4] == Set([7, 3, 11, 12]) + @test ebdmap[5] == Set([7, 4, 2, 3, 5, 8, 6, 1]) + @test ebdmap[6] == Set([4, 2, 3, 1]) + @test ebdmap[7] == Set([9, 10, 2, 8, 1]) + @test ebdmap[8] == Set([9, 5, 1]) end @testset "Utility Function Tests: check_solution_history test" begin - - test_solver=optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => PAVITO, - "presolve_bt" => false, - "disc_ratio" => 5, - "disc_consecutive_forbid" => false) + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => PAVITO, + "presolve_bt" => false, + "disc_ratio" => 5, + "disc_consecutive_forbid" => false, + ) m1 = circle(solver = test_solver) JuMP.optimize!(m1) @@ -97,13 +165,15 @@ end Alpine.variable_values(m1) - test_solver=optimizer_with_attributes(Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => PAVITO, - "presolve_bt" => false, - "disc_ratio" => 5, - "disc_consecutive_forbid" => true) - + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => PAVITO, + "presolve_bt" => false, + "disc_ratio" => 5, + "disc_consecutive_forbid" => true, + ) + m2 = circle(solver = test_solver) JuMP.optimize!(m2) alpine2 = JuMP.backend(m2).optimizer.model @@ -112,5 +182,4 @@ end @test termination_status(m2) == MOI.OPTIMAL @test alpine1.logs[:n_iter] > alpine2.logs[:n_iter] @test isapprox(JuMP.objective_value(m1), JuMP.objective_value(m2), atol = 1E-6) - end From 6bf60081e4c9eb58687f5cc2fd22d635c47c3bc5 Mon Sep 17 00:00:00 2001 From: harshangrjn Date: Tue, 23 Aug 2022 15:19:18 -0600 Subject: [PATCH 06/18] changelog update --- CHANGELOG.md | 3 ++- Project.toml | 2 +- src/Alpine.jl | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5cd22b71..1c58f298 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,9 @@ # Alpine.jl Change Log -## Staged +## v0.5.0 - New feature: Linking constraints for multilinear terms with uniform and adaptive partitions (speed up in run times for multilinear termed problems) - Added dependency on Combinatorics package for linking constraints +- Added JuliaFormatter.toml and formatting workfow ## v0.4.2 - Fix support for JuMP v1.2 (@odow) diff --git a/Project.toml b/Project.toml index b89cea1a..e9fc3187 100644 --- a/Project.toml +++ b/Project.toml @@ -2,7 +2,7 @@ name = "Alpine" uuid = "07493b3f-dabb-5b16-a503-4139292d7dd4" authors = ["Harsha Nagarajan, Site Wang, Kaarthik Sundar and contributors"] repo = "https://github.com/lanl-ansi/Alpine.jl.git" -version = "0.4.2" +version = "0.5.0" [deps] Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa" diff --git a/src/Alpine.jl b/src/Alpine.jl index 2d6c656c..58cc8740 100644 --- a/src/Alpine.jl +++ b/src/Alpine.jl @@ -8,7 +8,7 @@ import LinearAlgebra: dot, Diagonal import Statistics import Combinatorics -const _ALPINE_VERSION = "v0.4.2" +const _ALPINE_VERSION = "v0.5.0" const ALPINE_DEBUG = false const Alp = Alpine From 25977b967e358cf46a7abedb9d0d39820f56ff63 Mon Sep 17 00:00:00 2001 From: harshangrjn Date: Thu, 25 Aug 2022 10:14:50 -0600 Subject: [PATCH 07/18] format check indentation --- .github/workflows/format_check.yml | 61 +++++++++++++++--------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/.github/workflows/format_check.yml b/.github/workflows/format_check.yml index 8509ce45..695abe5b 100644 --- a/.github/workflows/format_check.yml +++ b/.github/workflows/format_check.yml @@ -1,31 +1,32 @@ name: format-check - on: - push: - branches: - - master - - release-* - pull_request: - types: [opened, synchronize, reopened] - jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: julia-actions/setup-julia@latest - with: - version: '1' - - uses: actions/checkout@v1 - - name: Format check - shell: julia --color=yes {0} - run: | - using Pkg - Pkg.add(PackageSpec(name="JuliaFormatter", version="1")) - using JuliaFormatter - format("src/MOI_wrapper", verbose=true) - format("test", verbose=true) - out = String(read(Cmd(`git diff`))) - if isempty(out) - exit(0) - end - @error "Some files have not been formatted !!!" - write(stdout, out) - exit(1) \ No newline at end of file +on: + push: + branches: + - master + - release-* + pull_request: + types: [opened, synchronize, reopened] +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: julia-actions/setup-julia@latest + with: + version: '1' + - uses: actions/checkout@v1 + - name: Format check + shell: julia --color=yes {0} + run: | + using Pkg + Pkg.add(PackageSpec(name="JuliaFormatter", version="1")) + using JuliaFormatter + format("src/MOI_wrapper", verbose=true) + format("test", verbose=true) + format("docs", verbose=true) + out = String(read(Cmd(`git diff`))) + if isempty(out) + exit(0) + end + @error "Some files have not been formatted !!!" + write(stdout, out) + exit(1) \ No newline at end of file From 67ba41618adcad5c7a97e0f29dd2f4c3d112c082 Mon Sep 17 00:00:00 2001 From: harshangrjn Date: Sun, 28 Aug 2022 23:10:01 -0600 Subject: [PATCH 08/18] rebasing to v0.4.3 --- examples/optimizers.jl | 10 ++++++---- examples/run_examples.jl | 2 +- src/MOI_wrapper/MOI_wrapper.jl | 6 +++--- src/algorithm.jl | 5 ++--- src/amp.jl | 3 +-- src/embedding.jl | 9 +++------ src/log.jl | 3 +-- src/utility.jl | 6 +++--- test/test_utility.jl | 9 ++++++--- 9 files changed, 26 insertions(+), 27 deletions(-) diff --git a/examples/optimizers.jl b/examples/optimizers.jl index 1b43e1f2..37aea85b 100644 --- a/examples/optimizers.jl +++ b/examples/optimizers.jl @@ -1,9 +1,11 @@ # MIP solver - commercial function get_gurobi() - GRB_ENV = Gurobi.Env() - return optimizer_with_attributes(() -> Gurobi.Optimizer(GRB_ENV), # To avoid printing License info multiple times - MOI.Silent() => true, - "Presolve" => 1) + GRB_ENV = Gurobi.Env() + return optimizer_with_attributes( + () -> Gurobi.Optimizer(GRB_ENV), # To avoid printing License info multiple times + MOI.Silent() => true, + "Presolve" => 1, + ) end function get_cplex() diff --git a/examples/run_examples.jl b/examples/run_examples.jl index 4d69e475..093247b8 100644 --- a/examples/run_examples.jl +++ b/examples/run_examples.jl @@ -30,7 +30,7 @@ juniper = get_juniper(gurobi, ipopt) const alpine = JuMP.optimizer_with_attributes( Alpine.Optimizer, - "minlp_solver" => juniper, + # "minlp_solver" => juniper, "nlp_solver" => ipopt, "mip_solver" => gurobi, "presolve_bt" => true, diff --git a/src/MOI_wrapper/MOI_wrapper.jl b/src/MOI_wrapper/MOI_wrapper.jl index 98b414c3..88de75e7 100644 --- a/src/MOI_wrapper/MOI_wrapper.jl +++ b/src/MOI_wrapper/MOI_wrapper.jl @@ -10,9 +10,9 @@ mutable struct Optimizer <: MOI.AbstractOptimizer options::OptimizerOptions # Options set by user # Sub-solver identifier for customized solver option - nlp_solver_id :: String # NLP Solver identifier string - minlp_solver_id :: String # MINLP local solver identifier string - mip_solver_id :: String # MIP solver identifier string + nlp_solver_id::String # NLP Solver identifier string + minlp_solver_id::String # MINLP local solver identifier string + mip_solver_id::String # MIP solver identifier string # User inputs num_var_orig::Int # Initial number of variables diff --git a/src/algorithm.jl b/src/algorithm.jl index b022d37f..2e33957b 100644 --- a/src/algorithm.jl +++ b/src/algorithm.jl @@ -23,7 +23,7 @@ function features_available(m::Optimizer) end function load!(m::Optimizer) - + # Initialize NLP interface requested_features = Alp.features_available(m) if m.d_orig !== nothing @@ -502,8 +502,7 @@ function bounding_solve(m::Optimizer) (status == MOI.OPTIMAL) ? JuMP.objective_value(m.model_mip) : JuMP.objective_bound(m.model_mip) candidate_bound_sol = [ - round.(JuMP.value(_index_to_variable_ref(m.model_mip, i)); digits = 7) - for + round.(JuMP.value(_index_to_variable_ref(m.model_mip, i)); digits = 7) for i in 1:(m.num_var_orig+m.num_var_linear_mip+m.num_var_nonlinear_mip) ] diff --git a/src/amp.jl b/src/amp.jl index 3b02367b..2e5a455a 100644 --- a/src/amp.jl +++ b/src/amp.jl @@ -153,8 +153,7 @@ function amp_post_affine_constraint(model_mip::JuMP.Model, affine::Dict) end function amp_post_convex_constraint(model_mip::JuMP.Model, convex::Dict) - !prod([i == 2 for i in convex[:powers]]) && - error("No relaxation implementation for convex constraints $(convex[:expr])") + !prod([i == 2 for i in convex[:powers]]) && error("No relaxation implementation for convex constraints $(convex[:expr])") if convex[:sense] == :(<=) JuMP.@constraint( diff --git a/src/embedding.jl b/src/embedding.jl index 3fe0e79c..9edccc96 100644 --- a/src/embedding.jl +++ b/src/embedding.jl @@ -26,10 +26,8 @@ function embedding_map(λCnt::Int, encoding::Any = ebd_gray, ibs::Bool = false) L_constr = Set() R_constr = Set() for j in 0:2^L - prod([(l in ebd_σ(H[i])) for i in ebd_I(j, 2^L + 1)]) && - push!(L_constr, j + 1) - prod([!(l in ebd_σ(H[i])) for i in ebd_I(j, 2^L + 1)]) && - push!(R_constr, j + 1) + prod([(l in ebd_σ(H[i])) for i in ebd_I(j, 2^L + 1)]) && push!(L_constr, j + 1) + prod([!(l in ebd_σ(H[i])) for i in ebd_I(j, 2^L + 1)]) && push!(R_constr, j + 1) end L_branch = intersect(J_s, setdiff(J, L_constr)) R_branch = intersect(J_s, setdiff(J, R_constr)) @@ -38,8 +36,7 @@ function embedding_map(λCnt::Int, encoding::Any = ebd_gray, ibs::Bool = false) else for j in 0:(λCnt-1) prod([(l in ebd_σ(H[i])) for i in ebd_I(j, λCnt)]) && push!(map[l], j + 1) - prod([!(l in ebd_σ(H[i])) for i in ebd_I(j, λCnt)]) && - push!(map[l+L], j + 1) + prod([!(l in ebd_σ(H[i])) for i in ebd_I(j, λCnt)]) && push!(map[l+L], j + 1) end end end diff --git a/src/log.jl b/src/log.jl index f7a68df0..d7962bca 100644 --- a/src/log.jl +++ b/src/log.jl @@ -40,8 +40,7 @@ function logging_summary(m::Optimizer) ) println( " # Bin-Int Variables = ", - length([i for i in 1:m.num_var_orig if m.var_type[i] == :Bin]) + - length([i for i in 1:m.num_var_orig if m.var_type[i] == :Int]), + length([i for i in 1:m.num_var_orig if m.var_type[i] == :Bin]) + length([i for i in 1:m.num_var_orig if m.var_type[i] == :Int]), ) println(" # Constraints = ", m.num_constr_orig) println(" # NL Constraints = ", m.num_nlconstr_orig) diff --git a/src/utility.jl b/src/utility.jl index db225113..ddfc7f9f 100644 --- a/src/utility.jl +++ b/src/utility.jl @@ -481,19 +481,19 @@ function round_sol(m::Optimizer, relaxed_sol) return rounded_sol end -function _fetch_mip_solver_identifier(m::Optimizer; override="") +function _fetch_mip_solver_identifier(m::Optimizer; override = "") (Alp.get_option(m, :mip_solver) === nothing) && return m.mip_solver_id = _get_solver_name(m, :mip_solver, override) return end -function _fetch_nlp_solver_identifier(m::Optimizer; override="") +function _fetch_nlp_solver_identifier(m::Optimizer; override = "") (Alp.get_option(m, :nlp_solver) === nothing) && return m.nlp_solver_id = _get_solver_name(m, :nlp_solver, override) return end -function _fetch_minlp_solver_identifier(m::Optimizer; override="") +function _fetch_minlp_solver_identifier(m::Optimizer; override = "") (Alp.get_option(m, :minlp_solver) === nothing) && return m.minlp_solver_id = _get_solver_name(m, :minlp_solver, override) return diff --git a/test/test_utility.jl b/test/test_utility.jl index 3f758c06..9c5df83b 100644 --- a/test/test_utility.jl +++ b/test/test_utility.jl @@ -13,11 +13,14 @@ m = blend029_gl(solver = test_solver) alpine = JuMP.backend(m).optimizer.model - Alpine._fetch_mip_solver_identifier(alpine;override="Gurobi.GurobiSolver(nothing, Any[])") + Alpine._fetch_mip_solver_identifier( + alpine; + override = "Gurobi.GurobiSolver(nothing, Any[])", + ) @test alpine.mip_solver_id == "Gurobi" - Alpine._fetch_mip_solver_identifier(alpine;override="CPLEX.CplexSolver(Any[])") + Alpine._fetch_mip_solver_identifier(alpine; override = "CPLEX.CplexSolver(Any[])") @test alpine.mip_solver_id == "CPLEX" - Alpine._fetch_nlp_solver_identifier(alpine;override="Ipopt.IpoptSolver(Any[])") + Alpine._fetch_nlp_solver_identifier(alpine; override = "Ipopt.IpoptSolver(Any[])") @test alpine.nlp_solver_id == "Ipopt" end From c05d18e6f3a675d9d35e5b891587f3be2c0f6aae Mon Sep 17 00:00:00 2001 From: harshangrjn Date: Tue, 30 Aug 2022 19:58:25 -0600 Subject: [PATCH 09/18] Cbc -> HiGHS --- CHANGELOG.md | 4 +- Project.toml | 6 +- README.md | 2 +- docs/src/index.md | 29 +++++++- examples/MINLPs/circle.jl | 5 +- examples/MINLPs/linearlift.jl | 15 +---- examples/MINLPs/nlp.jl | 40 ++--------- examples/Project.toml | 2 +- examples/README.md | 10 +++ examples/optimizers.jl | 35 ++++++++-- examples/run_examples.jl | 15 ++--- src/multi.jl | 4 +- src/solver.jl | 4 +- test/runtests.jl | 14 ++-- test/test_algorithm.jl | 122 ++++++++++++++-------------------- test/test_expression.jl | 46 ++++++------- test/test_solver.jl | 85 ++++++----------------- test/test_utility.jl | 2 +- 18 files changed, 196 insertions(+), 244 deletions(-) create mode 100644 examples/README.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 432d9116..4a5995e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,10 @@ # Alpine.jl Change Log ## v0.5.0 -- New feature: Linking constraints for multilinear terms with uniform and adaptive partitions (speed up in run times for multilinear termed problems) +- New feature: Linking constraints for multilinear terms with uniform and adaptive partitions (speed up in run times for multilinear problems) (@jongeunkim) - Added dependency on Combinatorics package for linking constraints +- Changed Cbc test dependency to HiGHS solver +- Dropped a few redundant unit tests - Added JuliaFormatter.toml and formatting workfow ## v0.4.3 diff --git a/Project.toml b/Project.toml index e9fc3187..3790ca3a 100644 --- a/Project.toml +++ b/Project.toml @@ -12,7 +12,7 @@ MathOptInterface = "b8f27783-ece8-5eb3-8dc8-9495eed66fee" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" [compat] -Cbc = "0.8, 0.9, 1" +HiGHS = "1" Ipopt = "0.8, 0.9, 1" JuMP = "0.22, 0.23, 1" Juniper = "0.8, 0.9" @@ -22,7 +22,7 @@ julia = "1" Combinatorics = "1" [extras] -Cbc = "9961bab8-2fa3-5c5a-9d89-47fab24efd76" +HiGHS = "87dc4568-4c63-4d18-b0c0-bb2238e4078b" Ipopt = "b6b21f68-93f8-5de0-b562-5493be1d77c9" Juniper = "2ddba703-00a4-53a7-87a5-e8b9971dde84" Pavito = "cd433a01-47d1-575d-afb7-6db927ee8d8f" @@ -30,4 +30,4 @@ Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] -test = ["Cbc", "Ipopt", "Juniper", "Pavito", "Random", "Test"] +test = ["HiGHS", "Ipopt", "Juniper", "Pavito", "Random", "Test"] diff --git a/README.md b/README.md index 8ccc4da9..b36a38be 100644 --- a/README.md +++ b/README.md @@ -63,8 +63,8 @@ We are seeking out hard benchmark instances for MINLPs. Please get in touch eith If you find Alpine useful in your work, we kindly request that you cite the following papers ([pdf](http://harshangrjn.github.io/pdf/JOGO_2018.pdf), [pdf](http://harshangrjn.github.io/pdf/CP_2016.pdf)) ```bibtex @article{alpine_JOGO2019, - author = {Nagarajan, Harsha and Lu, Mowen and Wang, Site and Bent, Russell and Sundar, Kaarthik}, title = {An adaptive, multivariate partitioning algorithm for global optimization of nonconvex programs}, + author = {Nagarajan, Harsha and Lu, Mowen and Wang, Site and Bent, Russell and Sundar, Kaarthik}, journal = {Journal of Global Optimization}, year = {2019}, issn = {1573-2916}, diff --git a/docs/src/index.md b/docs/src/index.md index b3a7b20b..d023047b 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -20,7 +20,7 @@ import Pkg Pkg.add("Alpine") ``` -At least one local nonlinear-programming (NLP) solver and a convex mixed-integer programming (MIP) solver are required for running Alpine. If your problem is an NLP, we recommend [Ipopt](https://github.com/jump-dev/Ipopt.jl), and else if your problem is a mixed-integer NLP (MINLP), we recommend [Juniper](https://github.com/lanl-ansi/Juniper.jl). For the underlying MIP solver, [Gurobi](https://github.com/jump-dev/Gurobi.jl) is highly recommended, as it is fast, scaleable and can be used to solve on fairly large-scale non-convex programs. However, the open-source [CBC](https://github.com/jump-dev/Cbc.jl) or [GLPK](https://github.com/jump-dev/GLPK.jl) solver is also compatible with Alpine. For example, Ipopt and GLPK can be installed via the package manager with +At least one local nonlinear-programming (NLP) solver and a convex mixed-integer programming (MIP) solver are required for running Alpine. If your problem is an NLP, we recommend [Ipopt](https://github.com/jump-dev/Ipopt.jl), and else if your problem is a mixed-integer NLP (MINLP), we recommend [Juniper](https://github.com/lanl-ansi/Juniper.jl). For the underlying MIP solver, [Gurobi](https://github.com/jump-dev/Gurobi.jl) is highly recommended, as it is fast, scaleable and can be used to solve on fairly large-scale non-convex programs. However, the open-source [HiGHS](https://github.com/jump-dev/HiGHS.jl) or [GLPK](https://github.com/jump-dev/GLPK.jl) solver is also compatible with Alpine. For example, Ipopt and Gurobi can be installed via the package manager with ```julia import Pkg @@ -38,14 +38,37 @@ Pkg.test("Alpine") ``` ## Citing Alpine -If you find Alpine useful in your work, we request you to cite the following paper [\[link\]](https://harshangrjn.github.io/pdf/JOGO_2018.pdf): +If you find Alpine useful in your work, we request you to cite the following paper [\[pdf\]](https://harshangrjn.github.io/pdf/JOGO_2018.pdf) [\[pdf\]](http://harshangrjn.github.io/pdf/CP_2016.pdf): ```bibtex @article{alpine_JOGO2019, - author = {Nagarajan, Harsha and Lu, Mowen and Wang, Site and Bent, Russell and Sundar, Kaarthik}, title = {An adaptive, multivariate partitioning algorithm for global optimization of nonconvex programs}, + author = {Nagarajan, Harsha and Lu, Mowen and Wang, Site and Bent, Russell and Sundar, Kaarthik}, journal = {Journal of Global Optimization}, year = {2019}, issn = {1573-2916}, doi = {10.1007/s10898-018-00734-1}, } + +@inproceedings{alpine_CP2016, + title = {Tightening {McCormick} relaxations for nonlinear programs via dynamic multivariate partitioning}, + author = {Nagarajan, Harsha and Lu, Mowen and Yamangil, Emre and Bent, Russell}, + booktitle = {International Conference on Principles and Practice of Constraint Programming}, + pages = {369--387}, + year = {2016}, + organization = {Springer}, + doi = {10.1007/978-3-319-44953-1_24}, +} +``` +If you find the underlying piecewise polyhedral formulations implemented in Alpine useful in your work, we kindly request that you cite the following paper [\[link\]](https://doi.org/10.1016/j.orl.2020.12.002): +```bibtex +@article{alpine_ORL2021, + title = {Piecewise polyhedral formulations for a multilinear term}, + author = {Sundar, Kaarthik and Nagarajan, Harsha and Linderoth, Jeff and Wang, Site and Bent, Russell}, + journal = {Operations Research Letters}, + volume = {49}, + number = {1}, + pages = {144--149}, + year = {2021}, + publisher = {Elsevier} +} ``` diff --git a/examples/MINLPs/circle.jl b/examples/MINLPs/circle.jl index f08a1068..f1fedcf1 100644 --- a/examples/MINLPs/circle.jl +++ b/examples/MINLPs/circle.jl @@ -15,9 +15,8 @@ function circle_MINLPLib(; solver = nothing) m = Model(solver) - @variable(m, objvar >= 0) - x_Idx = Any[1, 2] - @variable(m, -10 <= x[x_Idx] <= 10) + @variable(m, 0 <= objvar <= 5) + @variable(m, -10 <= x[1:2] <= 10) @NLconstraint( m, diff --git a/examples/MINLPs/linearlift.jl b/examples/MINLPs/linearlift.jl index bfbbf7e1..02b8b81e 100644 --- a/examples/MINLPs/linearlift.jl +++ b/examples/MINLPs/linearlift.jl @@ -1,18 +1,7 @@ function basic_linear_lift(; verbose = false, solver = nothing) - if solver === nothing - m = Model( - Alpine.Optimizer( - nlp_solver = IpoptSolver(), - mip_solver = CbcSolver(log_level = 0), - log_level = 10000, - ), - ) - else - m = Model(solver) - end + m = Model(solver) @variable(m, x[i = 1:3] >= 1) # At some point if an initial value is given, keep them - @constraint(m, (x[1] - x[2]) * (3 * x[2] - x[3]) >= 111) @NLconstraint(m, (x[1] - x[2]) * (3 * x[2] - x[3]) >= 111) @NLconstraint(m, (x[1] - x[2])^2 >= 100) @@ -24,7 +13,5 @@ function basic_linear_lift(; verbose = false, solver = nothing) @objective(m, Min, x[1] + x[2] + x[3]) - verbose && print(m) - return m end diff --git a/examples/MINLPs/nlp.jl b/examples/MINLPs/nlp.jl index 143eefe2..38d64548 100644 --- a/examples/MINLPs/nlp.jl +++ b/examples/MINLPs/nlp.jl @@ -1,49 +1,17 @@ -function nlp1(; verbose = false, solver = nothing, convhull = false, presolve = 0) - if solver === nothing - m = Model( - Alpine.Optimizer( - nlp_solver = IpoptSolver(print_level = 0), - mip_solver = GurobiSolver(OutputFlag = 0), - bilinear_convexhull = convhull, - monomial_convexhull = convhull, - presolve_bt = (presolve > 0), - presolve_bt_algo = presolve, - presolve_bt_bound_tol = 1e-1, - log_level = 10000, - ), - ) - else - m = Model(solver) - end +function nlp1(; solver = nothing) + m = Model(solver) @variable(m, 1 <= x[1:2] <= 10) - @NLconstraint(m, x[1] * x[2] >= 8) @NLobjective(m, Min, 6 * x[1]^2 + 4 * x[2]^2 - 2.5 * x[1] * x[2]) return m end -function nlp2(; verbose = false, solver = nothing, convhull = false, presolve = 0) - if solver === nothing - m = Model( - Alpine.Optimizer( - nlp_solver = IpoptSolver(print_level = 0), - mip_solver = GurobiSolver(OutputFlag = 0), - bilinear_convexhull = convhull, - monomial_convexhull = convhull, - presolve_bt = (presolve > 0), - presolve_bt_algo = presolve, - presolve_bt_bound_tol = 1e-1, - log_level = 10000, - ), - ) - else - m = Model(solver) - end +function nlp2(; solver = nothing) + m = Model(solver) @variable(m, -500 <= x[1:2] <= 500) - @NLobjective(m, Min, sum((x[i]^2 - i)^2 for i in 1:2)) return m diff --git a/examples/Project.toml b/examples/Project.toml index 9f0127a5..9a080344 100644 --- a/examples/Project.toml +++ b/examples/Project.toml @@ -1,8 +1,8 @@ [deps] Alpine = "07493b3f-dabb-5b16-a503-4139292d7dd4" CPLEX = "a076750e-1247-5638-91d2-ce28b192dca0" -Cbc = "9961bab8-2fa3-5c5a-9d89-47fab24efd76" Gurobi = "2e9cd046-0924-5485-92f1-d5272153d98b" +HiGHS = "87dc4568-4c63-4d18-b0c0-bb2238e4078b" Ipopt = "b6b21f68-93f8-5de0-b562-5493be1d77c9" JuMP = "4076af6c-e467-56ae-b986-b466b2749572" Juniper = "2ddba703-00a4-53a7-87a5-e8b9971dde84" diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 00000000..403a6375 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,10 @@ +# Examples for Alpine +`run_examples.jl` file contains the main driver file which can be executed to compute global optimality for a non-convex MINLP of your choice. Multiple such JuMP models of MINLPs can be found inside the `examples/MINLPs` folder. + +A few useful *hints* to explore within Alpine: +* Try different integer values (>= 4) for `disc_ratio` to potentially observe + better Alpine run times, which can be instance specific. +* Choose `presolve_bt` to `false` if you prefer the optimization-based bound tightening (OBBT) presolve to be turned off. +* If you prefer to use Alpine for only OBBT presolve, without any paritioning applied to the + nonlinear terms, include option `"apply_partitioning"` and set it to `false` while initializing the + Alpine solver. \ No newline at end of file diff --git a/examples/optimizers.jl b/examples/optimizers.jl index 37aea85b..c68d20d3 100644 --- a/examples/optimizers.jl +++ b/examples/optimizers.jl @@ -1,4 +1,7 @@ -# MIP solver - commercial +#---------------------------; +# MIP solvers - commercial ; +#---------------------------; +# https://github.com/jump-dev/Gurobi.jl function get_gurobi() GRB_ENV = Gurobi.Env() return optimizer_with_attributes( @@ -8,6 +11,7 @@ function get_gurobi() ) end +# https://github.com/jump-dev/CPLEX.jl function get_cplex() return optimizer_with_attributes( CPLEX.Optimizer, @@ -16,12 +20,27 @@ function get_cplex() ) end -# MIP solver - open-source +#---------------------------; +# MIP solvers - open-source +#---------------------------; +# https://github.com/jump-dev/HiGHS.jl +function get_highs() + return JuMP.optimizer_with_attributes( + HiGHS.Optimizer, + "presolve" => "on", + "log_to_console" => false, + ) +end + +# https://github.com/jump-dev/Cbc.jl function get_cbc() return optimizer_with_attributes(Cbc.Optimizer, MOI.Silent() => true) end -# Local solver +#---------------------------; +# Continuous local solver ; +#---------------------------; +# https://github.com/jump-dev/Ipopt.jl function get_ipopt() return optimizer_with_attributes( Ipopt.Optimizer, @@ -31,7 +50,10 @@ function get_ipopt() ) end -# Convex MINLP solver +#----------------------; +# Convex MINLP solver ; +#----------------------; +# https://github.com/jump-dev/Pavito.jl function get_pavito(mip_solver, cont_solver) return optimizer_with_attributes( Pavito.Optimizer, @@ -42,7 +64,10 @@ function get_pavito(mip_solver, cont_solver) ) end -# Non-convex Local MINLP solver +#-------------------------------; +# Non-convex Local MINLP solver ; +#-------------------------------; +# https://github.com/lanl-ansi/Juniper.jl function get_juniper(mip_solver, nl_solver) return optimizer_with_attributes( Juniper.Optimizer, diff --git a/examples/run_examples.jl b/examples/run_examples.jl index 093247b8..e4ab487d 100644 --- a/examples/run_examples.jl +++ b/examples/run_examples.jl @@ -7,17 +7,16 @@ using Juniper # - Additional - # # using CPLEX -# using Cbc +# using HiGHS # using Pavito -# using Random include("JuMP_models.jl") include("optimizers.jl") # Choose underlying solvers for Alpine -ipopt = get_ipopt() -gurobi = get_gurobi() -juniper = get_juniper(gurobi, ipopt) +nlp_solver = get_ipopt() #local solver +mip_solver = get_gurobi() +minlp_solver = get_juniper(mip_solver, nlp_solver) #local solver #= Global solver Hints: @@ -30,9 +29,9 @@ juniper = get_juniper(gurobi, ipopt) const alpine = JuMP.optimizer_with_attributes( Alpine.Optimizer, - # "minlp_solver" => juniper, - "nlp_solver" => ipopt, - "mip_solver" => gurobi, + # "minlp_solver" => minlp_solver, + "nlp_solver" => nlp_solver, + "mip_solver" => mip_solver, "presolve_bt" => true, "disc_ratio" => 10, ) diff --git a/src/multi.jl b/src/multi.jl index c0f3b46b..dff5d324 100644 --- a/src/multi.jl +++ b/src/multi.jl @@ -531,7 +531,7 @@ function amp_post_convhull_constrs( end """ - Method for regular multilinear terms (terms that only has continuous variables) + Method for multilinear terms with only continuous variables """ function amp_post_inequalities_cont( m::Optimizer, @@ -631,7 +631,7 @@ function amp_post_inequalities_cont( end return else - error("Must indicate a choice of convex hull formulation. ?(sos2, facet)") + error("Must indicate a choice of convex hull formulation: sos2, facet") end return diff --git a/src/solver.jl b/src/solver.jl index 9c879f9f..30850dce 100644 --- a/src/solver.jl +++ b/src/solver.jl @@ -6,7 +6,7 @@ mutable struct OptimizerOptions # Basic solver parameters log_level::Int # Verbosity flag: 0 for quiet, 1 for basic solve info, 2 for iteration info time_limit::Float64 # Time limit for algorithm (in seconds) - max_iter::Int # Maximum bound on number of iterations for partitioning algorithm + max_iter::Int # Maximum bound on number of iterations for the partitioning algorithm rel_gap::Float64 # Relative optimality gap for termination condition abs_gap::Float64 # Absolute optimality gap for termination condition tol::Float64 # Numerical tol used in algorithms @@ -29,7 +29,7 @@ mutable struct OptimizerOptions # Parameters used in Alpine's MIP-based partitioning algorithm apply_partitioning::Bool # Apply the partitioning algorithm only if thhis true, else terminate after presolve disc_var_pick::Any # Algorithm for choosing the variables to discretize: 1 for minimum vertex cover, 0 for all variables - disc_ratio::Any # Discretization ratio parameter, which is critical for convergence (using a fixed value for now, later switch to a function) + disc_ratio::Int # Discretization ratio parameter, which is critical for convergence (using a fixed value for now, later switch to a function) disc_uniform_rate::Int # Discretization rate parameter when using uniform partitions disc_add_partition_method::Any # Additional methods to add discretization disc_divert_chunks::Int # How many uniform partitions to construct diff --git a/test/runtests.jl b/test/runtests.jl index 987631b3..2464a074 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -2,7 +2,7 @@ using JuMP using Test import Alpine -import Cbc +import HiGHS import Ipopt import Juniper import Pavito @@ -19,17 +19,23 @@ const IPOPT = MOI.OptimizerWithAttributes( "sb" => "yes", "max_iter" => 9999, ) -const CBC = MOI.OptimizerWithAttributes(Cbc.Optimizer, MOI.Silent() => true) + +const HIGHS = MOI.OptimizerWithAttributes( + HiGHS.Optimizer, + "presolve" => "on", + "log_to_console" => false, +) + const JUNIPER = MOI.OptimizerWithAttributes( Juniper.Optimizer, MOI.Silent() => true, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "nl_solver" => IPOPT, ) const PAVITO = MOI.OptimizerWithAttributes( Pavito.Optimizer, MOI.Silent() => true, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "cont_solver" => IPOPT, "mip_solver_drives" => false, ) diff --git a/test/test_algorithm.jl b/test/test_algorithm.jl index 01151a44..7a21e1fb 100644 --- a/test/test_algorithm.jl +++ b/test/test_algorithm.jl @@ -23,7 +23,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "bilinear_convexhull" => false, "monomial_convexhull" => false, "presolve_bp" => true, @@ -47,7 +47,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "bilinear_convexhull" => false, "monomial_convexhull" => false, "presolve_bp" => true, @@ -70,7 +70,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "bilinear_convexhull" => false, "log_level" => 100, "max_iter" => 2, @@ -93,10 +93,10 @@ end @test MOI.get(m, Alpine.NumberOfPresolveIterations()) == 2 vars = all_variables(m) - @test MOI.get.(m, Alpine.TightenedLowerBound(), vars) ≈ - [100, 999.9, 999.9, 10, 150.2, 10, 35.4, 168] rtol = 1e-6 - @test MOI.get.(m, Alpine.TightenedUpperBound(), vars) ≈ - [4573.8, 5547.9, 5913.4, 332.4, 551, 390, 571.1, 638.7] rtol = 1e-6 + LB = [100, 1000, 1000, 10, 150.2, 10, 35.4, 168] + UB = [4573.6, 5547.8, 5913.3, 332.4, 551, 390, 571.1, 638.7] + @test isapprox(MOI.get.(m, Alpine.TightenedLowerBound(), vars), LB, atol = 1E-6) + @test isapprox(MOI.get.(m, Alpine.TightenedUpperBound(), vars), UB, atol = 1E-6) end # FIXME Pavito terminates with `NUMERICAL_ERROR` on Julia v1.0: @@ -104,7 +104,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "bilinear_convexhull" => false, "log_level" => 100, "max_iter" => 2, @@ -133,22 +133,21 @@ end "monomial_convexhull" => true, "presolve_bt" => false, "presolve_bp" => true, - "disc_ratio" => 10, - "log_level" => 100, + "disc_ratio" => 12, ) m = nlp1(solver = test_solver) JuMP.optimize!(m) @test termination_status(m) == MOI.OPTIMAL - @test isapprox(objective_value(m), 58.38367169858795; atol = 1e-4) - @test MOI.get(m, Alpine.NumberOfIterations()) == 4 + @test isapprox(objective_value(m), 58.38367169858795; atol = 1e-5) + @test MOI.get(m, Alpine.NumberOfIterations()) == 3 end @testset " Validation Test || AMP-CONV || basic solve || examples/nlp3.jl" begin test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "bilinear_convexhull" => true, "monomial_convexhull" => true, "presolve_bt" => false, @@ -189,18 +188,15 @@ end Alpine.Optimizer, "nlp_solver" => IPOPT, "mip_solver" => PAVITO, - "disc_abs_width_tol" => 1e-2, - "disc_ratio" => 5, - "presolve_bt" => true, - "presolve_bt_max_iter" => 1, - "presolve_bt_algo" => 1, - "presolve_bt_bound_tol" => 1e-2, - "log_level" => 100, + "presolve_bt" => false, + "disc_ratio" => 15, + "max_iter" => 2, ) m = circle_MINLPLib(solver = test_solver) JuMP.optimize!(m) + @test termination_status(m) == MOI.OTHER_LIMIT @test isapprox(objective_value(m), 4.45670663096; atol = 1E-6) end @@ -208,7 +204,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "bilinear_convexhull" => true, "monomial_convexhull" => true, "presolve_bt" => false, @@ -226,14 +222,14 @@ end end @testset " Validation Test || AMP || multi4N || N = 2 || exprmode=1:11" begin - n_instances = 11 + n_instances = 5 objValVec = 2.0 * ones(n_instances) for i in 1:n_instances test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "disc_abs_width_tol" => 1e-2, "max_iter" => 4, "disc_ratio" => 4, @@ -254,7 +250,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "disc_abs_width_tol" => 1e-2, "max_iter" => 5, "presolve_bt" => false, @@ -277,7 +273,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "disc_abs_width_tol" => 1e-2, "max_iter" => 4, "disc_ratio" => 4, @@ -299,7 +295,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "disc_abs_width_tol" => 1e-2, "max_iter" => 3, "disc_ratio" => 4, @@ -320,7 +316,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "bilinear_convexhull" => true, "monomial_convexhull" => true, "presolve_bt" => false, @@ -343,7 +339,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "disc_abs_width_tol" => 1e-2, "disc_ratio_branch" => false, "disc_ratio" => 18, @@ -364,7 +360,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "disc_abs_width_tol" => 1e-2, "disc_ratio_branch" => true, "max_iter" => 1, @@ -384,7 +380,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "disc_abs_width_tol" => 1e-2, "disc_ratio_branch" => true, "max_iter" => 1, @@ -404,7 +400,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "disc_abs_width_tol" => 1e-2, "disc_ratio_branch" => true, "max_iter" => 1, @@ -424,7 +420,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "disc_abs_width_tol" => 1e-2, "disc_ratio_branch" => true, "max_iter" => 1, @@ -444,7 +440,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "disc_abs_width_tol" => 1e-2, "disc_ratio_branch" => true, "max_iter" => 1, @@ -464,7 +460,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "disc_abs_width_tol" => 1e-2, "disc_ratio_branch" => true, "max_iter" => 1, @@ -484,7 +480,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "disc_abs_width_tol" => 1e-2, "disc_ratio_branch" => true, "max_iter" => 1, @@ -505,7 +501,7 @@ end Alpine.Optimizer, "minlp_solver" => PAVITO, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "presolve_bt" => false, "log_level" => 100, ) @@ -532,7 +528,7 @@ end Alpine.Optimizer, "minlp_solver" => JUNIPER, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "presolve_bt" => false, "disc_ratio" => 4, "log_level" => 100, @@ -592,26 +588,6 @@ end @test MOI.get(m, Alpine.NumberOfIterations()) == 4 end -# FIXME Pavito terminates with `NUMERICAL_ERROR` on Julia v1.0 in Mac OS (travis) -# However, this runs fine in CPLEX. -# @testset "Embedding Test || AMP || special problem || ... " begin -# test_solver=optimizer_with_attributes(Alpine.Optimizer, "nlp_solver" => IPOPT, -# "mip_solver" => PAVITO, -# "disc_abs_width_tol" => 1e-2, -# "disc_ratio" => 8, -# "max_iter" => 6, -# "presolve_bt" => false, -# "presolve_bp" => true, -# "presolve_bt_algo" => 1, -# "presolve_bt_bound_tol" => 1e-1, -# "convhull_ebd" => true, -# "log_level" => 100) - -# m = circle(solver = test_solver) -# JuMP.optimize!(m) -# @test isapprox(objective_value(m), 1.4142135534556992; atol=1e-3) -# end - @testset "Embedding IBS Test || AMP-CONV || basic solve || examples/nlp1.jl" begin test_solver = optimizer_with_attributes( Alpine.Optimizer, @@ -623,35 +599,38 @@ end "presolve_bp" => true, "convhull_ebd" => true, "convhull_ebd_ibs" => true, + "disc_ratio" => 12, "log_level" => 100, ) m = nlp1(solver = test_solver) JuMP.optimize!(m) @test termination_status(m) == MOI.OPTIMAL - @test isapprox(objective_value(m), 58.38367169858795; atol = 1e-4) - @test MOI.get(m, Alpine.NumberOfIterations()) == 4 + @test isapprox(objective_value(m), 58.38367169858795; atol = 1e-5) + @test MOI.get(m, Alpine.NumberOfIterations()) == 3 end @testset "Embedding IBS Test || AMP-CONV || basic solve || examples/nlp3.jl" begin test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "bilinear_convexhull" => true, "monomial_convexhull" => true, "presolve_bt" => false, "presolve_bp" => false, "convhull_ebd" => true, "convhull_ebd_ibs" => true, - "log_level" => 100, + "max_iter" => 3, ) m = nlp3(solver = test_solver) JuMP.optimize!(m) + alp = JuMP.backend(m).optimizer.model - @test termination_status(m) == MOI.OPTIMAL - @test isapprox(objective_value(m), 7049.247897696188; atol = 1e-4) - @test MOI.get(m, Alpine.NumberOfIterations()) == 9 + @test termination_status(m) == MOI.OTHER_LIMIT + @test isapprox(objective_value(m), 7049.247897696188; atol = 1e-5) + @test MOI.get(m, Alpine.NumberOfIterations()) == 3 + @test isapprox(alp.best_bound, 6893.2067, atol = 1E-4) end @testset "Embedding IBS Test || AMP || special problem || ... " begin @@ -688,14 +667,13 @@ end "presolve_bp" => true, "convhull_ebd" => true, "convhull_ebd_link" => true, - "disc_ratio" => 12, - "log_level" => 100, + "disc_ratio" => 20, ) m = nlp1(solver = test_solver) JuMP.optimize!(m) @test termination_status(m) == MOI.OPTIMAL - @test isapprox(objective_value(m), 58.38367169858795; atol = 1e-4) + @test isapprox(objective_value(m), 58.38367169858795; atol = 1e-5) @test MOI.get(m, Alpine.NumberOfIterations()) == 3 end @@ -703,7 +681,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "bilinear_convexhull" => true, "monomial_convexhull" => true, "presolve_bt" => false, @@ -726,7 +704,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "max_iter" => 1, "presolve_bt" => false, "disc_ratio" => 10, @@ -743,7 +721,7 @@ end Alpine.Optimizer, "minlp_solver" => PAVITO, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "presolve_bp" => true, "disc_var_pick" => 1, "log_level" => 100, @@ -778,7 +756,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "disc_add_partition_method" => "uniform", "disc_uniform_rate" => 10, "max_iter" => 1, @@ -796,7 +774,7 @@ end Alpine.Optimizer, "minlp_solver" => PAVITO, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "bilinear_convexhull" => true, "monomial_convexhull" => true, "presolve_bp" => true, diff --git a/test/test_expression.jl b/test/test_expression.jl index 35838f33..7db29727 100644 --- a/test/test_expression.jl +++ b/test/test_expression.jl @@ -2,7 +2,7 @@ test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "log_level" => 100, ) @@ -120,7 +120,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "log_level" => 100, ) m = nlp1(solver = test_solver) @@ -143,7 +143,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "log_level" => 100, ) @@ -222,7 +222,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "log_level" => 100, ) @@ -244,7 +244,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "minlp_solver" => JUNIPER, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "log_level" => 100, ) @@ -368,7 +368,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "log_level" => 100, ) @@ -728,7 +728,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "log_level" => 100, ) @@ -829,7 +829,7 @@ end optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "log_level" => 100, ), ) @@ -873,7 +873,7 @@ end optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "log_level" => 100, ), ) @@ -934,7 +934,7 @@ end optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "log_level" => 100, ), ) @@ -1002,7 +1002,7 @@ end optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "log_level" => 100, ), ) @@ -1056,7 +1056,7 @@ end optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "log_level" => 100, ), ) @@ -1111,7 +1111,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "log_level" => 100, ) m = convex_test(solver = test_solver) @@ -1322,7 +1322,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "disc_ratio" => 8, "log_level" => 100, ) @@ -1381,7 +1381,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "log_level" => 100, ) @@ -1485,7 +1485,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "disc_ratio" => 8, "log_level" => 100, ) @@ -2679,7 +2679,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "minlp_solver" => JUNIPER, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "log_level" => 100, ) @@ -3340,7 +3340,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "minlp_solver" => JUNIPER, "log_level" => 100, ) @@ -3362,7 +3362,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "log_level" => 100, ) @@ -3389,7 +3389,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "log_level" => 100, ) @@ -3419,7 +3419,7 @@ end Alpine.Optimizer, "minlp_solver" => JUNIPER, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "log_level" => 100, ) @@ -3501,7 +3501,7 @@ end Alpine.Optimizer, "minlp_solver" => JUNIPER, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "log_level" => 100, ) @@ -3645,7 +3645,7 @@ end Alpine.Optimizer, "minlp_solver" => JUNIPER, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "presolve_bt" => true, ) diff --git a/test/test_solver.jl b/test/test_solver.jl index c4546cbe..977c07ef 100644 --- a/test/test_solver.jl +++ b/test/test_solver.jl @@ -3,7 +3,7 @@ test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "log_level" => 100, ) m = operator_c(solver = test_solver) @@ -22,7 +22,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "disc_var_pick" => 0, "disc_uniform_rate" => 10, "presolve_bp" => false, @@ -45,7 +45,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "disc_var_pick" => 2, "disc_uniform_rate" => 10, "presolve_bp" => false, @@ -67,7 +67,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "disc_var_pick" => 1, "disc_uniform_rate" => 10, "presolve_bp" => false, @@ -89,7 +89,7 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "disc_var_pick" => 3, "presolve_bp" => false, "presolve_bt" => false, @@ -113,13 +113,12 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "disc_var_pick" => 0, "disc_uniform_rate" => 10, - "presolve_bp" => false, - "presolve_bt" => false, + "presolve_bt" => true, + "presolve_bt_max_iter" => 2, "max_iter" => 1, - "log_level" => 100, ) m = castro2m2(solver = test_solver) @@ -137,13 +136,12 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "disc_var_pick" => 1, "disc_uniform_rate" => 10, - "presolve_bp" => false, - "presolve_bt" => false, + "presolve_bt" => true, + "presolve_bt_max_iter" => 2, "max_iter" => 1, - "log_level" => 100, ) m = castro2m2(solver = test_solver) @@ -160,11 +158,11 @@ end test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "disc_var_pick" => 2, "disc_uniform_rate" => 15, - "presolve_bp" => false, - "presolve_bt" => false, + "presolve_bt" => true, + "presolve_bt_max_iter" => 2, "max_iter" => 1, "log_level" => 100, ) @@ -188,7 +186,7 @@ end Alpine.Optimizer, "minlp_solver" => PAVITO, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "disc_var_pick" => 0, "disc_uniform_rate" => 10, "presolve_bt" => false, @@ -236,7 +234,7 @@ end Alpine.Optimizer, "minlp_solver" => PAVITO, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "disc_var_pick" => 1, "disc_uniform_rate" => 10, "presolve_bp" => false, @@ -285,7 +283,7 @@ end Alpine.Optimizer, "minlp_solver" => PAVITO, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "disc_var_pick" => 2, "disc_uniform_rate" => 10, "presolve_bp" => false, @@ -306,11 +304,11 @@ end @testset "Partitioning variable selection tests :: castro6m2" begin - # Dynamic Scheme step 2 + # Dynamic Scheme step 1 test_solver = optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "disc_var_pick" => 3, "presolve_bp" => true, "presolve_bt" => false, @@ -330,56 +328,13 @@ end @test length(alpine.disc_vars) == 12 @test length(Set(alpine.disc_vars)) == 12 @test MOI.get(m, MOI.RawOptimizerAttribute("disc_var_pick")) == 3 - - # Dynamic Scheme step 2 - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "disc_var_pick" => 3, - "presolve_bp" => true, - "presolve_bt" => false, - "max_iter" => 2, - "log_level" => 100, - ) - - m = castro6m2(solver = test_solver) - JuMP.optimize!(m) - alpine = JuMP.backend(m).optimizer.model - - @test JuMP.termination_status(m) == MOI.OTHER_LIMIT - @test JuMP.objective_value(m) <= 228.7810 - - @test length(alpine.candidate_disc_vars) == 24 - @test length(Set(alpine.candidate_disc_vars)) == 24 - @test length(alpine.disc_vars) == 12 - @test length(Set(alpine.disc_vars)) == 12 - @test MOI.get(m, MOI.RawOptimizerAttribute("disc_var_pick")) == 3 -end - -@testset "Test getsolvetime for time tracking" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => CBC, - "disc_var_pick" => 0, - "disc_uniform_rate" => 10, - "presolve_bp" => false, - "presolve_bt" => false, - "max_iter" => 1, - "log_level" => 100, - ) - - m = castro2m2(solver = test_solver) - JuMP.optimize!(m) - @test solve_time(m) > 0.0 end @testset "Hessians disabled with user-defined multivariate functions" begin test_solver = JuMP.optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "log_level" => 100, ) m = Model(test_solver) diff --git a/test/test_utility.jl b/test/test_utility.jl index 9c5df83b..2c5d7e12 100644 --- a/test/test_utility.jl +++ b/test/test_utility.jl @@ -3,7 +3,7 @@ Alpine.Optimizer, "minlp_solver" => PAVITO, "nlp_solver" => IPOPT, - "mip_solver" => CBC, + "mip_solver" => HIGHS, "presolve_bp" => true, "disc_var_pick" => 1, "log_level" => 100, From 81ab9c706ad06820cb15d4437b046b5622ab6a2f Mon Sep 17 00:00:00 2001 From: harshangrjn Date: Tue, 30 Aug 2022 22:42:40 -0600 Subject: [PATCH 10/18] test fix --- test/test_algorithm.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_algorithm.jl b/test/test_algorithm.jl index 7a21e1fb..99cf2ec3 100644 --- a/test/test_algorithm.jl +++ b/test/test_algorithm.jl @@ -599,7 +599,7 @@ end "presolve_bp" => true, "convhull_ebd" => true, "convhull_ebd_ibs" => true, - "disc_ratio" => 12, + "disc_ratio" => 8, "log_level" => 100, ) m = nlp1(solver = test_solver) @@ -607,7 +607,7 @@ end @test termination_status(m) == MOI.OPTIMAL @test isapprox(objective_value(m), 58.38367169858795; atol = 1e-5) - @test MOI.get(m, Alpine.NumberOfIterations()) == 3 + @test MOI.get(m, Alpine.NumberOfIterations()) == 4 end @testset "Embedding IBS Test || AMP-CONV || basic solve || examples/nlp3.jl" begin From 737fdf821feb177850333de0af5ee03d693e0fe0 Mon Sep 17 00:00:00 2001 From: harshangrjn Date: Tue, 30 Aug 2022 23:12:05 -0600 Subject: [PATCH 11/18] test fix_2 --- test/test_algorithm.jl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/test_algorithm.jl b/test/test_algorithm.jl index 99cf2ec3..c10f7a15 100644 --- a/test/test_algorithm.jl +++ b/test/test_algorithm.jl @@ -667,14 +667,15 @@ end "presolve_bp" => true, "convhull_ebd" => true, "convhull_ebd_link" => true, - "disc_ratio" => 20, + "disc_ratio" => 10, + "max_iter" => 2, ) m = nlp1(solver = test_solver) JuMP.optimize!(m) - @test termination_status(m) == MOI.OPTIMAL + @test termination_status(m) == MOI.OTHER_LIMIT @test isapprox(objective_value(m), 58.38367169858795; atol = 1e-5) - @test MOI.get(m, Alpine.NumberOfIterations()) == 3 + @test MOI.get(m, Alpine.NumberOfIterations()) == 2 end @testset "Embedding LINK Test || AMP-CONV || basic solve || examples/nlp3.jl" begin From 47b9cf9bbdb6182007dfc9efb845e050241797c4 Mon Sep 17 00:00:00 2001 From: harshangrjn Date: Mon, 5 Sep 2022 19:30:30 -0600 Subject: [PATCH 12/18] cleanup and tests for linking constraints --- CHANGELOG.md | 9 +- README.md | 9 +- docs/src/index.md | 9 +- docs/src/parameters.md | 2 +- examples/JuMP_models.jl | 5 +- examples/MINLPs/blend.jl | 4 +- examples/MINLPs/brainpc3.jl | 2 +- examples/MINLPs/castro.jl | 6 +- examples/MINLPs/circle.jl | 6 +- examples/MINLPs/convex.jl | 4 +- examples/MINLPs/discretemulti.jl | 20 +- examples/MINLPs/div.jl | 2 +- examples/MINLPs/exprstest.jl | 8 +- examples/MINLPs/integer.jl | 18 +- examples/MINLPs/linearlift.jl | 2 +- examples/MINLPs/mult3.jl | 64 + examples/MINLPs/multi.jl | 12 +- examples/MINLPs/nlp.jl | 8 +- examples/MINLPs/rosenbrock.jl | 2 +- examples/MINLPs/sincos.jl | 6 +- examples/Project.toml | 1 + examples/README.md | 4 +- examples/run_examples.jl | 5 +- examples/run_examples_linking.jl | 59 - src/Alpine.jl | 11 +- src/MOI_wrapper/MOI_wrapper.jl | 5 + src/algorithm.jl | 21 +- src/{amp.jl => bounding_model.jl} | 40 +- src/embedding.jl | 2 +- src/heuristics.jl | 11 - src/linking.jl | 75 - src/log.jl | 15 +- src/{multi.jl => multilinear.jl} | 195 +- src/relaxations.jl | 81 + src/{solver.jl => solver_options.jl} | 52 +- src/tmc.jl | 475 -- src/utility.jl | 14 +- src/{bounds.jl => variable_bounds.jl} | 13 - test/runtests.jl | 6 +- test/test_algorithm.jl | 1908 +++---- test/test_expression.jl | 7283 +++++++++++++------------ test/test_utility.jl | 4 +- 42 files changed, 4977 insertions(+), 5501 deletions(-) create mode 100644 examples/MINLPs/mult3.jl delete mode 100644 examples/run_examples_linking.jl rename src/{amp.jl => bounding_model.jl} (91%) delete mode 100644 src/linking.jl rename src/{multi.jl => multilinear.jl} (81%) create mode 100644 src/relaxations.jl rename src/{solver.jl => solver_options.jl} (80%) delete mode 100644 src/tmc.jl rename src/{bounds.jl => variable_bounds.jl} (96%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a5995e0..19258620 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,13 @@ # Alpine.jl Change Log ## v0.5.0 -- New feature: Linking constraints for multilinear terms with uniform and adaptive partitions (speed up in run times for multilinear problems) (@jongeunkim) +- New feature: Linking constraints for multilinear terms with uniform and adaptive partitions (significant speed up in run times for multilinear problems: http://www.optimization-online.org/DB_HTML/2022/07/8974.html) (@jongeunkim) - Added dependency on Combinatorics package for linking constraints +- Added unit tests for linking constraints feature - Changed Cbc test dependency to HiGHS solver - Dropped a few redundant unit tests +- Dropped support for (slower) piecewise McCormick formulations +- Changed `disc_ratio` to `partition_scaling_factor` - Added JuliaFormatter.toml and formatting workfow ## v0.4.3 @@ -192,7 +195,7 @@ Closed issues: - Alpine.jl first release ## Merged Features -- `disc_ratio` selection algorithm +- `partition_scaling_factor` selection algorithm - logarithm embedding formulation - bounding model warm starting and no-good-cuts using solution pool - `disc_vars` selection algorithm based on weighted minimum vertex cover @@ -236,6 +239,6 @@ Closed issues: - Fixed many other things ## Tests & Coverage -- Most new features are covered (embedding, `disc_ratio` algorithm, etc.) +- Most new features are covered (embedding, `partition_scaling_factor` algorithm, etc.) - Stronger expression parsing tests with new operators covered - Coverage should be more than `~90%` diff --git a/README.md b/README.md index b36a38be..06e487aa 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ If you find Alpine useful in your work, we kindly request that you cite the foll doi = {10.1007/978-3-319-44953-1_24}, } ``` -If you find the underlying piecewise polyhedral formulations implemented in Alpine useful in your work, we kindly request that you cite the following paper ([link](https://doi.org/10.1016/j.orl.2020.12.002)): +If you find the underlying piecewise polyhedral formulations implemented in Alpine useful in your work, we kindly request that you cite the following papers ([link-1](https://doi.org/10.1016/j.orl.2020.12.002), [link-2](http://www.optimization-online.org/DB_HTML/2022/07/8974.html)): ```bibtex @article{alpine_ORL2021, title = {Piecewise polyhedral formulations for a multilinear term}, @@ -93,4 +93,11 @@ If you find the underlying piecewise polyhedral formulations implemented in Alpi year = {2021}, publisher = {Elsevier} } + +@article{alpine_OptOnline2022, + title={Piecewise Polyhedral Relaxations of Multilinear Optimization}, + author={Kim, Jongeun and Richard, Jean-Philippe P. and Tawarmalani, Mohit}, + eprinttype={Optimization Online}, + date={2022} +} ``` \ No newline at end of file diff --git a/docs/src/index.md b/docs/src/index.md index d023047b..e5d0112e 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -59,7 +59,7 @@ If you find Alpine useful in your work, we request you to cite the following pap doi = {10.1007/978-3-319-44953-1_24}, } ``` -If you find the underlying piecewise polyhedral formulations implemented in Alpine useful in your work, we kindly request that you cite the following paper [\[link\]](https://doi.org/10.1016/j.orl.2020.12.002): +If you find the underlying piecewise polyhedral formulations implemented in Alpine useful in your work, we kindly request that you cite the following papers ([link-1](https://doi.org/10.1016/j.orl.2020.12.002), [link-2](http://www.optimization-online.org/DB_HTML/2022/07/8974.html)): ```bibtex @article{alpine_ORL2021, title = {Piecewise polyhedral formulations for a multilinear term}, @@ -71,4 +71,11 @@ If you find the underlying piecewise polyhedral formulations implemented in Alpi year = {2021}, publisher = {Elsevier} } + +@article{alpine_OptOnline2022, + title={Piecewise Polyhedral Relaxations of Multilinear Optimization}, + author={Kim, Jongeun and Richard, Jean-Philippe P. and Tawarmalani, Mohit}, + eprinttype={Optimization Online}, + date={2022} +} ``` diff --git a/docs/src/parameters.md b/docs/src/parameters.md index 5540109f..71a5facc 100644 --- a/docs/src/parameters.md +++ b/docs/src/parameters.md @@ -21,7 +21,7 @@ Here are a few general solver options which control the performance of Alpine: ## Adaptive Partitioning Options * `apply_partitioning (default = true)`: applies Alpine's built-in MIP-based partitioning algorithm only when activated; else terminates with the presolve solution. -* `disc_ratio (default = 4)`: used during [`add_adaptive_partition`](@ref) for measuring the width of new partitions relative to the active partition chosen in the sequentially solved lower-bounding MIPs. This value can substantially affect the run time for global convergence; this value can be set to different integer values (>= 4) for various classes of problems. +* `partition_scaling_factor (default = 10)`: used during [`add_adaptive_partition`](@ref) for scaling the width of new partitions relative to the active partition chosen in the sequentially-solved lower-bounding MIP models. This value can substantially affect the run time for global convergence; this value can be set to different integer values (>= 4) for various classes of problems. * `disc_var_pick (default = 0)`: controls Alpine's algorithm used for selecting variables for partitioning; `0` is for max-cover, `1` is for minimum-vertex-cover. This parameter allows functional inputs. diff --git a/examples/JuMP_models.jl b/examples/JuMP_models.jl index bfda0155..3a2d7a87 100644 --- a/examples/JuMP_models.jl +++ b/examples/JuMP_models.jl @@ -9,6 +9,5 @@ include("MINLPs/div.jl") include("MINLPs/exprstest.jl") include("MINLPs/linearlift.jl") include("MINLPs/multi.jl") -include("MINLPs/rosenbrock.jl") -# include("MINLPs/sincos.jl") -# include("MINLPs/integer.jl") +include("MINLPs/mult3.jl") +include("MINLPs/rosenbrock.jl") \ No newline at end of file diff --git a/examples/MINLPs/blend.jl b/examples/MINLPs/blend.jl index e05fcfdb..a4e8fbbf 100644 --- a/examples/MINLPs/blend.jl +++ b/examples/MINLPs/blend.jl @@ -1,5 +1,5 @@ function blend029(; solver = nothing) - m = Model(solver) + m = JuMP.Model(solver) @variable(m, x[1:102]) for i in 67:102 @@ -324,7 +324,7 @@ function blend029(; solver = nothing) end function blend029_gl(; solver = nothing) - m = Model(solver) + m = JuMP.Model(solver) @variable(m, x[1:102]) for i in 67:102 diff --git a/examples/MINLPs/brainpc3.jl b/examples/MINLPs/brainpc3.jl index 6b2231f2..80b31afb 100644 --- a/examples/MINLPs/brainpc3.jl +++ b/examples/MINLPs/brainpc3.jl @@ -1,5 +1,5 @@ function brainpc3(; solver = nothing) - m = Model(solver) + m = JuMP.Model(solver) # ----- Variables ----- # @variable(m, x[1:6907]) diff --git a/examples/MINLPs/castro.jl b/examples/MINLPs/castro.jl index 9d235cd7..3327b6d9 100644 --- a/examples/MINLPs/castro.jl +++ b/examples/MINLPs/castro.jl @@ -1,5 +1,5 @@ function castro2m2(; solver = nothing) - m = Model(solver) + m = JuMP.Model(solver) @variable(m, 0 <= x[1:41] <= 1E5) @variable(m, obj) @@ -64,7 +64,7 @@ function castro2m2(; solver = nothing) end function castro6m2(; solver = nothing) - m = Model(solver) + m = JuMP.Model(solver) @variable(m, 0 <= x[1:133] <= 1E6) @variable(m, obj) @@ -332,7 +332,7 @@ function castro6m2(; solver = nothing) end function castro4m2(; solver = nothing) - m = Model(solver) + m = JuMP.Model(solver) # ----- Variables ----- # @variable(m, 0 <= x[1:55] <= 1E6) diff --git a/examples/MINLPs/circle.jl b/examples/MINLPs/circle.jl index f1fedcf1..fee7907e 100644 --- a/examples/MINLPs/circle.jl +++ b/examples/MINLPs/circle.jl @@ -1,5 +1,5 @@ function circle(; solver = nothing) - m = Model(solver) + m = JuMP.Model(solver) @variable(m, 0 <= x[1:2] <= 2) @NLconstraint(m, x[1]^2 + x[2]^2 >= 2) @@ -13,10 +13,10 @@ function circle_MINLPLib(; solver = nothing) # Above instance has been mofified to convert the problem into a non-convex NLP # Global solution: 4.45670663096, arg min = [4.2536125, 3.4367961] - m = Model(solver) + m = JuMP.Model(solver) @variable(m, 0 <= objvar <= 5) - @variable(m, -10 <= x[1:2] <= 10) + @variable(m, 1 <= x[1:2] <= 5) @NLconstraint( m, diff --git a/examples/MINLPs/convex.jl b/examples/MINLPs/convex.jl index ce34270d..12205fec 100644 --- a/examples/MINLPs/convex.jl +++ b/examples/MINLPs/convex.jl @@ -1,5 +1,5 @@ function convex_test(; solver = nothing) - m = Model(solver) + m = JuMP.Model(solver) @variable(m, 0 <= x[1:5] <= 2) @@ -54,7 +54,7 @@ function convex_test(; solver = nothing) end function convex_solve(; solver = nothing) - m = Model(solver) + m = JuMP.Model(solver) @variable(m, 0 <= x[1:5] <= 100) diff --git a/examples/MINLPs/discretemulti.jl b/examples/MINLPs/discretemulti.jl index 09df1e84..fa3cdf59 100644 --- a/examples/MINLPs/discretemulti.jl +++ b/examples/MINLPs/discretemulti.jl @@ -1,5 +1,5 @@ function binprod_nlp3(; solver = nothing) - m = Model(solver) + m = JuMP.Model(solver) LB = [100, 1000, 1000, 10, 10, 10, 10, 10] UB = [10000, 10000, 10000, 1000, 1000, 1000, 1000, 1000] @@ -31,7 +31,7 @@ function binprod_nlp3(; solver = nothing) end function circlebin(; verbose = false, solver = nothing) - m = Model(solver) + m = JuMP.Model(solver) @variable(m, 0 <= x[1:5] <= 1, Bin) @NLconstraint(m, x[1]^2 + x[2]^2 >= 2) @@ -41,7 +41,7 @@ function circlebin(; verbose = false, solver = nothing) end function bpml(; verbose = false, solver = nothing) - m = Model(solver) + m = JuMP.Model(solver) @variable(m, 0 <= x[1:5] <= 1, Bin) @variable(m, y[1:5] >= 0) @@ -61,7 +61,7 @@ function bpml(; verbose = false, solver = nothing) end function bmpl_linearlifting(; solver = nothing) - m = Model(solver) + m = JuMP.Model(solver) @variable(m, 0 <= x[1:5] <= 1, Bin) @variable(m, y[1:5] >= 0) @@ -76,7 +76,7 @@ function bmpl_linearlifting(; solver = nothing) end function bpml_lnl(; solver = nothing) - m = Model(solver) + m = JuMP.Model(solver) Random.seed!(10) @variable(m, 0 <= X[1:5] <= 1, Bin) @@ -88,7 +88,7 @@ function bpml_lnl(; solver = nothing) end function bpml_binl(; solver = nothing) - m = Model(solver) + m = JuMP.Model(solver) Random.seed!(10) @variable(m, 0 <= X[1:5] <= 1, Bin) @@ -100,7 +100,7 @@ function bpml_binl(; solver = nothing) end function bpml_monl(; solver = nothing) - m = Model(solver) + m = JuMP.Model(solver) Random.seed!(10) @variable(m, 0 <= X[1:5] <= 1, Bin) @@ -112,7 +112,7 @@ function bpml_monl(; solver = nothing) end function bpml_negative(; solver = nothing) - m = Model(solver) + m = JuMP.Model(solver) Random.seed!(10) @variable(m, 0 <= X[1:5] <= 1, Bin) @@ -129,7 +129,7 @@ function bpml_negative(; solver = nothing) end function intprod_basic(; solver = nothing) - m = Model(solver) + m = JuMP.Model(solver) @variable(m, 1 <= Z[1:10] <= 10, Int) @NLconstraint(m, (Z[1] + Z[2]) * (Z[3] + Z[4]) >= 25) @@ -142,7 +142,7 @@ function intprod_basic(; solver = nothing) end function discretemulti_basic(; solver = nothing) - m = Model(solver) + m = JuMP.Model(solver) Random.seed!(10) @variable(m, 0 <= X[1:5] <= 1, Bin) diff --git a/examples/MINLPs/div.jl b/examples/MINLPs/div.jl index d016a676..a4ad4626 100644 --- a/examples/MINLPs/div.jl +++ b/examples/MINLPs/div.jl @@ -1,5 +1,5 @@ function div(; verbose = false, solver = nothing) - m = Model(solver) + m = JuMP.Model(solver) @variable(m, 1 <= x[1:2] <= 10) diff --git a/examples/MINLPs/exprstest.jl b/examples/MINLPs/exprstest.jl index 77be678a..3ebb03d2 100644 --- a/examples/MINLPs/exprstest.jl +++ b/examples/MINLPs/exprstest.jl @@ -1,5 +1,5 @@ function exprstest(; solver = nothing) - m = Model(solver) + m = JuMP.Model(solver) @variable(m, px[i = 1:6] >= 1) # At some point if an initial value is given, keep them @@ -30,7 +30,7 @@ function exprstest(; solver = nothing) end function operator_b(; solver = nothing) - m = Model(solver) + m = JuMP.Model(solver) @variable(m, x[1:4] >= 0) @variable(m, y[1:3] <= 0) @@ -74,7 +74,7 @@ function operator_b(; solver = nothing) end function operator_basic(; solver = nothing) - m = Model(solver) + m = JuMP.Model(solver) @variable(m, x[1:4] >= 0) @@ -176,7 +176,7 @@ function operator_basic(; solver = nothing) end function operator_c(; solver = nothing) - m = Model(solver) + m = JuMP.Model(solver) @variable(m, px[i = 1:6] >= 1) # At some point if an initial value is given, keep them diff --git a/examples/MINLPs/integer.jl b/examples/MINLPs/integer.jl index 93ec37f9..a7342e5d 100644 --- a/examples/MINLPs/integer.jl +++ b/examples/MINLPs/integer.jl @@ -2,7 +2,7 @@ function ex1225a(; solver = nothing) # GOpt: 131670.377903 # This problem may be numerically sensitive - m = Model(solver) + m = JuMP.Model(solver) # ----- Variables ----- # @variable(m, objvar) @@ -123,7 +123,7 @@ function ex1264a(; solver = nothing) # Source: http://minlplib.org/ex1264a.html # GOpt: 8.6 - m = Model(solver) + m = JuMP.Model(solver) @variable(m, objvar) b_Idx = Any[17, 18, 19, 20] @@ -231,7 +231,7 @@ function prob03(; solver = nothing) # Source: http://minlplib.org/prob03.html # GOpt: 10.0000 - m = Model(solver) + m = JuMP.Model(solver) @variable(m, objvar) i_Idx = Any[1, 2] @@ -249,7 +249,7 @@ function prob10(; solver = nothing) # Source: http://minlplib.org/prob10.html # GOpt: 3.44550379 - m = Model(solver) + m = JuMP.Model(solver) @variable(m, objvar) x_Idx = Any[2] @@ -275,7 +275,7 @@ function st_miqp1(; solver = nothing) # source: http://minlplib.org/st_miqp1.html # GOpt: 281.0000 - m = Model(solver) + m = JuMP.Model(solver) # ----- Variables ----- # @variable(m, objvar) @@ -312,7 +312,7 @@ function st_miqp2(; solver = nothing) # Source: http://minlplib.org/st_miqp2.html # GOpt: 2.0000 - m = Model(solver) + m = JuMP.Model(solver) # ----- Variables ----- # @variable(m, objvar) @@ -344,7 +344,7 @@ function st_miqp3(; solver = nothing) # Source: http://minlplib.org/st_miqp3.html # GOpt: -6.0000 - m = Model(solver) + m = JuMP.Model(solver) # ----- Variables ----- # @variable(m, objvar) @@ -367,7 +367,7 @@ function st_miqp4(; solver = nothing) # Source: http://minlplib.org/st_miqp4.html # GOpt: -4574.0000 - m = Model(solver) + m = JuMP.Model(solver) # ----- Variables ----- # @variable(m, objvar) @@ -398,7 +398,7 @@ function st_miqp5(; solver = nothing) # Source: http://minlplib.org/st_miqp5.html # GOpt: -333.88888890 - m = Model(solver) + m = JuMP.Model(solver) # ----- Variables ----- # @variable(m, objvar) diff --git a/examples/MINLPs/linearlift.jl b/examples/MINLPs/linearlift.jl index 02b8b81e..8456e140 100644 --- a/examples/MINLPs/linearlift.jl +++ b/examples/MINLPs/linearlift.jl @@ -1,5 +1,5 @@ function basic_linear_lift(; verbose = false, solver = nothing) - m = Model(solver) + m = JuMP.Model(solver) @variable(m, x[i = 1:3] >= 1) # At some point if an initial value is given, keep them @constraint(m, (x[1] - x[2]) * (3 * x[2] - x[3]) >= 111) diff --git a/examples/MINLPs/mult3.jl b/examples/MINLPs/mult3.jl new file mode 100644 index 00000000..d0701563 --- /dev/null +++ b/examples/MINLPs/mult3.jl @@ -0,0 +1,64 @@ +function linking_constraints_testing(; solver = nothing) + m = JuMP.Model(solver) + + x_Idx = Any[1, 2, 3, 4] + @variable(m, 0 <= x[x_Idx] <= 1) + @variable(m, obj) + @objective(m, Min, obj) + @NLconstraint(m, e1, -(0.4931*x[1]*x[2] + + 0.6864*x[1]*x[3] - + 0.0577*x[1]*x[4] + + 0.3468*x[1]*x[2]*x[3] - + 0.6988*x[1]*x[3]*x[4] - + 0.9648*x[1]*x[2]*x[4]) + obj == 0.0) + + return m + end + +function m_10_3_0_100_1(; solver = nothing) + m = JuMP.Model(solver) + + x_Idx = Any[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + @variable(m, 0 <= x[x_Idx] <= 1) + @variable(m, obj) + @objective(m, Min, obj) + @NLconstraint(m, e1, -(0.4931*x[1]*x[2]+0.6864*x[1]*x[3]+0.0577*x[1]*x[4]+0.331*x[1]*x[5]+0.4615*x[1]*x[6]-0.1788*x[1]*x[7]-0.2886*x[1]*x[8]+0.4708*x[1]*x[9]-0.0574*x[1]*x[10]-0.0747*x[2]*x[3]+0.5194*x[2]*x[4]+0.4049*x[2]*x[5]-0.4841*x[2]*x[6]+0.8754*x[2]*x[7]-0.0878*x[2]*x[8]+0.617*x[2]*x[9]+0.8177*x[2]*x[10]+0.3898*x[3]*x[4]-0.561*x[3]*x[5]+0.7099*x[3]*x[6]+0.4888*x[3]*x[7]-0.3978*x[3]*x[8]+0.3439*x[3]*x[9]+0.2374*x[3]*x[10]+0.9351*x[4]*x[5]+0.9805*x[4]*x[6]-0.324*x[4]*x[7]+0.8415*x[4]*x[8]-0.3219*x[4]*x[9]+0.8619*x[4]*x[10]+0.0931*x[5]*x[6]-0.069*x[5]*x[7]-0.6462*x[5]*x[8]-0.244*x[5]*x[9]-0.6496*x[5]*x[10]-0.2863*x[6]*x[7]+0.3314*x[6]*x[8]+0.2371*x[6]*x[9]-0.0621*x[6]*x[10]-0.3675*x[7]*x[8]-0.4622*x[7]*x[9]-0.6002*x[7]*x[10]-0.1691*x[8]*x[9]+0.9586*x[8]*x[10]+0.0864*x[9]*x[10]-0.741*x[1]+0.6095*x[2]+0.6916*x[3]+0.4181*x[4]+0.0579*x[5]+0.3277*x[6]+0.8015*x[7]+0.8823*x[8]-0.7712*x[9]+0.7333*x[10]+0.9951*x[1]*x[2]*x[3]+0.1336*x[1]*x[2]*x[4]+0.9318*x[1]*x[2]*x[5]+0.4959*x[1]*x[2]*x[6]-0.2652*x[1]*x[2]*x[7]-0.0387*x[1]*x[2]*x[8]-0.8525*x[1]*x[2]*x[9]-0.9893*x[1]*x[2]*x[10]-0.3058*x[1]*x[3]*x[4]-0.3155*x[1]*x[3]*x[5]-0.5641*x[1]*x[3]*x[6]-0.7337*x[1]*x[3]*x[7]+0.801*x[1]*x[3]*x[8]-0.2265*x[1]*x[3]*x[9]-0.109*x[1]*x[3]*x[10]+0.3239*x[1]*x[4]*x[5]-0.9678*x[1]*x[4]*x[6]+0.3017*x[1]*x[4]*x[7]+0.2928*x[1]*x[4]*x[8]-0.354*x[1]*x[4]*x[9]+0.7114*x[1]*x[4]*x[10]-0.1974*x[1]*x[5]*x[6]-0.5863*x[1]*x[5]*x[7]+0.9371*x[1]*x[5]*x[8]+0.1968*x[1]*x[5]*x[9]+0.346*x[1]*x[5]*x[10]-0.0862*x[1]*x[6]*x[7]-0.34*x[1]*x[6]*x[8]-0.7992*x[1]*x[6]*x[9]+0.5109*x[1]*x[6]*x[10]+0.2114*x[1]*x[7]*x[8]+0.4381*x[1]*x[7]*x[9]+0.7947*x[1]*x[7]*x[10]+0.3165*x[1]*x[8]*x[9]-0.6986*x[1]*x[8]*x[10]+0.2246*x[1]*x[9]*x[10]+0.9573*x[2]*x[3]*x[4]+0.9983*x[2]*x[3]*x[5]-0.4864*x[2]*x[3]*x[6]+0.1017*x[2]*x[3]*x[7]+0.3181*x[2]*x[3]*x[8]+0.108*x[2]*x[3]*x[9]+0.9555*x[2]*x[3]*x[10]+0.8038*x[2]*x[4]*x[5]+0.3158*x[2]*x[4]*x[6]+0.4577*x[2]*x[4]*x[7]-0.1951*x[2]*x[4]*x[8]+0.8573*x[2]*x[4]*x[9]-0.7043*x[2]*x[4]*x[10]+0.3491*x[2]*x[5]*x[6]+0.5392*x[2]*x[5]*x[7]-0.3214*x[2]*x[5]*x[8]-0.7684*x[2]*x[5]*x[9]+0.2287*x[2]*x[5]*x[10]+0.6412*x[2]*x[6]*x[7]+0.8942*x[2]*x[6]*x[8]+0.4623*x[2]*x[6]*x[9]-0.0048*x[2]*x[6]*x[10]-0.2504*x[2]*x[7]*x[8]-0.157*x[2]*x[7]*x[9]+0.1058*x[2]*x[7]*x[10]+0.9958*x[2]*x[8]*x[9]+0.9808*x[2]*x[8]*x[10]+0.4926*x[2]*x[9]*x[10]+0.9075*x[3]*x[4]*x[5]-0.8135*x[3]*x[4]*x[6]+0.468*x[3]*x[4]*x[7]+0.5035*x[3]*x[4]*x[8]+0.8937*x[3]*x[4]*x[9]+0.4124*x[3]*x[4]*x[10]+0.6276*x[3]*x[5]*x[6]+0.1172*x[3]*x[5]*x[7]-0.8766*x[3]*x[5]*x[8]-0.0392*x[3]*x[5]*x[9]+0.1954*x[3]*x[5]*x[10]-0.7249*x[3]*x[6]*x[7]+0.1748*x[3]*x[6]*x[8]+0.0399*x[3]*x[6]*x[9]+0.7718*x[3]*x[6]*x[10]-0.3924*x[3]*x[7]*x[8]+0.3393*x[3]*x[7]*x[9]+0.3299*x[3]*x[7]*x[10]+0.0074*x[3]*x[8]*x[9]-0.4768*x[3]*x[8]*x[10]-0.8469*x[3]*x[9]*x[10]-0.7975*x[4]*x[5]*x[6]+0.0985*x[4]*x[5]*x[7]-0.2488*x[4]*x[5]*x[8]-0.9697*x[4]*x[5]*x[9]+0.5858*x[4]*x[5]*x[10]+0.2418*x[4]*x[6]*x[7]+0.5472*x[4]*x[6]*x[8]+0.9072*x[4]*x[6]*x[9]-0.7715*x[4]*x[6]*x[10]-0.3631*x[4]*x[7]*x[8]+0.1936*x[4]*x[7]*x[9]-0.9037*x[4]*x[7]*x[10]-0.7716*x[4]*x[8]*x[9]-0.5681*x[4]*x[8]*x[10]-0.7989*x[4]*x[9]*x[10]-0.8533*x[5]*x[6]*x[7]-0.5063*x[5]*x[6]*x[8]-0.1132*x[5]*x[6]*x[9]-0.5833*x[5]*x[6]*x[10]+0.134*x[5]*x[7]*x[8]-0.9514*x[5]*x[7]*x[9]-0.1594*x[5]*x[7]*x[10]-0.2043*x[5]*x[8]*x[9]+0.9532*x[5]*x[8]*x[10]+0.3852*x[5]*x[9]*x[10]-0.9901*x[6]*x[7]*x[8]-0.7402*x[6]*x[7]*x[9]-0.9064*x[6]*x[7]*x[10]+0.6796*x[6]*x[8]*x[9]+0.357*x[6]*x[8]*x[10]+0.1639*x[6]*x[9]*x[10]+0.4671*x[7]*x[8]*x[9]-0.7679*x[7]*x[8]*x[10]+0.6806*x[7]*x[9]*x[10]+0.67*x[8]*x[9]*x[10])+ obj == 0.0) + + return m +end + +function m_10_3_0_100_2(; solver = nothing) + m = JuMP.Model(solver) + + x_Idx = Any[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + @variable(m, 0 <= x[x_Idx] <= 1) + @variable(m, obj) + @objective(m, Min, obj) + @NLconstraint(m, e1, -(0.9844*x[1]*x[2]-0.5504*x[1]*x[3]+0.8946*x[1]*x[4]+0.6956*x[1]*x[5]+0.4003*x[1]*x[6]+0.1089*x[1]*x[7]-0.1168*x[1]*x[8]-0.5016*x[1]*x[9]+0.7953*x[1]*x[10]-0.7085*x[2]*x[3]-0.1308*x[2]*x[4]-0.0852*x[2]*x[5]-0.3812*x[2]*x[6]-0.0382*x[2]*x[7]+0.3795*x[2]*x[8]+0.6216*x[2]*x[9]-0.2157*x[2]*x[10]-0.4137*x[3]*x[4]+0.152*x[3]*x[5]+0.4507*x[3]*x[6]-0.7145*x[3]*x[7]-0.3329*x[3]*x[8]-0.6792*x[3]*x[9]+0.0692*x[3]*x[10]+0.4467*x[4]*x[5]-0.5436*x[4]*x[6]-0.602*x[4]*x[7]+0.9452*x[4]*x[8]+0.9871*x[4]*x[9]-0.8361*x[4]*x[10]-0.4982*x[5]*x[6]-0.5683*x[5]*x[7]-0.6084*x[5]*x[8]+0.7005*x[5]*x[9]-0.9106*x[5]*x[10]+0.7278*x[6]*x[7]-0.8657*x[6]*x[8]-0.1454*x[6]*x[9]-0.7254*x[6]*x[10]-0.7618*x[7]*x[8]-0.3881*x[7]*x[9]+0.2265*x[7]*x[10]+0.3273*x[8]*x[9]+0.7918*x[8]*x[10]+0.5074*x[9]*x[10]+0.2597*x[1]-0.558*x[2]-0.0323*x[3]+0.23*x[4]+0.9753*x[5]+0.1184*x[6]-0.2582*x[7]-0.3248*x[8]+0.4909*x[9]+0.1395*x[10]+0.2647*x[1]*x[2]*x[3]-0.5144*x[1]*x[2]*x[4]-0.6792*x[1]*x[2]*x[5]-0.9575*x[1]*x[2]*x[6]-0.6195*x[1]*x[2]*x[7]-0.3753*x[1]*x[2]*x[8]+0.6193*x[1]*x[2]*x[9]+0.1474*x[1]*x[2]*x[10]+0.6525*x[1]*x[3]*x[4]-0.4271*x[1]*x[3]*x[5]-0.679*x[1]*x[3]*x[6]-0.3382*x[1]*x[3]*x[7]-0.4683*x[1]*x[3]*x[8]+0.0896*x[1]*x[3]*x[9]+0.107*x[1]*x[3]*x[10]-0.9568*x[1]*x[4]*x[5]-0.7025*x[1]*x[4]*x[6]-0.7902*x[1]*x[4]*x[7]+0.2284*x[1]*x[4]*x[8]-0.1874*x[1]*x[4]*x[9]+0.8031*x[1]*x[4]*x[10]+0.8857*x[1]*x[5]*x[6]-0.6868*x[1]*x[5]*x[7]+0.8739*x[1]*x[5]*x[8]-0.7291*x[1]*x[5]*x[9]-0.2574*x[1]*x[5]*x[10]-0.357*x[1]*x[6]*x[7]+0.4299*x[1]*x[6]*x[8]+0.4594*x[1]*x[6]*x[9]-0.2428*x[1]*x[6]*x[10]+0.6579*x[1]*x[7]*x[8]+0.9073*x[1]*x[7]*x[9]-0.3832*x[1]*x[7]*x[10]+0.1595*x[1]*x[8]*x[9]-0.5331*x[1]*x[8]*x[10]+0.6888*x[1]*x[9]*x[10]-0.4837*x[2]*x[3]*x[4]+0.6795*x[2]*x[3]*x[5]+0.0753*x[2]*x[3]*x[6]+0.2431*x[2]*x[3]*x[7]-0.0184*x[2]*x[3]*x[8]-0.4303*x[2]*x[3]*x[9]-0.5289*x[2]*x[3]*x[10]+0.3028*x[2]*x[4]*x[5]+0.2143*x[2]*x[4]*x[6]-0.2037*x[2]*x[4]*x[7]+0.6976*x[2]*x[4]*x[8]+0.2752*x[2]*x[4]*x[9]-0.4824*x[2]*x[4]*x[10]-0.2823*x[2]*x[5]*x[6]+0.1237*x[2]*x[5]*x[7]-0.7571*x[2]*x[5]*x[8]+0.9569*x[2]*x[5]*x[9]-0.2336*x[2]*x[5]*x[10]+0.4414*x[2]*x[6]*x[7]-0.2835*x[2]*x[6]*x[8]+0.8198*x[2]*x[6]*x[9]+0.0874*x[2]*x[6]*x[10]+0.9194*x[2]*x[7]*x[8]+0.8589*x[2]*x[7]*x[9]+0.2666*x[2]*x[7]*x[10]-0.4088*x[2]*x[8]*x[9]-0.6505*x[2]*x[8]*x[10]+0.6852*x[2]*x[9]*x[10]+0.2372*x[3]*x[4]*x[5]+0.4118*x[3]*x[4]*x[6]-0.5151*x[3]*x[4]*x[7]+0.5959*x[3]*x[4]*x[8]-0.218*x[3]*x[4]*x[9]-0.7801*x[3]*x[4]*x[10]+0.5074*x[3]*x[5]*x[6]-0.9404*x[3]*x[5]*x[7]+0.4013*x[3]*x[5]*x[8]+0.0504*x[3]*x[5]*x[9]+0.5051*x[3]*x[5]*x[10]+0.2954*x[3]*x[6]*x[7]+0.7422*x[3]*x[6]*x[8]+0.6614*x[3]*x[6]*x[9]+0.9144*x[3]*x[6]*x[10]-0.5555*x[3]*x[7]*x[8]+0.159*x[3]*x[7]*x[9]+0.9815*x[3]*x[7]*x[10]+0.6799*x[3]*x[8]*x[9]-0.6504*x[3]*x[8]*x[10]+0.4191*x[3]*x[9]*x[10]-0.3969*x[4]*x[5]*x[6]-0.9499*x[4]*x[5]*x[7]+0.8335*x[4]*x[5]*x[8]+0.3776*x[4]*x[5]*x[9]+0.5135*x[4]*x[5]*x[10]+0.8655*x[4]*x[6]*x[7]-0.89*x[4]*x[6]*x[8]-0.0021*x[4]*x[6]*x[9]-0.881*x[4]*x[6]*x[10]-0.6563*x[4]*x[7]*x[8]+0.3767*x[4]*x[7]*x[9]-0.3868*x[4]*x[7]*x[10]+0.4704*x[4]*x[8]*x[9]+0.5043*x[4]*x[8]*x[10]-0.2086*x[4]*x[9]*x[10]-0.8244*x[5]*x[6]*x[7]-0.9021*x[5]*x[6]*x[8]+0.5587*x[5]*x[6]*x[9]+0.3616*x[5]*x[6]*x[10]-0.3769*x[5]*x[7]*x[8]+0.0455*x[5]*x[7]*x[9]+0.0116*x[5]*x[7]*x[10]-0.1229*x[5]*x[8]*x[9]+0.1753*x[5]*x[8]*x[10]-0.4053*x[5]*x[9]*x[10]-0.4102*x[6]*x[7]*x[8]-0.8524*x[6]*x[7]*x[9]+0.9499*x[6]*x[7]*x[10]+0.4563*x[6]*x[8]*x[9]+0.5162*x[6]*x[8]*x[10]-0.3816*x[6]*x[9]*x[10]-0.507*x[7]*x[8]*x[9]-0.4862*x[7]*x[8]*x[10]+0.2361*x[7]*x[9]*x[10]+0.8756*x[8]*x[9]*x[10])+obj == 0.0) + + return m +end + +function m_10_3_10_100_1(; solver = nothing) + m = JuMP.Model(solver) + + + x_Idx = Any[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + @variable(m, 0 <= x[x_Idx] <= 1) + @variable(m, obj) + @objective(m, Min, obj) + + @NLconstraint(m, e1, -(0.4931*x[1]*x[2]+0.6864*x[1]*x[3]+0.0577*x[1]*x[4]+0.331*x[1]*x[5]+0.4615*x[1]*x[6]-0.1788*x[1]*x[7]-0.2886*x[1]*x[8]+0.4708*x[1]*x[9]-0.0574*x[1]*x[10]-0.0747*x[2]*x[3]+0.5194*x[2]*x[4]+0.4049*x[2]*x[5]-0.4841*x[2]*x[6]+0.8754*x[2]*x[7]-0.0878*x[2]*x[8]+0.617*x[2]*x[9]+0.8177*x[2]*x[10]+0.3898*x[3]*x[4]-0.561*x[3]*x[5]+0.7099*x[3]*x[6]+0.4888*x[3]*x[7]-0.3978*x[3]*x[8]+0.3439*x[3]*x[9]+0.2374*x[3]*x[10]+0.9351*x[4]*x[5]+0.9805*x[4]*x[6]-0.324*x[4]*x[7]+0.8415*x[4]*x[8]-0.3219*x[4]*x[9]+0.8619*x[4]*x[10]+0.0931*x[5]*x[6]-0.069*x[5]*x[7]-0.6462*x[5]*x[8]-0.244*x[5]*x[9]-0.6496*x[5]*x[10]-0.2863*x[6]*x[7]+0.3314*x[6]*x[8]+0.2371*x[6]*x[9]-0.0621*x[6]*x[10]-0.3675*x[7]*x[8]-0.4622*x[7]*x[9]-0.6002*x[7]*x[10]-0.1691*x[8]*x[9]+0.9586*x[8]*x[10]+0.0864*x[9]*x[10]-0.741*x[1]+0.6095*x[2]+0.6916*x[3]+0.4181*x[4]+0.0579*x[5]+0.3277*x[6]+0.8015*x[7]+0.8823*x[8]-0.7712*x[9]+0.7333*x[10]+0.9951*x[1]*x[2]*x[3]+0.1336*x[1]*x[2]*x[4]+0.9318*x[1]*x[2]*x[5]+0.4959*x[1]*x[2]*x[6]-0.2652*x[1]*x[2]*x[7]-0.0387*x[1]*x[2]*x[8]-0.8525*x[1]*x[2]*x[9]-0.9893*x[1]*x[2]*x[10]-0.3058*x[1]*x[3]*x[4]-0.3155*x[1]*x[3]*x[5]-0.5641*x[1]*x[3]*x[6]-0.7337*x[1]*x[3]*x[7]+0.801*x[1]*x[3]*x[8]-0.2265*x[1]*x[3]*x[9]-0.109*x[1]*x[3]*x[10]+0.3239*x[1]*x[4]*x[5]-0.9678*x[1]*x[4]*x[6]+0.3017*x[1]*x[4]*x[7]+0.2928*x[1]*x[4]*x[8]-0.354*x[1]*x[4]*x[9]+0.7114*x[1]*x[4]*x[10]-0.1974*x[1]*x[5]*x[6]-0.5863*x[1]*x[5]*x[7]+0.9371*x[1]*x[5]*x[8]+0.1968*x[1]*x[5]*x[9]+0.346*x[1]*x[5]*x[10]-0.0862*x[1]*x[6]*x[7]-0.34*x[1]*x[6]*x[8]-0.7992*x[1]*x[6]*x[9]+0.5109*x[1]*x[6]*x[10]+0.2114*x[1]*x[7]*x[8]+0.4381*x[1]*x[7]*x[9]+0.7947*x[1]*x[7]*x[10]+0.3165*x[1]*x[8]*x[9]-0.6986*x[1]*x[8]*x[10]+0.2246*x[1]*x[9]*x[10]+0.9573*x[2]*x[3]*x[4]+0.9983*x[2]*x[3]*x[5]-0.4864*x[2]*x[3]*x[6]+0.1017*x[2]*x[3]*x[7]+0.3181*x[2]*x[3]*x[8]+0.108*x[2]*x[3]*x[9]+0.9555*x[2]*x[3]*x[10]+0.8038*x[2]*x[4]*x[5]+0.3158*x[2]*x[4]*x[6]+0.4577*x[2]*x[4]*x[7]-0.1951*x[2]*x[4]*x[8]+0.8573*x[2]*x[4]*x[9]-0.7043*x[2]*x[4]*x[10]+0.3491*x[2]*x[5]*x[6]+0.5392*x[2]*x[5]*x[7]-0.3214*x[2]*x[5]*x[8]-0.7684*x[2]*x[5]*x[9]+0.2287*x[2]*x[5]*x[10]+0.6412*x[2]*x[6]*x[7]+0.8942*x[2]*x[6]*x[8]+0.4623*x[2]*x[6]*x[9]-0.0048*x[2]*x[6]*x[10]-0.2504*x[2]*x[7]*x[8]-0.157*x[2]*x[7]*x[9]+0.1058*x[2]*x[7]*x[10]+0.9958*x[2]*x[8]*x[9]+0.9808*x[2]*x[8]*x[10]+0.4926*x[2]*x[9]*x[10]+0.9075*x[3]*x[4]*x[5]-0.8135*x[3]*x[4]*x[6]+0.468*x[3]*x[4]*x[7]+0.5035*x[3]*x[4]*x[8]+0.8937*x[3]*x[4]*x[9]+0.4124*x[3]*x[4]*x[10]+0.6276*x[3]*x[5]*x[6]+0.1172*x[3]*x[5]*x[7]-0.8766*x[3]*x[5]*x[8]-0.0392*x[3]*x[5]*x[9]+0.1954*x[3]*x[5]*x[10]-0.7249*x[3]*x[6]*x[7]+0.1748*x[3]*x[6]*x[8]+0.0399*x[3]*x[6]*x[9]+0.7718*x[3]*x[6]*x[10]-0.3924*x[3]*x[7]*x[8]+0.3393*x[3]*x[7]*x[9]+0.3299*x[3]*x[7]*x[10]+0.0074*x[3]*x[8]*x[9]-0.4768*x[3]*x[8]*x[10]-0.8469*x[3]*x[9]*x[10]-0.7975*x[4]*x[5]*x[6]+0.0985*x[4]*x[5]*x[7]-0.2488*x[4]*x[5]*x[8]-0.9697*x[4]*x[5]*x[9]+0.5858*x[4]*x[5]*x[10]+0.2418*x[4]*x[6]*x[7]+0.5472*x[4]*x[6]*x[8]+0.9072*x[4]*x[6]*x[9]-0.7715*x[4]*x[6]*x[10]-0.3631*x[4]*x[7]*x[8]+0.1936*x[4]*x[7]*x[9]-0.9037*x[4]*x[7]*x[10]-0.7716*x[4]*x[8]*x[9]-0.5681*x[4]*x[8]*x[10]-0.7989*x[4]*x[9]*x[10]-0.8533*x[5]*x[6]*x[7]-0.5063*x[5]*x[6]*x[8]-0.1132*x[5]*x[6]*x[9]-0.5833*x[5]*x[6]*x[10]+0.134*x[5]*x[7]*x[8]-0.9514*x[5]*x[7]*x[9]-0.1594*x[5]*x[7]*x[10]-0.2043*x[5]*x[8]*x[9]+0.9532*x[5]*x[8]*x[10]+0.3852*x[5]*x[9]*x[10]-0.9901*x[6]*x[7]*x[8]-0.7402*x[6]*x[7]*x[9]-0.9064*x[6]*x[7]*x[10]+0.6796*x[6]*x[8]*x[9]+0.357*x[6]*x[8]*x[10]+0.1639*x[6]*x[9]*x[10]+0.4671*x[7]*x[8]*x[9]-0.7679*x[7]*x[8]*x[10]+0.6806*x[7]*x[9]*x[10]+0.67*x[8]*x[9]*x[10])+obj == 0.0) + @NLconstraint(m, e2, 0.9844*x[1]*x[2]-0.5504*x[1]*x[3]+0.8946*x[1]*x[4]+0.6956*x[1]*x[5]+0.4003*x[1]*x[6]+0.1089*x[1]*x[7]-0.1168*x[1]*x[8]-0.5016*x[1]*x[9]+0.7953*x[1]*x[10]-0.7085*x[2]*x[3]-0.1308*x[2]*x[4]-0.0852*x[2]*x[5]-0.3812*x[2]*x[6]-0.0382*x[2]*x[7]+0.3795*x[2]*x[8]+0.6216*x[2]*x[9]-0.2157*x[2]*x[10]-0.4137*x[3]*x[4]+0.152*x[3]*x[5]+0.4507*x[3]*x[6]-0.7145*x[3]*x[7]-0.3329*x[3]*x[8]-0.6792*x[3]*x[9]+0.0692*x[3]*x[10]+0.4467*x[4]*x[5]-0.5436*x[4]*x[6]-0.602*x[4]*x[7]+0.9452*x[4]*x[8]+0.9871*x[4]*x[9]-0.8361*x[4]*x[10]-0.4982*x[5]*x[6]-0.5683*x[5]*x[7]-0.6084*x[5]*x[8]+0.7005*x[5]*x[9]-0.9106*x[5]*x[10]+0.7278*x[6]*x[7]-0.8657*x[6]*x[8]-0.1454*x[6]*x[9]-0.7254*x[6]*x[10]-0.7618*x[7]*x[8]-0.3881*x[7]*x[9]+0.2265*x[7]*x[10]+0.3273*x[8]*x[9]+0.7918*x[8]*x[10]+0.5074*x[9]*x[10]+0.2597*x[1]-0.558*x[2]-0.0323*x[3]+0.23*x[4]+0.9753*x[5]+0.1184*x[6]-0.2582*x[7]-0.3248*x[8]+0.4909*x[9]+0.1395*x[10]+0.2647*x[1]*x[2]*x[3]-0.5144*x[1]*x[2]*x[4]-0.6792*x[1]*x[2]*x[5]-0.9575*x[1]*x[2]*x[6]-0.6195*x[1]*x[2]*x[7]-0.3753*x[1]*x[2]*x[8]+0.6193*x[1]*x[2]*x[9]+0.1474*x[1]*x[2]*x[10]+0.6525*x[1]*x[3]*x[4]-0.4271*x[1]*x[3]*x[5]-0.679*x[1]*x[3]*x[6]-0.3382*x[1]*x[3]*x[7]-0.4683*x[1]*x[3]*x[8]+0.0896*x[1]*x[3]*x[9]+0.107*x[1]*x[3]*x[10]-0.9568*x[1]*x[4]*x[5]-0.7025*x[1]*x[4]*x[6]-0.7902*x[1]*x[4]*x[7]+0.2284*x[1]*x[4]*x[8]-0.1874*x[1]*x[4]*x[9]+0.8031*x[1]*x[4]*x[10]+0.8857*x[1]*x[5]*x[6]-0.6868*x[1]*x[5]*x[7]+0.8739*x[1]*x[5]*x[8]-0.7291*x[1]*x[5]*x[9]-0.2574*x[1]*x[5]*x[10]-0.357*x[1]*x[6]*x[7]+0.4299*x[1]*x[6]*x[8]+0.4594*x[1]*x[6]*x[9]-0.2428*x[1]*x[6]*x[10]+0.6579*x[1]*x[7]*x[8]+0.9073*x[1]*x[7]*x[9]-0.3832*x[1]*x[7]*x[10]+0.1595*x[1]*x[8]*x[9]-0.5331*x[1]*x[8]*x[10]+0.6888*x[1]*x[9]*x[10]-0.4837*x[2]*x[3]*x[4]+0.6795*x[2]*x[3]*x[5]+0.0753*x[2]*x[3]*x[6]+0.2431*x[2]*x[3]*x[7]-0.0184*x[2]*x[3]*x[8]-0.4303*x[2]*x[3]*x[9]-0.5289*x[2]*x[3]*x[10]+0.3028*x[2]*x[4]*x[5]+0.2143*x[2]*x[4]*x[6]-0.2037*x[2]*x[4]*x[7]+0.6976*x[2]*x[4]*x[8]+0.2752*x[2]*x[4]*x[9]-0.4824*x[2]*x[4]*x[10]-0.2823*x[2]*x[5]*x[6]+0.1237*x[2]*x[5]*x[7]-0.7571*x[2]*x[5]*x[8]+0.9569*x[2]*x[5]*x[9]-0.2336*x[2]*x[5]*x[10]+0.4414*x[2]*x[6]*x[7]-0.2835*x[2]*x[6]*x[8]+0.8198*x[2]*x[6]*x[9]+0.0874*x[2]*x[6]*x[10]+0.9194*x[2]*x[7]*x[8]+0.8589*x[2]*x[7]*x[9]+0.2666*x[2]*x[7]*x[10]-0.4088*x[2]*x[8]*x[9]-0.6505*x[2]*x[8]*x[10]+0.6852*x[2]*x[9]*x[10]+0.2372*x[3]*x[4]*x[5]+0.4118*x[3]*x[4]*x[6]-0.5151*x[3]*x[4]*x[7]+0.5959*x[3]*x[4]*x[8]-0.218*x[3]*x[4]*x[9]-0.7801*x[3]*x[4]*x[10]+0.5074*x[3]*x[5]*x[6]-0.9404*x[3]*x[5]*x[7]+0.4013*x[3]*x[5]*x[8]+0.0504*x[3]*x[5]*x[9]+0.5051*x[3]*x[5]*x[10]+0.2954*x[3]*x[6]*x[7]+0.7422*x[3]*x[6]*x[8]+0.6614*x[3]*x[6]*x[9]+0.9144*x[3]*x[6]*x[10]-0.5555*x[3]*x[7]*x[8]+0.159*x[3]*x[7]*x[9]+0.9815*x[3]*x[7]*x[10]+0.6799*x[3]*x[8]*x[9]-0.6504*x[3]*x[8]*x[10]+0.4191*x[3]*x[9]*x[10]-0.3969*x[4]*x[5]*x[6]-0.9499*x[4]*x[5]*x[7]+0.8335*x[4]*x[5]*x[8]+0.3776*x[4]*x[5]*x[9]+0.5135*x[4]*x[5]*x[10]+0.8655*x[4]*x[6]*x[7]-0.89*x[4]*x[6]*x[8]-0.0021*x[4]*x[6]*x[9]-0.881*x[4]*x[6]*x[10]-0.6563*x[4]*x[7]*x[8]+0.3767*x[4]*x[7]*x[9]-0.3868*x[4]*x[7]*x[10]+0.4704*x[4]*x[8]*x[9]+0.5043*x[4]*x[8]*x[10]-0.2086*x[4]*x[9]*x[10]-0.8244*x[5]*x[6]*x[7]-0.9021*x[5]*x[6]*x[8]+0.5587*x[5]*x[6]*x[9]+0.3616*x[5]*x[6]*x[10]-0.3769*x[5]*x[7]*x[8]+0.0455*x[5]*x[7]*x[9]+0.0116*x[5]*x[7]*x[10]-0.1229*x[5]*x[8]*x[9]+0.1753*x[5]*x[8]*x[10]-0.4053*x[5]*x[9]*x[10]-0.4102*x[6]*x[7]*x[8]-0.8524*x[6]*x[7]*x[9]+0.9499*x[6]*x[7]*x[10]+0.4563*x[6]*x[8]*x[9]+0.5162*x[6]*x[8]*x[10]-0.3816*x[6]*x[9]*x[10]-0.507*x[7]*x[8]*x[9]-0.4862*x[7]*x[8]*x[10]+0.2361*x[7]*x[9]*x[10]+0.8756*x[8]*x[9]*x[10] <= 45.614) + @NLconstraint(m, e3, 0.0242*x[1]*x[2]+0.5528*x[1]*x[3]-0.0143*x[1]*x[4]-0.5903*x[1]*x[5]-0.1097*x[1]*x[6]-0.1329*x[1]*x[7]-0.8906*x[1]*x[8]+0.401*x[1]*x[9]+0.8385*x[1]*x[10]-0.222*x[2]*x[3]-0.5022*x[2]*x[4]-0.2673*x[2]*x[5]+0.9973*x[2]*x[6]+0.3242*x[2]*x[7]-0.6405*x[2]*x[8]+0.7448*x[2]*x[9]-0.5121*x[2]*x[10]-0.7672*x[3]*x[4]+0.6364*x[3]*x[5]+0.0713*x[3]*x[6]+0.9761*x[3]*x[7]-0.1674*x[3]*x[8]+0.6164*x[3]*x[9]-0.5201*x[3]*x[10]+0.9405*x[4]*x[5]-0.2474*x[4]*x[6]+0.2668*x[4]*x[7]-0.7262*x[4]*x[8]+0.5369*x[4]*x[9]-0.7976*x[4]*x[10]+0.1039*x[5]*x[6]+0.6633*x[5]*x[7]-0.2455*x[5]*x[8]+0.7355*x[5]*x[9]+0.2493*x[5]*x[10]+0.1046*x[6]*x[7]-0.5768*x[6]*x[8]+0.6454*x[6]*x[9]-0.2728*x[6]*x[10]-0.539*x[7]*x[8]-0.3418*x[7]*x[9]+0.3602*x[7]*x[10]-0.1419*x[8]*x[9]-0.0954*x[8]*x[10]+0.8552*x[9]*x[10]-0.1075*x[1]+0.3345*x[2]+0.5617*x[3]+0.5817*x[4]-0.6045*x[5]-0.4872*x[6]+0.3536*x[7]+0.7971*x[8]-0.25*x[9]-0.9599*x[10]+0.2964*x[1]*x[2]*x[3]+0.3672*x[1]*x[2]*x[4]-0.6592*x[1]*x[2]*x[5]-0.4539*x[1]*x[2]*x[6]-0.1185*x[1]*x[2]*x[7]-0.0846*x[1]*x[2]*x[8]-0.2095*x[1]*x[2]*x[9]+0.3767*x[1]*x[2]*x[10]-0.4022*x[1]*x[3]*x[4]-0.5895*x[1]*x[3]*x[5]-0.6154*x[1]*x[3]*x[6]-0.162*x[1]*x[3]*x[7]+0.3813*x[1]*x[3]*x[8]-0.7189*x[1]*x[3]*x[9]-0.7125*x[1]*x[3]*x[10]+0.3249*x[1]*x[4]*x[5]+0.1514*x[1]*x[4]*x[6]+0.5499*x[1]*x[4]*x[7]+0.5506*x[1]*x[4]*x[8]+0.5307*x[1]*x[4]*x[9]+0.753*x[1]*x[4]*x[10]-0.8016*x[1]*x[5]*x[6]-0.331*x[1]*x[5]*x[7]+0.2902*x[1]*x[5]*x[8]-0.7368*x[1]*x[5]*x[9]+0.6151*x[1]*x[5]*x[10]+0.0837*x[1]*x[6]*x[7]-0.4685*x[1]*x[6]*x[8]-0.0823*x[1]*x[6]*x[9]+0.0219*x[1]*x[6]*x[10]+0.0097*x[1]*x[7]*x[8]+0.9235*x[1]*x[7]*x[9]+0.1005*x[1]*x[7]*x[10]-0.6207*x[1]*x[8]*x[9]-0.5978*x[1]*x[8]*x[10]-0.5025*x[1]*x[9]*x[10]+0.9402*x[2]*x[3]*x[4]+0.5528*x[2]*x[3]*x[5]-0.4546*x[2]*x[3]*x[6]-0.0061*x[2]*x[3]*x[7]-0.2025*x[2]*x[3]*x[8]+0.2266*x[2]*x[3]*x[9]-0.8295*x[2]*x[3]*x[10]+0.474*x[2]*x[4]*x[5]+0.7257*x[2]*x[4]*x[6]-0.3179*x[2]*x[4]*x[7]+0.3889*x[2]*x[4]*x[8]+0.2838*x[2]*x[4]*x[9]-0.829*x[2]*x[4]*x[10]+0.416*x[2]*x[5]*x[6]+0.1849*x[2]*x[5]*x[7]-0.5344*x[2]*x[5]*x[8]-0.8496*x[2]*x[5]*x[9]-0.3513*x[2]*x[5]*x[10]+0.8262*x[2]*x[6]*x[7]-0.5914*x[2]*x[6]*x[8]-0.0945*x[2]*x[6]*x[9]+0.4543*x[2]*x[6]*x[10]-0.9433*x[2]*x[7]*x[8]+0.0341*x[2]*x[7]*x[9]+0.5353*x[2]*x[7]*x[10]+0.7887*x[2]*x[8]*x[9]+0.889*x[2]*x[8]*x[10]-0.4204*x[2]*x[9]*x[10]+0.0629*x[3]*x[4]*x[5]-0.5343*x[3]*x[4]*x[6]-0.3744*x[3]*x[4]*x[7]-0.717*x[3]*x[4]*x[8]-0.3148*x[3]*x[4]*x[9]-0.6929*x[3]*x[4]*x[10]+0.6984*x[3]*x[5]*x[6]+0.9441*x[3]*x[5]*x[7]-0.1182*x[3]*x[5]*x[8]+0.5489*x[3]*x[5]*x[9]-0.0876*x[3]*x[5]*x[10]+0.729*x[3]*x[6]*x[7]+0.456*x[3]*x[6]*x[8]+0.2747*x[3]*x[6]*x[9]+0.4481*x[3]*x[6]*x[10]+0.2084*x[3]*x[7]*x[8]-0.9474*x[3]*x[7]*x[9]-0.4145*x[3]*x[7]*x[10]-0.6056*x[3]*x[8]*x[9]+0.8973*x[3]*x[8]*x[10]+0.0637*x[3]*x[9]*x[10]-0.9793*x[4]*x[5]*x[6]-0.0957*x[4]*x[5]*x[7]+0.9272*x[4]*x[5]*x[8]+0.9722*x[4]*x[5]*x[9]-0.3182*x[4]*x[5]*x[10]+0.9186*x[4]*x[6]*x[7]-0.3466*x[4]*x[6]*x[8]+0.4085*x[4]*x[6]*x[9]+0.5809*x[4]*x[6]*x[10]+0.4471*x[4]*x[7]*x[8]+0.4579*x[4]*x[7]*x[9]-0.1092*x[4]*x[7]*x[10]-0.2364*x[4]*x[8]*x[9]+0.8444*x[4]*x[8]*x[10]+0.4968*x[4]*x[9]*x[10]-0.1465*x[5]*x[6]*x[7]-0.5651*x[5]*x[6]*x[8]+0.4588*x[5]*x[6]*x[9]+0.5938*x[5]*x[6]*x[10]+0.1168*x[5]*x[7]*x[8]+0.7708*x[5]*x[7]*x[9]-0.2337*x[5]*x[7]*x[10]-0.5184*x[5]*x[8]*x[9]-0.3698*x[5]*x[8]*x[10]-0.1342*x[5]*x[9]*x[10]-0.904*x[6]*x[7]*x[8]-0.1518*x[6]*x[7]*x[9]+0.4747*x[6]*x[7]*x[10]+0.7456*x[6]*x[8]*x[9]-0.384*x[6]*x[8]*x[10]+0.6866*x[6]*x[9]*x[10]+0.6322*x[7]*x[8]*x[9]-0.1864*x[7]*x[8]*x[10]+0.73*x[7]*x[9]*x[10]+0.7045*x[8]*x[9]*x[10] <= 40.2) + @NLconstraint(m, e4, (-0.2692*x[1]*x[2])-0.5992*x[1]*x[3]-0.1808*x[1]*x[4]-0.5216*x[1]*x[5]+0.41*x[1]*x[6]-0.8418*x[1]*x[7]-0.5924*x[1]*x[8]-0.9653*x[1]*x[9]-0.3314*x[1]*x[10]-0.4303*x[2]*x[3]+0.6908*x[2]*x[4]-0.0111*x[2]*x[5]+0.4202*x[2]*x[6]-0.4907*x[2]*x[7]+0.6454*x[2]*x[8]-0.4368*x[2]*x[9]+0.2496*x[2]*x[10]+0.4916*x[3]*x[4]+0.7479*x[3]*x[5]-0.7442*x[3]*x[6]-0.4416*x[3]*x[7]+0.847*x[3]*x[8]+0.9726*x[3]*x[9]+0.5786*x[3]*x[10]-0.3041*x[4]*x[5]+0.5286*x[4]*x[6]-0.6138*x[4]*x[7]-0.8712*x[4]*x[8]-0.9096*x[4]*x[9]-0.707*x[4]*x[10]+0.6138*x[5]*x[6]+0.312*x[5]*x[7]-0.5107*x[5]*x[8]-0.3513*x[5]*x[9]+0.9673*x[5]*x[10]+0.2275*x[6]*x[7]-0.415*x[6]*x[8]-0.0089*x[6]*x[9]+0.4723*x[6]*x[10]-0.9209*x[7]*x[8]-0.9687*x[7]*x[9]-0.043*x[7]*x[10]+0.5532*x[8]*x[9]+0.8139*x[8]*x[10]+0.8304*x[9]*x[10]-0.3323*x[1]-0.4014*x[2]+0.6574*x[3]-0.0813*x[4]-0.9703*x[5]-0.3218*x[6]-0.8836*x[7]-0.8145*x[8]+0.3035*x[9]-0.2096*x[10]+0.9819*x[1]*x[2]*x[3]+0.9495*x[1]*x[2]*x[4]+0.9406*x[1]*x[2]*x[5]+0.9377*x[1]*x[2]*x[6]-0.2505*x[1]*x[2]*x[7]-0.8054*x[1]*x[2]*x[8]+0.5014*x[1]*x[2]*x[9]+0.649*x[1]*x[2]*x[10]+0.4489*x[1]*x[3]*x[4]-0.2659*x[1]*x[3]*x[5]+0.2441*x[1]*x[3]*x[6]-0.3874*x[1]*x[3]*x[7]-0.3974*x[1]*x[3]*x[8]+0.3528*x[1]*x[3]*x[9]+0.6601*x[1]*x[3]*x[10]+0.1126*x[1]*x[4]*x[5]+0.1189*x[1]*x[4]*x[6]-0.3444*x[1]*x[4]*x[7]+0.4614*x[1]*x[4]*x[8]-0.6835*x[1]*x[4]*x[9]+0.0658*x[1]*x[4]*x[10]+0.5684*x[1]*x[5]*x[6]-0.5684*x[1]*x[5]*x[7]-0.3494*x[1]*x[5]*x[8]+0.0029*x[1]*x[5]*x[9]-0.5542*x[1]*x[5]*x[10]-0.067*x[1]*x[6]*x[7]-0.6264*x[1]*x[6]*x[8]-0.6098*x[1]*x[6]*x[9]-0.5862*x[1]*x[6]*x[10]+0.8116*x[1]*x[7]*x[8]+0.5998*x[1]*x[7]*x[9]+0.4699*x[1]*x[7]*x[10]-0.1693*x[1]*x[8]*x[9]+0.622*x[1]*x[8]*x[10]+0.9767*x[1]*x[9]*x[10]-0.0178*x[2]*x[3]*x[4]-0.5614*x[2]*x[3]*x[5]+0.5238*x[2]*x[3]*x[6]+0.8146*x[2]*x[3]*x[7]+0.1793*x[2]*x[3]*x[8]+0.7412*x[2]*x[3]*x[9]-0.9228*x[2]*x[3]*x[10]+0.8761*x[2]*x[4]*x[5]-0.9062*x[2]*x[4]*x[6]+0.7942*x[2]*x[4]*x[7]-0.9605*x[2]*x[4]*x[8]+0.9985*x[2]*x[4]*x[9]+0.9604*x[2]*x[4]*x[10]+0.2233*x[2]*x[5]*x[6]+0.1751*x[2]*x[5]*x[7]+0.9245*x[2]*x[5]*x[8]+0.7868*x[2]*x[5]*x[9]-0.5956*x[2]*x[5]*x[10]-0.9745*x[2]*x[6]*x[7]-0.49*x[2]*x[6]*x[8]+0.7809*x[2]*x[6]*x[9]-0.4609*x[2]*x[6]*x[10]+0.778*x[2]*x[7]*x[8]+0.0383*x[2]*x[7]*x[9]-0.2656*x[2]*x[7]*x[10]+0.9676*x[2]*x[8]*x[9]+0.7539*x[2]*x[8]*x[10]+0.3629*x[2]*x[9]*x[10]-0.2751*x[3]*x[4]*x[5]-0.6036*x[3]*x[4]*x[6]-0.6255*x[3]*x[4]*x[7]+0.9753*x[3]*x[4]*x[8]-0.6347*x[3]*x[4]*x[9]-0.9763*x[3]*x[4]*x[10]+0.8874*x[3]*x[5]*x[6]-0.0161*x[3]*x[5]*x[7]+0.9611*x[3]*x[5]*x[8]+0.2266*x[3]*x[5]*x[9]-0.2746*x[3]*x[5]*x[10]+0.0648*x[3]*x[6]*x[7]-0.7084*x[3]*x[6]*x[8]-0.7343*x[3]*x[6]*x[9]-0.2376*x[3]*x[6]*x[10]+0.4007*x[3]*x[7]*x[8]+0.0995*x[3]*x[7]*x[9]+0.6511*x[3]*x[7]*x[10]+0.0747*x[3]*x[8]*x[9]+0.3247*x[3]*x[8]*x[10]-0.8937*x[3]*x[9]*x[10]-0.6571*x[4]*x[5]*x[6]+0.2373*x[4]*x[5]*x[7]+0.5175*x[4]*x[5]*x[8]+0.8201*x[4]*x[5]*x[9]+0.428*x[4]*x[5]*x[10]+0.48*x[4]*x[6]*x[7]-0.2866*x[4]*x[6]*x[8]+0.6437*x[4]*x[6]*x[9]+0.1041*x[4]*x[6]*x[10]+0.3016*x[4]*x[7]*x[8]-0.6249*x[4]*x[7]*x[9]+0.6366*x[4]*x[7]*x[10]-0.9552*x[4]*x[8]*x[9]+0.3144*x[4]*x[8]*x[10]-0.7607*x[4]*x[9]*x[10]-0.2293*x[5]*x[6]*x[7]-0.5147*x[5]*x[6]*x[8]+0.9307*x[5]*x[6]*x[9]-0.0294*x[5]*x[6]*x[10]+0.9847*x[5]*x[7]*x[8]-0.4374*x[5]*x[7]*x[9]+0.9569*x[5]*x[7]*x[10]+0.9057*x[5]*x[8]*x[9]-0.5138*x[5]*x[8]*x[10]-0.1668*x[5]*x[9]*x[10]+0.4716*x[6]*x[7]*x[8]-0.6094*x[6]*x[7]*x[9]+0.2787*x[6]*x[7]*x[10]+0.2594*x[6]*x[8]*x[9]-0.7943*x[6]*x[8]*x[10]-0.7225*x[6]*x[9]*x[10]-0.0902*x[7]*x[8]*x[9]+0.9687*x[7]*x[8]*x[10]-0.1502*x[7]*x[9]*x[10]+0.4096*x[8]*x[9]*x[10] <= 61.993) + @NLconstraint(m, e5, 0.269*x[1]*x[3]-0.0967*x[1]*x[2]-0.5516*x[1]*x[4]-0.2037*x[1]*x[5]+0.6602*x[1]*x[6]-0.722*x[1]*x[7]+0.5119*x[1]*x[8]+0.586*x[1]*x[9]-0.5442*x[1]*x[10]+0.0562*x[2]*x[3]-0.7251*x[2]*x[4]-0.6521*x[2]*x[5]-0.7049*x[2]*x[6]+0.62*x[2]*x[7]-0.497*x[2]*x[8]-0.1799*x[2]*x[9]+0.9132*x[2]*x[10]+0.4395*x[3]*x[4]+0.6708*x[3]*x[5]+0.5537*x[3]*x[6]+0.0758*x[3]*x[7]+0.2226*x[3]*x[8]+0.3882*x[3]*x[9]+0.2014*x[3]*x[10]-0.8073*x[4]*x[5]+0.0984*x[4]*x[6]-0.4142*x[4]*x[7]-0.5883*x[4]*x[8]+0.6861*x[4]*x[9]+0.303*x[4]*x[10]+0.9262*x[5]*x[6]+0.2199*x[5]*x[7]-0.1922*x[5]*x[8]-0.7428*x[5]*x[9]-0.7244*x[5]*x[10]-0.5698*x[6]*x[7]+0.046*x[6]*x[8]+0.4195*x[6]*x[9]+0.0448*x[6]*x[10]-0.6311*x[7]*x[8]+0.7262*x[7]*x[9]-0.3714*x[7]*x[10]-0.9939*x[8]*x[9]+0.9992*x[8]*x[10]+0.7608*x[9]*x[10]-0.5125*x[1]+0.0878*x[2]+0.522*x[3]+0.3632*x[4]-0.1574*x[5]+0.1895*x[6]-0.1071*x[7]+0.889*x[8]-0.6673*x[9]+0.9491*x[10]+0.6504*x[1]*x[2]*x[3]-0.3218*x[1]*x[2]*x[4]-0.3831*x[1]*x[2]*x[5]-0.2782*x[1]*x[2]*x[6]-0.1766*x[1]*x[2]*x[7]-0.0781*x[1]*x[2]*x[8]-0.2352*x[1]*x[2]*x[9]+0.2862*x[1]*x[2]*x[10]-0.5167*x[1]*x[3]*x[4]+0.4314*x[1]*x[3]*x[5]+0.7136*x[1]*x[3]*x[6]-0.6721*x[1]*x[3]*x[7]+0.4626*x[1]*x[3]*x[8]+0.0198*x[1]*x[3]*x[9]-0.4397*x[1]*x[3]*x[10]+0.9861*x[1]*x[4]*x[5]+0.5225*x[1]*x[4]*x[6]-0.9346*x[1]*x[4]*x[7]+0.4133*x[1]*x[4]*x[8]+0.3442*x[1]*x[4]*x[9]-0.8199*x[1]*x[4]*x[10]-0.0776*x[1]*x[5]*x[6]-0.4723*x[1]*x[5]*x[7]-0.289*x[1]*x[5]*x[8]+0.4463*x[1]*x[5]*x[9]-0.9454*x[1]*x[5]*x[10]+0.1697*x[1]*x[6]*x[7]+0.3885*x[1]*x[6]*x[8]-0.7786*x[1]*x[6]*x[9]+0.0525*x[1]*x[6]*x[10]+0.9874*x[1]*x[7]*x[8]+0.4525*x[1]*x[7]*x[9]+0.521*x[1]*x[7]*x[10]-0.5928*x[1]*x[8]*x[9]+0.7265*x[1]*x[8]*x[10]-0.615*x[1]*x[9]*x[10]-0.8237*x[2]*x[3]*x[4]-0.5174*x[2]*x[3]*x[5]+0.821*x[2]*x[3]*x[6]+0.6597*x[2]*x[3]*x[7]-0.8449*x[2]*x[3]*x[8]+0.743*x[2]*x[3]*x[9]+0.1144*x[2]*x[3]*x[10]-0.2056*x[2]*x[4]*x[5]+0.9986*x[2]*x[4]*x[6]+0.54*x[2]*x[4]*x[7]+0.5713*x[2]*x[4]*x[8]+0.5068*x[2]*x[4]*x[9]+0.1204*x[2]*x[4]*x[10]+0.3888*x[2]*x[5]*x[6]+0.7512*x[2]*x[5]*x[7]-0.9713*x[2]*x[5]*x[8]-0.4285*x[2]*x[5]*x[9]-0.6373*x[2]*x[5]*x[10]+0.6154*x[2]*x[6]*x[7]+0.1051*x[2]*x[6]*x[8]-0.0283*x[2]*x[6]*x[9]+0.0735*x[2]*x[6]*x[10]-0.9093*x[2]*x[7]*x[8]-0.7123*x[2]*x[7]*x[9]+0.5603*x[2]*x[7]*x[10]+0.5412*x[2]*x[8]*x[9]-0.6809*x[2]*x[8]*x[10]-0.0621*x[2]*x[9]*x[10]-0.674*x[3]*x[4]*x[5]+0.0977*x[3]*x[4]*x[6]-0.3899*x[3]*x[4]*x[7]-0.6912*x[3]*x[4]*x[8]+0.15*x[3]*x[4]*x[9]-0.7118*x[3]*x[4]*x[10]-0.6134*x[3]*x[5]*x[6]+0.3822*x[3]*x[5]*x[7]+0.9004*x[3]*x[5]*x[8]-0.7372*x[3]*x[5]*x[9]+0.42*x[3]*x[5]*x[10]-0.2405*x[3]*x[6]*x[7]-0.204*x[3]*x[6]*x[8]-0.998*x[3]*x[6]*x[9]-0.1736*x[3]*x[6]*x[10]+0.6076*x[3]*x[7]*x[8]+0.7557*x[3]*x[7]*x[9]-0.7184*x[3]*x[7]*x[10]-0.9139*x[3]*x[8]*x[9]+0.1313*x[3]*x[8]*x[10]-0.8836*x[3]*x[9]*x[10]+0.7427*x[4]*x[5]*x[6]-0.3114*x[4]*x[5]*x[7]-0.0203*x[4]*x[5]*x[8]-0.4356*x[4]*x[5]*x[9]-0.5229*x[4]*x[5]*x[10]+0.0993*x[4]*x[6]*x[7]+0.4277*x[4]*x[6]*x[8]+0.8057*x[4]*x[6]*x[9]+0.5147*x[4]*x[6]*x[10]+0.0785*x[4]*x[7]*x[8]+0.2918*x[4]*x[7]*x[9]+0.5539*x[4]*x[7]*x[10]+0.758*x[4]*x[8]*x[9]+0.2055*x[4]*x[8]*x[10]-0.877*x[4]*x[9]*x[10]-0.1218*x[5]*x[6]*x[7]-0.9826*x[5]*x[6]*x[8]-0.4008*x[5]*x[6]*x[9]+0.947*x[5]*x[6]*x[10]+0.9103*x[5]*x[7]*x[8]-0.5734*x[5]*x[7]*x[9]+0.3479*x[5]*x[7]*x[10]+0.0723*x[5]*x[8]*x[9]-0.2806*x[5]*x[8]*x[10]-0.9973*x[5]*x[9]*x[10]+0.6989*x[6]*x[7]*x[8]-0.1571*x[6]*x[7]*x[9]+0.4957*x[6]*x[7]*x[10]-0.9767*x[6]*x[8]*x[9]+0.2287*x[6]*x[8]*x[10]-0.1111*x[6]*x[9]*x[10]+0.3253*x[7]*x[8]*x[9]+0.3775*x[7]*x[8]*x[10]+0.8783*x[7]*x[9]*x[10]+0.4335*x[8]*x[9]*x[10] <= 8.691) + @NLconstraint(m, e6, (-0.21*x[1]*x[2])-0.5062*x[1]*x[3]-0.8757*x[1]*x[4]+0.8153*x[1]*x[5]+0.0395*x[1]*x[6]-0.8308*x[1]*x[7]-0.2081*x[1]*x[8]-0.797*x[1]*x[9]-0.9042*x[1]*x[10]-0.5208*x[2]*x[3]+0.2869*x[2]*x[4]+0.0977*x[2]*x[5]-0.6313*x[2]*x[6]-0.1462*x[2]*x[7]+0.2552*x[2]*x[8]-0.8255*x[2]*x[9]+0.0742*x[2]*x[10]+0.6895*x[3]*x[4]-0.181*x[3]*x[5]-0.5937*x[3]*x[6]+0.6543*x[3]*x[7]+0.9317*x[3]*x[8]-0.2445*x[3]*x[9]+0.2943*x[3]*x[10]+0.3555*x[4]*x[5]-0.1086*x[4]*x[6]-0.6558*x[4]*x[7]-0.296*x[4]*x[8]-0.3417*x[4]*x[9]+0.4937*x[4]*x[10]-0.457*x[5]*x[6]+0.1226*x[5]*x[7]-0.7351*x[5]*x[8]+0.5968*x[5]*x[9]-0.5881*x[5]*x[10]-0.9469*x[6]*x[7]-0.6075*x[6]*x[8]-0.9843*x[6]*x[9]+0.6435*x[6]*x[10]+0.8889*x[7]*x[8]-0.064*x[7]*x[9]-0.7728*x[7]*x[10]-0.679*x[8]*x[9]+0.6905*x[8]*x[10]+0.7074*x[9]*x[10]-0.3972*x[1]-0.4977*x[2]-0.5983*x[3]-0.4784*x[4]-0.4858*x[5]+0.2572*x[6]-0.0521*x[7]+0.7398*x[8]+0.2972*x[9]+0.7789*x[10]+0.8198*x[1]*x[2]*x[4]-0.6978*x[1]*x[2]*x[3]-0.5889*x[1]*x[2]*x[5]-0.5569*x[1]*x[2]*x[6]-0.7317*x[1]*x[2]*x[7]+0.3949*x[1]*x[2]*x[8]+0.9541*x[1]*x[2]*x[9]-0.9943*x[1]*x[2]*x[10]-0.0116*x[1]*x[3]*x[4]-0.5047*x[1]*x[3]*x[5]+0.8051*x[1]*x[3]*x[6]-0.7914*x[1]*x[3]*x[7]+0.5505*x[1]*x[3]*x[8]-0.7908*x[1]*x[3]*x[9]+0.2414*x[1]*x[3]*x[10]-0.3313*x[1]*x[4]*x[5]+0.9555*x[1]*x[4]*x[6]+0.3839*x[1]*x[4]*x[7]+0.6554*x[1]*x[4]*x[8]+0.9363*x[1]*x[4]*x[9]-0.4451*x[1]*x[4]*x[10]-0.2679*x[1]*x[5]*x[6]-0.6916*x[1]*x[5]*x[7]+0.9618*x[1]*x[5]*x[8]+0.8635*x[1]*x[5]*x[9]-0.5314*x[1]*x[5]*x[10]-0.7532*x[1]*x[6]*x[7]-0.2676*x[1]*x[6]*x[8]+0.6789*x[1]*x[6]*x[9]-0.7484*x[1]*x[6]*x[10]+0.9799*x[1]*x[7]*x[8]-0.04*x[1]*x[7]*x[9]+0.9229*x[1]*x[7]*x[10]+0.9211*x[1]*x[8]*x[9]+0.5065*x[1]*x[8]*x[10]+0.2912*x[1]*x[9]*x[10]+0.3298*x[2]*x[3]*x[4]+0.7586*x[2]*x[3]*x[5]+0.4593*x[2]*x[3]*x[6]+0.3926*x[2]*x[3]*x[7]+0.0687*x[2]*x[3]*x[8]+0.4976*x[2]*x[3]*x[9]+0.6535*x[2]*x[3]*x[10]-0.9917*x[2]*x[4]*x[5]-0.5502*x[2]*x[4]*x[6]-0.1718*x[2]*x[4]*x[7]+0.2573*x[2]*x[4]*x[8]-0.9025*x[2]*x[4]*x[9]+0.3264*x[2]*x[4]*x[10]-0.6443*x[2]*x[5]*x[6]+0.1642*x[2]*x[5]*x[7]+0.9221*x[2]*x[5]*x[8]-0.428*x[2]*x[5]*x[9]-0.4399*x[2]*x[5]*x[10]+0.7566*x[2]*x[6]*x[7]+0.354*x[2]*x[6]*x[8]-0.5276*x[2]*x[6]*x[9]-0.6272*x[2]*x[6]*x[10]-0.8758*x[2]*x[7]*x[8]-0.6662*x[2]*x[7]*x[9]-0.5727*x[2]*x[7]*x[10]-0.1467*x[2]*x[8]*x[9]-0.8066*x[2]*x[8]*x[10]-0.53*x[2]*x[9]*x[10]-0.7406*x[3]*x[4]*x[5]+0.8858*x[3]*x[4]*x[6]-0.3289*x[3]*x[4]*x[7]-0.8604*x[3]*x[4]*x[8]-0.0148*x[3]*x[4]*x[9]+0.3933*x[3]*x[4]*x[10]+0.4846*x[3]*x[5]*x[6]-0.7567*x[3]*x[5]*x[7]+0.083*x[3]*x[5]*x[8]-0.0985*x[3]*x[5]*x[9]+0.3703*x[3]*x[5]*x[10]+0.6679*x[3]*x[6]*x[7]+0.8643*x[3]*x[6]*x[8]+0.533*x[3]*x[6]*x[9]+0.1871*x[3]*x[6]*x[10]-0.1905*x[3]*x[7]*x[8]+0.9994*x[3]*x[7]*x[9]-0.7306*x[3]*x[7]*x[10]-0.2797*x[3]*x[8]*x[9]-0.7742*x[3]*x[8]*x[10]+0.2634*x[3]*x[9]*x[10]-0.6882*x[4]*x[5]*x[6]-0.1916*x[4]*x[5]*x[7]-0.6292*x[4]*x[5]*x[8]+0.3706*x[4]*x[5]*x[9]+0.2252*x[4]*x[5]*x[10]-0.5111*x[4]*x[6]*x[7]-0.7106*x[4]*x[6]*x[8]+0.436*x[4]*x[6]*x[9]+0.6397*x[4]*x[6]*x[10]-0.7626*x[4]*x[7]*x[8]-0.7465*x[4]*x[7]*x[9]-0.4273*x[4]*x[7]*x[10]+0.9735*x[4]*x[8]*x[9]-0.5091*x[4]*x[8]*x[10]-0.0217*x[4]*x[9]*x[10]-0.9406*x[5]*x[6]*x[7]-0.5301*x[5]*x[6]*x[8]-0.0925*x[5]*x[6]*x[9]-0.4232*x[5]*x[6]*x[10]+0.4301*x[5]*x[7]*x[8]-0.1282*x[5]*x[7]*x[9]+0.2232*x[5]*x[7]*x[10]+0.124*x[5]*x[8]*x[9]-0.3137*x[5]*x[8]*x[10]+0.5432*x[5]*x[9]*x[10]-0.0037*x[6]*x[7]*x[8]-0.0924*x[6]*x[7]*x[9]+0.3913*x[6]*x[7]*x[10]-0.6371*x[6]*x[8]*x[9]-0.1172*x[6]*x[8]*x[10]-0.1265*x[6]*x[9]*x[10]-0.8825*x[7]*x[8]*x[9]-0.2623*x[7]*x[8]*x[10]-0.1383*x[7]*x[9]*x[10]-0.6027*x[8]*x[9]*x[10] <= 79.525) + @NLconstraint(m, e7, 0.9658*x[1]*x[2]-0.8057*x[1]*x[3]+0.2716*x[1]*x[4]-0.8667*x[1]*x[5]-0.6541*x[1]*x[6]-0.0723*x[1]*x[7]-0.1218*x[1]*x[8]+0.6082*x[1]*x[9]-0.1423*x[1]*x[10]+0.5249*x[2]*x[3]+0.4167*x[2]*x[4]-0.507*x[2]*x[5]+0.8024*x[2]*x[6]-0.8732*x[2]*x[7]-0.9641*x[2]*x[8]+0.8948*x[2]*x[9]-0.0228*x[2]*x[10]-0.2308*x[3]*x[4]-0.8365*x[3]*x[5]-0.0407*x[3]*x[6]-0.6009*x[3]*x[7]-0.2916*x[3]*x[8]-0.1374*x[3]*x[9]+0.8125*x[3]*x[10]+0.8725*x[4]*x[5]+0.4909*x[4]*x[6]+0.9356*x[4]*x[7]+0.7571*x[4]*x[8]-0.4834*x[4]*x[9]+0.5875*x[4]*x[10]-0.8418*x[5]*x[6]-0.9637*x[5]*x[7]-0.3318*x[5]*x[8]-0.3304*x[5]*x[9]+0.0086*x[5]*x[10]-0.2382*x[6]*x[7]+0.7865*x[6]*x[8]-0.4775*x[6]*x[9]-0.0112*x[6]*x[10]+0.4793*x[7]*x[8]+0.2361*x[7]*x[9]+0.3537*x[7]*x[10]+0.4693*x[8]*x[9]+0.7316*x[8]*x[10]+0.3182*x[9]*x[10]+0.8041*x[1]-0.4561*x[2]+0.8676*x[3]-0.7196*x[4]-0.3273*x[5]-0.0517*x[6]-0.9975*x[7]-0.5365*x[8]+0.9168*x[9]+0.7715*x[10]+0.7603*x[1]*x[2]*x[3]-0.5705*x[1]*x[2]*x[4]+0.9037*x[1]*x[2]*x[5]+0.4382*x[1]*x[2]*x[6]-0.7787*x[1]*x[2]*x[7]+0.9149*x[1]*x[2]*x[8]+0.2939*x[1]*x[2]*x[9]+0.1637*x[1]*x[2]*x[10]-0.9742*x[1]*x[3]*x[4]-0.4477*x[1]*x[3]*x[5]+0.6009*x[1]*x[3]*x[6]-0.3442*x[1]*x[3]*x[7]+0.1588*x[1]*x[3]*x[8]-0.9521*x[1]*x[3]*x[9]+0.3398*x[1]*x[3]*x[10]-0.6371*x[1]*x[4]*x[5]-0.4268*x[1]*x[4]*x[6]+0.3169*x[1]*x[4]*x[7]+0.1779*x[1]*x[4]*x[8]-0.8726*x[1]*x[4]*x[9]-0.7344*x[1]*x[4]*x[10]+0.4833*x[1]*x[5]*x[6]+0.0007*x[1]*x[5]*x[7]-0.9371*x[1]*x[5]*x[8]+0.9815*x[1]*x[5]*x[9]-0.9932*x[1]*x[5]*x[10]+0.3986*x[1]*x[6]*x[7]+0.5181*x[1]*x[6]*x[8]-0.4916*x[1]*x[6]*x[9]-0.3371*x[1]*x[6]*x[10]+0.1457*x[1]*x[7]*x[8]+0.9832*x[1]*x[7]*x[9]-0.0207*x[1]*x[7]*x[10]+0.1223*x[1]*x[8]*x[9]+0.2128*x[1]*x[8]*x[10]-0.8286*x[1]*x[9]*x[10]-0.4837*x[2]*x[3]*x[4]-0.0592*x[2]*x[3]*x[5]+0.6266*x[2]*x[3]*x[6]+0.4492*x[2]*x[3]*x[7]+0.9861*x[2]*x[3]*x[8]-0.8687*x[2]*x[3]*x[9]-0.8504*x[2]*x[3]*x[10]+0.6624*x[2]*x[4]*x[5]-0.1745*x[2]*x[4]*x[6]+0.3241*x[2]*x[4]*x[7]-0.4919*x[2]*x[4]*x[8]-0.0339*x[2]*x[4]*x[9]+0.2248*x[2]*x[4]*x[10]+0.366*x[2]*x[5]*x[6]-0.1987*x[2]*x[5]*x[7]-0.5784*x[2]*x[5]*x[8]+0.8198*x[2]*x[5]*x[9]-0.0486*x[2]*x[5]*x[10]+0.7126*x[2]*x[6]*x[7]+0.8337*x[2]*x[6]*x[8]+0.0308*x[2]*x[6]*x[9]+0.4378*x[2]*x[6]*x[10]-0.4249*x[2]*x[7]*x[8]-0.876*x[2]*x[7]*x[9]-0.247*x[2]*x[7]*x[10]-0.482*x[2]*x[8]*x[9]+0.0808*x[2]*x[8]*x[10]+0.0687*x[2]*x[9]*x[10]-0.9379*x[3]*x[4]*x[5]-0.1556*x[3]*x[4]*x[6]-0.1534*x[3]*x[4]*x[7]+0.2972*x[3]*x[4]*x[8]-0.682*x[3]*x[4]*x[9]-0.2246*x[3]*x[4]*x[10]+0.2078*x[3]*x[5]*x[6]+0.0801*x[3]*x[5]*x[7]+0.412*x[3]*x[5]*x[8]-0.7653*x[3]*x[5]*x[9]+0.7097*x[3]*x[5]*x[10]+0.1609*x[3]*x[6]*x[7]+0.0463*x[3]*x[6]*x[8]-0.049*x[3]*x[6]*x[9]-0.9321*x[3]*x[6]*x[10]+0.5337*x[3]*x[7]*x[8]+0.6369*x[3]*x[7]*x[9]-0.8873*x[3]*x[7]*x[10]-0.5746*x[3]*x[8]*x[9]+0.4865*x[3]*x[8]*x[10]-0.3803*x[3]*x[9]*x[10]-0.7699*x[4]*x[5]*x[6]+0.7363*x[4]*x[5]*x[7]-0.2812*x[4]*x[5]*x[8]+0.8172*x[4]*x[5]*x[9]-0.5754*x[4]*x[5]*x[10]-0.2821*x[4]*x[6]*x[7]-0.8113*x[4]*x[6]*x[8]+0.3038*x[4]*x[6]*x[9]+0.8093*x[4]*x[6]*x[10]+0.5277*x[4]*x[7]*x[8]+0.7849*x[4]*x[7]*x[9]+0.6706*x[4]*x[7]*x[10]+0.0152*x[4]*x[8]*x[9]-0.009*x[4]*x[8]*x[10]+0.0082*x[4]*x[9]*x[10]+0.5372*x[5]*x[6]*x[7]-0.2333*x[5]*x[6]*x[8]-0.8164*x[5]*x[6]*x[9]+0.8521*x[5]*x[6]*x[10]+0.4163*x[5]*x[7]*x[8]+0.6625*x[5]*x[7]*x[9]+0.6022*x[5]*x[7]*x[10]+0.1782*x[5]*x[8]*x[9]+0.63*x[5]*x[8]*x[10]+0.4385*x[5]*x[9]*x[10]+0.9963*x[6]*x[7]*x[8]+0.8737*x[6]*x[7]*x[9]+0.382*x[6]*x[7]*x[10]+0.4417*x[6]*x[8]*x[9]+0.2669*x[6]*x[8]*x[10]+0.7712*x[6]*x[9]*x[10]+0.5226*x[7]*x[8]*x[9]+0.3681*x[7]*x[8]*x[10]+0.7255*x[7]*x[9]*x[10]-0.4059*x[8]*x[9]*x[10] <= 55.647) + @NLconstraint(m, e8, 0.5619*x[1]*x[2]+0.6594*x[1]*x[3]-0.6765*x[1]*x[4]+0.8412*x[1]*x[5]-0.6171*x[1]*x[6]+0.5953*x[1]*x[7]+0.9679*x[1]*x[8]+0.7684*x[1]*x[9]+0.3959*x[1]*x[10]+0.61*x[2]*x[3]+0.6235*x[2]*x[4]-0.2316*x[2]*x[5]+0.2738*x[2]*x[6]-0.5261*x[2]*x[7]+0.6011*x[2]*x[8]+0.421*x[2]*x[9]-0.9893*x[2]*x[10]-0.5615*x[3]*x[4]+0.7985*x[3]*x[5]+0.1976*x[3]*x[6]-0.1837*x[3]*x[7]-0.7994*x[3]*x[8]-0.7895*x[3]*x[9]+0.146*x[3]*x[10]-0.5227*x[4]*x[5]+0.3006*x[4]*x[6]+0.8038*x[4]*x[7]-0.0596*x[4]*x[8]+0.152*x[4]*x[9]+0.5178*x[4]*x[10]-0.1747*x[5]*x[6]+0.9976*x[5]*x[7]+0.1196*x[5]*x[8]-0.5697*x[5]*x[9]-0.8498*x[5]*x[10]-0.6921*x[6]*x[7]-0.0832*x[6]*x[8]+0.7875*x[6]*x[9]+0.2374*x[6]*x[10]+0.2773*x[7]*x[8]+0.8304*x[7]*x[9]-0.2771*x[7]*x[10]+0.8288*x[8]*x[9]-0.6953*x[8]*x[10]+0.9491*x[9]*x[10]-0.1701*x[1]+0.4837*x[2]-0.9392*x[3]-0.0295*x[4]+0.8232*x[5]+0.8049*x[6]+0.8403*x[7]+0.0402*x[8]+0.4708*x[9]+0.653*x[10]+(-0.3254*x[1]*x[2]*x[3])-0.6267*x[1]*x[2]*x[4]-0.2341*x[1]*x[2]*x[5]+0.332*x[1]*x[2]*x[6]+0.8281*x[1]*x[2]*x[7]-0.1747*x[1]*x[2]*x[8]+0.9767*x[1]*x[2]*x[9]-0.6643*x[1]*x[2]*x[10]-0.7506*x[1]*x[3]*x[4]+0.0168*x[1]*x[3]*x[5]-0.0513*x[1]*x[3]*x[6]-0.6878*x[1]*x[3]*x[7]-0.0265*x[1]*x[3]*x[8]+0.6138*x[1]*x[3]*x[9]+0.9757*x[1]*x[3]*x[10]-0.8293*x[1]*x[4]*x[5]+0.9219*x[1]*x[4]*x[6]+0.403*x[1]*x[4]*x[7]-0.0383*x[1]*x[4]*x[8]-0.1156*x[1]*x[4]*x[9]-0.9505*x[1]*x[4]*x[10]-0.5166*x[1]*x[5]*x[6]-0.7652*x[1]*x[5]*x[7]-0.9915*x[1]*x[5]*x[8]-0.477*x[1]*x[5]*x[9]+0.1948*x[1]*x[5]*x[10]-0.9361*x[1]*x[6]*x[7]-0.0442*x[1]*x[6]*x[8]-0.4517*x[1]*x[6]*x[9]-0.8448*x[1]*x[6]*x[10]-0.8462*x[1]*x[7]*x[8]+0.7179*x[1]*x[7]*x[9]+0.1438*x[1]*x[7]*x[10]-0.831*x[1]*x[8]*x[9]+0.1377*x[1]*x[8]*x[10]+0.2404*x[1]*x[9]*x[10]+0.4776*x[2]*x[3]*x[4]+0.9781*x[2]*x[3]*x[5]-0.4061*x[2]*x[3]*x[6]-0.8912*x[2]*x[3]*x[7]+0.9125*x[2]*x[3]*x[8]+0.706*x[2]*x[3]*x[9]-0.8906*x[2]*x[3]*x[10]+0.942*x[2]*x[4]*x[5]-0.0261*x[2]*x[4]*x[6]-0.068*x[2]*x[4]*x[7]-0.847*x[2]*x[4]*x[8]+0.5746*x[2]*x[4]*x[9]-0.3526*x[2]*x[4]*x[10]+0.4389*x[2]*x[5]*x[6]+0.4542*x[2]*x[5]*x[7]+0.0367*x[2]*x[5]*x[8]-0.3709*x[2]*x[5]*x[9]+0.8193*x[2]*x[5]*x[10]+0.5633*x[2]*x[6]*x[7]-0.0382*x[2]*x[6]*x[8]-0.959*x[2]*x[6]*x[9]-0.7036*x[2]*x[6]*x[10]+0.7485*x[2]*x[7]*x[8]-0.0868*x[2]*x[7]*x[9]-0.6044*x[2]*x[7]*x[10]+0.3054*x[2]*x[8]*x[9]+0.6064*x[2]*x[8]*x[10]-0.5288*x[2]*x[9]*x[10]-0.0285*x[3]*x[4]*x[5]-0.5481*x[3]*x[4]*x[6]-0.7647*x[3]*x[4]*x[7]+0.6671*x[3]*x[4]*x[8]-0.0921*x[3]*x[4]*x[9]+0.7822*x[3]*x[4]*x[10]-0.688*x[3]*x[5]*x[6]-0.623*x[3]*x[5]*x[7]-0.6958*x[3]*x[5]*x[8]+0.2072*x[3]*x[5]*x[9]+0.8573*x[3]*x[5]*x[10]+0.9353*x[3]*x[6]*x[7]-0.7581*x[3]*x[6]*x[8]-0.6678*x[3]*x[6]*x[9]+0.7244*x[3]*x[6]*x[10]+0.497*x[3]*x[7]*x[8]+0.8841*x[3]*x[7]*x[9]-0.419*x[3]*x[7]*x[10]-0.5639*x[3]*x[8]*x[9]+0.3384*x[3]*x[8]*x[10]+0.8517*x[3]*x[9]*x[10]+0.2487*x[4]*x[5]*x[6]+0.352*x[4]*x[5]*x[7]-0.9956*x[4]*x[5]*x[8]+0.1963*x[4]*x[5]*x[9]+0.6505*x[4]*x[5]*x[10]+0.8868*x[4]*x[6]*x[7]+0.064*x[4]*x[6]*x[8]-0.2306*x[4]*x[6]*x[9]+0.3456*x[4]*x[6]*x[10]-0.0124*x[4]*x[7]*x[8]-0.7644*x[4]*x[7]*x[9]-0.9407*x[4]*x[7]*x[10]-0.5041*x[4]*x[8]*x[9]-0.4612*x[4]*x[8]*x[10]+0.6372*x[4]*x[9]*x[10]-0.9423*x[5]*x[6]*x[7]+0.4769*x[5]*x[6]*x[8]+0.6691*x[5]*x[6]*x[9]-0.6518*x[5]*x[6]*x[10]+0.5892*x[5]*x[7]*x[8]+0.1282*x[5]*x[7]*x[9]-0.0097*x[5]*x[7]*x[10]-0.0037*x[5]*x[8]*x[9]-0.4974*x[5]*x[8]*x[10]-0.1368*x[5]*x[9]*x[10]-0.663*x[6]*x[7]*x[8]-0.3471*x[6]*x[7]*x[9]-0.9665*x[6]*x[7]*x[10]-0.6331*x[6]*x[8]*x[9]-0.0998*x[6]*x[8]*x[10]+0.9348*x[6]*x[9]*x[10]-0.5585*x[7]*x[8]*x[9]-0.1588*x[7]*x[8]*x[10]+0.3535*x[7]*x[9]*x[10]-0.5013*x[8]*x[9]*x[10] <= 70.358) + @NLconstraint(m, e9, 0.5066*x[1]*x[2]+0.5209*x[1]*x[3]-0.8096*x[1]*x[4]+0.2097*x[1]*x[5]-0.8223*x[1]*x[6]+0.8219*x[1]*x[7]+0.8915*x[1]*x[8]+0.4384*x[1]*x[9]+0.0104*x[1]*x[10]-0.6145*x[2]*x[3]+0.3569*x[2]*x[4]-0.0835*x[2]*x[5]-0.1778*x[2]*x[6]+0.1688*x[2]*x[7]-0.6302*x[2]*x[8]+0.0573*x[2]*x[9]+0.8851*x[2]*x[10]+0.9515*x[3]*x[4]-0.0604*x[3]*x[5]-0.8915*x[3]*x[6]-0.0968*x[3]*x[7]-0.5954*x[3]*x[8]-0.902*x[3]*x[9]+0.9315*x[3]*x[10]+0.4294*x[4]*x[5]+0.7398*x[4]*x[6]-0.6759*x[4]*x[7]-0.0166*x[4]*x[8]+0.3176*x[4]*x[9]-0.434*x[4]*x[10]-0.8219*x[5]*x[6]-0.9323*x[5]*x[7]-0.2384*x[5]*x[8]+0.2604*x[5]*x[9]+0.4567*x[5]*x[10]+0.7508*x[6]*x[7]+0.1384*x[6]*x[8]-0.5557*x[6]*x[9]-0.2385*x[6]*x[10]+0.0199*x[7]*x[8]+0.7632*x[7]*x[9]-0.9947*x[7]*x[10]-0.3877*x[8]*x[9]+0.8177*x[8]*x[10]-0.3725*x[9]*x[10]-0.3487*x[1]-0.8521*x[2]+0.7201*x[3]-0.9411*x[4]-0.6075*x[5]+0.4446*x[6]-0.6889*x[7]+0.5368*x[8]+0.9675*x[9]-0.1386*x[10]+0.3477*x[1]*x[2]*x[3]-0.8469*x[1]*x[2]*x[4]-0.0643*x[1]*x[2]*x[5]+0.9855*x[1]*x[2]*x[6]+0.169*x[1]*x[2]*x[7]+0.1277*x[1]*x[2]*x[8]+0.1701*x[1]*x[2]*x[9]-0.2288*x[1]*x[2]*x[10]+0.6269*x[1]*x[3]*x[4]-0.165*x[1]*x[3]*x[5]-0.3328*x[1]*x[3]*x[6]+0.0711*x[1]*x[3]*x[7]+0.8548*x[1]*x[3]*x[8]+0.4886*x[1]*x[3]*x[9]-0.4103*x[1]*x[3]*x[10]+0.1394*x[1]*x[4]*x[5]-0.3792*x[1]*x[4]*x[6]-0.061*x[1]*x[4]*x[7]-0.6923*x[1]*x[4]*x[8]+0.194*x[1]*x[4]*x[9]-0.2253*x[1]*x[4]*x[10]-0.6197*x[1]*x[5]*x[6]-0.799*x[1]*x[5]*x[7]-0.9851*x[1]*x[5]*x[8]-0.164*x[1]*x[5]*x[9]+0.1448*x[1]*x[5]*x[10]+0.0185*x[1]*x[6]*x[7]+0.3829*x[1]*x[6]*x[8]+0.2687*x[1]*x[6]*x[9]+0.9428*x[1]*x[6]*x[10]+0.9418*x[1]*x[7]*x[8]+0.4694*x[1]*x[7]*x[9]+0.8523*x[1]*x[7]*x[10]-0.87*x[1]*x[8]*x[9]-0.5796*x[1]*x[8]*x[10]-0.486*x[1]*x[9]*x[10]+0.3746*x[2]*x[3]*x[4]+0.4788*x[2]*x[3]*x[5]+0.0586*x[2]*x[3]*x[6]+0.1473*x[2]*x[3]*x[7]+0.2498*x[2]*x[3]*x[8]-0.6388*x[2]*x[3]*x[9]+0.2472*x[2]*x[3]*x[10]-0.3687*x[2]*x[4]*x[5]+0.3536*x[2]*x[4]*x[6]+0.0072*x[2]*x[4]*x[7]-0.5806*x[2]*x[4]*x[8]-0.5058*x[2]*x[4]*x[9]-0.116*x[2]*x[4]*x[10]+0.191*x[2]*x[5]*x[6]+0.3699*x[2]*x[5]*x[7]+0.3731*x[2]*x[5]*x[8]+0.0031*x[2]*x[5]*x[9]+0.9294*x[2]*x[5]*x[10]-0.6047*x[2]*x[6]*x[7]+0.2348*x[2]*x[6]*x[8]+0.8324*x[2]*x[6]*x[9]+0.6608*x[2]*x[6]*x[10]-0.1673*x[2]*x[7]*x[8]-0.9519*x[2]*x[7]*x[9]+0.8066*x[2]*x[7]*x[10]-0.9313*x[2]*x[8]*x[9]-0.0297*x[2]*x[8]*x[10]-0.7382*x[2]*x[9]*x[10]-0.672*x[3]*x[4]*x[5]+0.3061*x[3]*x[4]*x[6]-0.1984*x[3]*x[4]*x[7]-0.8696*x[3]*x[4]*x[8]-0.5035*x[3]*x[4]*x[9]+0.2835*x[3]*x[4]*x[10]+0.2576*x[3]*x[5]*x[6]-0.5016*x[3]*x[5]*x[7]-0.738*x[3]*x[5]*x[8]-0.6402*x[3]*x[5]*x[9]+0.2333*x[3]*x[5]*x[10]-0.1863*x[3]*x[6]*x[7]+0.6045*x[3]*x[6]*x[8]-0.5819*x[3]*x[6]*x[9]-0.809*x[3]*x[6]*x[10]-0.3189*x[3]*x[7]*x[8]+0.802*x[3]*x[7]*x[9]-0.8383*x[3]*x[7]*x[10]+0.3569*x[3]*x[8]*x[9]+0.0003*x[3]*x[8]*x[10]+0.8089*x[3]*x[9]*x[10]-0.875*x[4]*x[5]*x[6]+0.4462*x[4]*x[5]*x[7]-0.3338*x[4]*x[5]*x[8]+0.1814*x[4]*x[5]*x[9]-0.8771*x[4]*x[5]*x[10]-0.9101*x[4]*x[6]*x[7]+0.1635*x[4]*x[6]*x[8]-0.1352*x[4]*x[6]*x[9]-0.8026*x[4]*x[6]*x[10]+0.9155*x[4]*x[7]*x[8]+0.5442*x[4]*x[7]*x[9]-0.7053*x[4]*x[7]*x[10]+0.4455*x[4]*x[8]*x[9]+0.9929*x[4]*x[8]*x[10]-0.3529*x[4]*x[9]*x[10]-0.8803*x[5]*x[6]*x[7]-0.9694*x[5]*x[6]*x[8]+0.7938*x[5]*x[6]*x[9]+0.664*x[5]*x[6]*x[10]+0.5083*x[5]*x[7]*x[8]-0.3124*x[5]*x[7]*x[9]-0.4061*x[5]*x[7]*x[10]+0.0858*x[5]*x[8]*x[9]-0.2714*x[5]*x[8]*x[10]-0.8232*x[5]*x[9]*x[10]-0.1146*x[6]*x[7]*x[8]+0.9703*x[6]*x[7]*x[9]+0.9858*x[6]*x[7]*x[10]+0.859*x[6]*x[8]*x[9]+0.0264*x[6]*x[8]*x[10]-0.8325*x[6]*x[9]*x[10]-0.2402*x[7]*x[8]*x[9]+0.9962*x[7]*x[8]*x[10]-0.612*x[7]*x[9]*x[10]-0.7468*x[8]*x[9]*x[10] <= 27.631) + @NLconstraint(m, e10, 0.6845*x[1]*x[2]-0.7219*x[1]*x[3]+0.7798*x[1]*x[4]+0.0733*x[1]*x[5]-0.7376*x[1]*x[6]+0.0256*x[1]*x[7]-0.2386*x[1]*x[8]+0.8016*x[1]*x[9]+0.6794*x[1]*x[10]+0.6011*x[2]*x[3]-0.1622*x[2]*x[4]-0.0369*x[2]*x[5]-0.5992*x[2]*x[6]+0.9241*x[2]*x[7]+0.9873*x[2]*x[8]+0.5992*x[2]*x[9]+0.8133*x[2]*x[10]+0.4239*x[3]*x[4]-0.1981*x[3]*x[5]+0.5006*x[3]*x[6]-0.5385*x[3]*x[7]+0.1593*x[3]*x[8]-0.0871*x[3]*x[9]-0.9382*x[3]*x[10]-0.0148*x[4]*x[5]-0.4904*x[4]*x[6]+0.5096*x[4]*x[7]-0.4809*x[4]*x[8]-0.4848*x[4]*x[9]+0.3062*x[4]*x[10]+0.9318*x[5]*x[6]-0.1853*x[5]*x[7]+0.5946*x[5]*x[8]-0.9998*x[5]*x[9]+0.054*x[5]*x[10]+0.9006*x[6]*x[7]-0.322*x[6]*x[8]-0.4127*x[6]*x[9]-0.6934*x[6]*x[10]+0.408*x[7]*x[8]-0.6923*x[7]*x[9]-0.0869*x[7]*x[10]-0.0219*x[8]*x[9]+0.4814*x[8]*x[10]-0.0782*x[9]*x[10]-0.3978*x[1]-0.0586*x[2]+0.8491*x[3]-0.9975*x[4]+0.5027*x[5]+0.496*x[6]-0.6663*x[7]+0.2055*x[8]-0.1878*x[9]+0.5555*x[10]+(-0.8875*x[1]*x[2]*x[3])-0.7171*x[1]*x[2]*x[4]-0.2179*x[1]*x[2]*x[5]-0.317*x[1]*x[2]*x[6]-0.0332*x[1]*x[2]*x[7]-0.625*x[1]*x[2]*x[8]+0.2913*x[1]*x[2]*x[9]+0.0755*x[1]*x[2]*x[10]-0.0178*x[1]*x[3]*x[4]-0.215*x[1]*x[3]*x[5]-0.7588*x[1]*x[3]*x[6]+0.2416*x[1]*x[3]*x[7]-0.1383*x[1]*x[3]*x[8]+0.2175*x[1]*x[3]*x[9]-0.5311*x[1]*x[3]*x[10]-0.6322*x[1]*x[4]*x[5]-0.8211*x[1]*x[4]*x[6]-0.2421*x[1]*x[4]*x[7]-0.9794*x[1]*x[4]*x[8]+0.6866*x[1]*x[4]*x[9]+0.144*x[1]*x[4]*x[10]+0.935*x[1]*x[5]*x[6]-0.7224*x[1]*x[5]*x[7]-0.79*x[1]*x[5]*x[8]-0.6261*x[1]*x[5]*x[9]-0.59*x[1]*x[5]*x[10]+0.8708*x[1]*x[6]*x[7]+0.5423*x[1]*x[6]*x[8]+0.3356*x[1]*x[6]*x[9]+0.142*x[1]*x[6]*x[10]+0.5119*x[1]*x[7]*x[8]+0.7599*x[1]*x[7]*x[9]-0.4022*x[1]*x[7]*x[10]+0.4446*x[1]*x[8]*x[9]-0.8166*x[1]*x[8]*x[10]+0.6446*x[1]*x[9]*x[10]-0.1284*x[2]*x[3]*x[4]-0.3651*x[2]*x[3]*x[5]-0.2567*x[2]*x[3]*x[6]+0.1421*x[2]*x[3]*x[7]-0.8825*x[2]*x[3]*x[8]-0.6058*x[2]*x[3]*x[9]+0.503*x[2]*x[3]*x[10]-0.0462*x[2]*x[4]*x[5]-0.717*x[2]*x[4]*x[6]+0.0253*x[2]*x[4]*x[7]-0.9476*x[2]*x[4]*x[8]-0.3171*x[2]*x[4]*x[9]+0.5691*x[2]*x[4]*x[10]-0.3612*x[2]*x[5]*x[6]+0.0488*x[2]*x[5]*x[7]+0.423*x[2]*x[5]*x[8]+0.2762*x[2]*x[5]*x[9]+0.0221*x[2]*x[5]*x[10]+0.3975*x[2]*x[6]*x[7]-0.5281*x[2]*x[6]*x[8]-0.722*x[2]*x[6]*x[9]-0.1433*x[2]*x[6]*x[10]+0.1957*x[2]*x[7]*x[8]+0.7882*x[2]*x[7]*x[9]+0.9988*x[2]*x[7]*x[10]+0.8552*x[2]*x[8]*x[9]+0.3681*x[2]*x[8]*x[10]-0.6187*x[2]*x[9]*x[10]-0.2208*x[3]*x[4]*x[5]-0.8222*x[3]*x[4]*x[6]+0.3944*x[3]*x[4]*x[7]+0.4808*x[3]*x[4]*x[8]-0.8075*x[3]*x[4]*x[9]-0.8579*x[3]*x[4]*x[10]-0.5665*x[3]*x[5]*x[6]-0.895*x[3]*x[5]*x[7]-0.3975*x[3]*x[5]*x[8]+0.4934*x[3]*x[5]*x[9]+0.2624*x[3]*x[5]*x[10]+0.2931*x[3]*x[6]*x[7]-0.8108*x[3]*x[6]*x[8]-0.6769*x[3]*x[6]*x[9]-0.2571*x[3]*x[6]*x[10]+0.1818*x[3]*x[7]*x[8]-0.5706*x[3]*x[7]*x[9]+0.6166*x[3]*x[7]*x[10]-0.7727*x[3]*x[8]*x[9]-0.2887*x[3]*x[8]*x[10]-0.6625*x[3]*x[9]*x[10]-0.4673*x[4]*x[5]*x[6]+0.9985*x[4]*x[5]*x[7]-0.0513*x[4]*x[5]*x[8]-0.243*x[4]*x[5]*x[9]+0.9283*x[4]*x[5]*x[10]-0.9095*x[4]*x[6]*x[7]+0.0583*x[4]*x[6]*x[8]+0.823*x[4]*x[6]*x[9]-0.5969*x[4]*x[6]*x[10]+0.8222*x[4]*x[7]*x[8]-0.0405*x[4]*x[7]*x[9]-0.131*x[4]*x[7]*x[10]-0.3485*x[4]*x[8]*x[9]+0.8998*x[4]*x[8]*x[10]-0.2805*x[4]*x[9]*x[10]+0.5217*x[5]*x[6]*x[7]-0.933*x[5]*x[6]*x[8]+0.9836*x[5]*x[6]*x[9]-0.9513*x[5]*x[6]*x[10]-0.9415*x[5]*x[7]*x[8]-0.4551*x[5]*x[7]*x[9]+0.4972*x[5]*x[7]*x[10]-0.429*x[5]*x[8]*x[9]-0.5465*x[5]*x[8]*x[10]-0.1411*x[5]*x[9]*x[10]+0.5444*x[6]*x[7]*x[8]+0.1779*x[6]*x[7]*x[9]+0.0402*x[6]*x[7]*x[10]-0.9732*x[6]*x[8]*x[9]-0.3496*x[6]*x[8]*x[10]-0.2575*x[6]*x[9]*x[10]+0.6694*x[7]*x[8]*x[9]-0.4773*x[7]*x[8]*x[10]+0.4754*x[7]*x[9]*x[10]-0.9142*x[8]*x[9]*x[10] <= 54.766) + @NLconstraint(m, e11, 0.1794*x[1]*x[3]-0.1986*x[1]*x[2]-0.2451*x[1]*x[4]-0.1578*x[1]*x[5]+0.2522*x[1]*x[6]+0.562*x[1]*x[7]+0.9868*x[1]*x[8]+0.0232*x[1]*x[9]+0.5897*x[1]*x[10]+0.1998*x[2]*x[3]-0.9026*x[2]*x[4]+0.5954*x[2]*x[5]-0.0184*x[2]*x[6]-0.9132*x[2]*x[7]-0.0269*x[2]*x[8]+0.5776*x[2]*x[9]+0.2437*x[2]*x[10]-0.9638*x[3]*x[4]+0.4683*x[3]*x[5]-0.0524*x[3]*x[6]+0.865*x[3]*x[7]-0.0714*x[3]*x[8]-0.5196*x[3]*x[9]+0.2146*x[3]*x[10]+0.2514*x[4]*x[5]-0.9667*x[4]*x[6]-0.328*x[4]*x[7]+0.185*x[4]*x[8]-0.1588*x[4]*x[9]-0.6343*x[4]*x[10]+0.7847*x[5]*x[6]+0.2423*x[5]*x[7]-0.357*x[5]*x[8]-0.2066*x[5]*x[9]-0.1247*x[5]*x[10]-0.9086*x[6]*x[7]-0.4053*x[6]*x[8]-0.6526*x[6]*x[9]-0.7753*x[6]*x[10]+0.6139*x[7]*x[8]+0.0606*x[7]*x[9]-0.4917*x[7]*x[10]+0.82*x[8]*x[9]-0.8487*x[8]*x[10]-0.4958*x[9]*x[10]-0.4949*x[1]+0.7862*x[2]+0.7091*x[3]-0.6288*x[4]+0.7083*x[5]+0.4814*x[6]+0.1703*x[7]+0.511*x[8]+0.9122*x[9]+0.1772*x[10]+(-0.3364*x[1]*x[2]*x[3])-0.0269*x[1]*x[2]*x[4]+0.958*x[1]*x[2]*x[5]-0.871*x[1]*x[2]*x[6]-0.3226*x[1]*x[2]*x[7]-0.8197*x[1]*x[2]*x[8]-0.1814*x[1]*x[2]*x[9]-0.8487*x[1]*x[2]*x[10]+0.2095*x[1]*x[3]*x[4]-0.2767*x[1]*x[3]*x[5]-0.3641*x[1]*x[3]*x[6]-0.0245*x[1]*x[3]*x[7]+0.4568*x[1]*x[3]*x[8]+0.3128*x[1]*x[3]*x[9]+0.4853*x[1]*x[3]*x[10]+0.9152*x[1]*x[4]*x[5]-0.5344*x[1]*x[4]*x[6]+0.9609*x[1]*x[4]*x[7]+0.1761*x[1]*x[4]*x[8]+0.344*x[1]*x[4]*x[9]-0.3941*x[1]*x[4]*x[10]+0.8352*x[1]*x[5]*x[6]-0.8145*x[1]*x[5]*x[7]+0.4713*x[1]*x[5]*x[8]-0.2967*x[1]*x[5]*x[9]+0.1227*x[1]*x[5]*x[10]+0.6128*x[1]*x[6]*x[7]-0.5156*x[1]*x[6]*x[8]-0.1357*x[1]*x[6]*x[9]+0.4391*x[1]*x[6]*x[10]-0.916*x[1]*x[7]*x[8]-0.9986*x[1]*x[7]*x[9]+0.3863*x[1]*x[7]*x[10]-0.0975*x[1]*x[8]*x[9]+0.8211*x[1]*x[8]*x[10]+0.6467*x[1]*x[9]*x[10]+0.054*x[2]*x[3]*x[4]+0.0186*x[2]*x[3]*x[5]+0.3056*x[2]*x[3]*x[6]+0.6154*x[2]*x[3]*x[7]+0.0074*x[2]*x[3]*x[8]+0.4949*x[2]*x[3]*x[9]+0.6723*x[2]*x[3]*x[10]+0.3352*x[2]*x[4]*x[5]+0.0008*x[2]*x[4]*x[6]+0.5953*x[2]*x[4]*x[7]-0.6033*x[2]*x[4]*x[8]+0.5045*x[2]*x[4]*x[9]-0.269*x[2]*x[4]*x[10]+0.6495*x[2]*x[5]*x[6]+0.8248*x[2]*x[5]*x[7]-0.6363*x[2]*x[5]*x[8]+0.6394*x[2]*x[5]*x[9]+0.1078*x[2]*x[5]*x[10]+0.8161*x[2]*x[6]*x[7]-0.4037*x[2]*x[6]*x[8]+0.2088*x[2]*x[6]*x[9]-0.6234*x[2]*x[6]*x[10]-0.5131*x[2]*x[7]*x[8]-0.3159*x[2]*x[7]*x[9]-0.3376*x[2]*x[7]*x[10]-0.8348*x[2]*x[8]*x[9]-0.4805*x[2]*x[8]*x[10]+0.8075*x[2]*x[9]*x[10]+0.1383*x[3]*x[4]*x[5]-0.8913*x[3]*x[4]*x[6]-0.4103*x[3]*x[4]*x[7]+0.4252*x[3]*x[4]*x[8]-0.7663*x[3]*x[4]*x[9]-0.9546*x[3]*x[4]*x[10]+0.1664*x[3]*x[5]*x[6]-0.1357*x[3]*x[5]*x[7]+0.843*x[3]*x[5]*x[8]-0.4141*x[3]*x[5]*x[9]+0.9824*x[3]*x[5]*x[10]+0.8706*x[3]*x[6]*x[7]+0.3098*x[3]*x[6]*x[8]-0.8453*x[3]*x[6]*x[9]+0.4691*x[3]*x[6]*x[10]-0.4006*x[3]*x[7]*x[8]+0.3848*x[3]*x[7]*x[9]+0.9792*x[3]*x[7]*x[10]-0.4612*x[3]*x[8]*x[9]-0.9516*x[3]*x[8]*x[10]-0.4543*x[3]*x[9]*x[10]+0.5378*x[4]*x[5]*x[6]-0.8641*x[4]*x[5]*x[7]+0.6423*x[4]*x[5]*x[8]-0.8484*x[4]*x[5]*x[9]-0.3092*x[4]*x[5]*x[10]+0.6513*x[4]*x[6]*x[7]+0.0055*x[4]*x[6]*x[8]+0.0029*x[4]*x[6]*x[9]+0.9821*x[4]*x[6]*x[10]+0.477*x[4]*x[7]*x[8]+0.9873*x[4]*x[7]*x[9]+0.2413*x[4]*x[7]*x[10]+0.3671*x[4]*x[8]*x[9]-0.2025*x[4]*x[8]*x[10]-0.5689*x[4]*x[9]*x[10]+0.6425*x[5]*x[6]*x[7]+0.4043*x[5]*x[6]*x[8]-0.2493*x[5]*x[6]*x[9]-0.4849*x[5]*x[6]*x[10]+0.3103*x[5]*x[7]*x[8]-0.2523*x[5]*x[7]*x[9]+0.7611*x[5]*x[7]*x[10]+0.3698*x[5]*x[8]*x[9]-0.8896*x[5]*x[8]*x[10]+0.7634*x[5]*x[9]*x[10]-0.3524*x[6]*x[7]*x[8]-0.7996*x[6]*x[7]*x[9]+0.4739*x[6]*x[7]*x[10]+0.5203*x[6]*x[8]*x[9]-0.1375*x[6]*x[8]*x[10]-0.0134*x[6]*x[9]*x[10]-0.7802*x[7]*x[8]*x[9]+0.1529*x[7]*x[8]*x[10]-0.7427*x[7]*x[9]*x[10]+0.034*x[8]*x[9]*x[10] <= 80.713) + + return m +end \ No newline at end of file diff --git a/examples/MINLPs/multi.jl b/examples/MINLPs/multi.jl index 2b496457..e567f001 100644 --- a/examples/MINLPs/multi.jl +++ b/examples/MINLPs/multi.jl @@ -20,7 +20,7 @@ # println("--------------------------------------------------------------------------") function multi4(; verbose = false, solver = nothing, exprmode = 1) - m = Model(solver) + m = JuMP.Model(solver) Random.seed!(1) @variable(m, 0.1 <= x[1:4] <= rand() * 100) @@ -59,7 +59,7 @@ function multi4(; verbose = false, solver = nothing, exprmode = 1) end function multi3(; verbose = false, solver = nothing, exprmode = 1) - m = Model(solver) + m = JuMP.Model(solver) Random.seed!(1) ub = rand() @@ -86,7 +86,7 @@ end function multi2(; verbose = false, solver = nothing) # Global solution: 0.92906489 (arg min: [0.7336635, 1.266336]) - m = Model(solver) + m = JuMP.Model(solver) Random.seed!(1) @variable(m, 0.1 <= x[1:2] <= rand() * 10) @@ -107,7 +107,7 @@ function multi4N(; N = 1, randomub = true, ) - m = Model(solver) + m = JuMP.Model(solver) M = 1 + 3 * N Random.seed!(100) @@ -161,7 +161,7 @@ function multi3N(; N = 1, delta = 4, ) - m = Model(solver) + m = JuMP.Model(solver) M = 1 + 2 * N Random.seed!(100) @@ -195,7 +195,7 @@ function multiKND(; K = 2, D = 1, ) - m = Model(solver) + m = JuMP.Model(solver) M = K + (K - D) * (N - 1) Random.seed!(100) diff --git a/examples/MINLPs/nlp.jl b/examples/MINLPs/nlp.jl index 38d64548..3be3a468 100644 --- a/examples/MINLPs/nlp.jl +++ b/examples/MINLPs/nlp.jl @@ -1,7 +1,7 @@ function nlp1(; solver = nothing) - m = Model(solver) + m = JuMP.Model(solver) - @variable(m, 1 <= x[1:2] <= 10) + @variable(m, 1 <= x[1:2] <= 4) @NLconstraint(m, x[1] * x[2] >= 8) @NLobjective(m, Min, 6 * x[1]^2 + 4 * x[2]^2 - 2.5 * x[1] * x[2]) @@ -9,7 +9,7 @@ function nlp1(; solver = nothing) end function nlp2(; solver = nothing) - m = Model(solver) + m = JuMP.Model(solver) @variable(m, -500 <= x[1:2] <= 500) @NLobjective(m, Min, sum((x[i]^2 - i)^2 for i in 1:2)) @@ -32,7 +32,7 @@ function max_cover_var_picker(m::Alpine.Optimizer) end function nlp3(; solver = nothing) - m = Model(solver) + m = JuMP.Model(solver) LB = [100, 1000, 1000, 10, 10, 10, 10, 10] UB = [10000, 10000, 10000, 1000, 1000, 1000, 1000, 1000] diff --git a/examples/MINLPs/rosenbrock.jl b/examples/MINLPs/rosenbrock.jl index 3ce7d647..9941af08 100644 --- a/examples/MINLPs/rosenbrock.jl +++ b/examples/MINLPs/rosenbrock.jl @@ -2,7 +2,7 @@ # Global optimum = 0.0, arg min = (1,1) function rosenbrock(; solver = nothing) - m = Model(solver) + m = JuMP.Model(solver) @variable(m, -10 <= x <= 10) @variable(m, -10 <= y <= 10) diff --git a/examples/MINLPs/sincos.jl b/examples/MINLPs/sincos.jl index 2e3c2987..59e4e5e7 100644 --- a/examples/MINLPs/sincos.jl +++ b/examples/MINLPs/sincos.jl @@ -1,7 +1,7 @@ # Functions in this file are not tested until support for trigonometric functions is added. function sincos_p1(; solver = nothing) - m = Model(solver) + m = JuMP.Model(solver) @variable(m, 0.1 <= x[1:10] <= 10) @NLconstraint(m, [i in 1:9], x[i] * x[i+1] * sin(x[i]) >= 0.32) @@ -12,7 +12,7 @@ function sincos_p1(; solver = nothing) end function trig(; solver = nothing) - m = Model(solver) + m = JuMP.Model(solver) @variable(m, objvar) x_Idx = Any[1] @@ -34,7 +34,7 @@ function trig(; solver = nothing) end function specialopts(; verbose = false, solver = nothing) - m = Model(solver) + m = JuMP.Model(solver) @variable(m, x[i = 1:6]) diff --git a/examples/Project.toml b/examples/Project.toml index 9a080344..21f8f651 100644 --- a/examples/Project.toml +++ b/examples/Project.toml @@ -1,5 +1,6 @@ [deps] Alpine = "07493b3f-dabb-5b16-a503-4139292d7dd4" +BARON = "2e2ca445-9e14-5b13-8677-4410f177f82b" CPLEX = "a076750e-1247-5638-91d2-ce28b192dca0" Gurobi = "2e9cd046-0924-5485-92f1-d5272153d98b" HiGHS = "87dc4568-4c63-4d18-b0c0-bb2238e4078b" diff --git a/examples/README.md b/examples/README.md index 403a6375..3d3ffb3c 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,8 +1,8 @@ # Examples for Alpine `run_examples.jl` file contains the main driver file which can be executed to compute global optimality for a non-convex MINLP of your choice. Multiple such JuMP models of MINLPs can be found inside the `examples/MINLPs` folder. -A few useful *hints* to explore within Alpine: -* Try different integer values (>= 4) for `disc_ratio` to potentially observe +A few useful **hints** to explore within Alpine: +* Try different integer values (>= 4) for `partition_scaling_factor` to potentially observe better Alpine run times, which can be instance specific. * Choose `presolve_bt` to `false` if you prefer the optimization-based bound tightening (OBBT) presolve to be turned off. * If you prefer to use Alpine for only OBBT presolve, without any paritioning applied to the diff --git a/examples/run_examples.jl b/examples/run_examples.jl index e4ab487d..792cf0a4 100644 --- a/examples/run_examples.jl +++ b/examples/run_examples.jl @@ -20,7 +20,7 @@ minlp_solver = get_juniper(mip_solver, nlp_solver) #local solver #= Global solver Hints: - => Try different integer values (>=4) for `disc_ratio` to potentially observe + => Try different integer values (>=4) for `partition_scaling_factor` to potentially observe better Alpine run times (can be instance specific). => Choose `presolve_bt` to `false` if you prefer the bound tightening (OBBT) presolve to be turned off. => If you prefer to use Alpine for only OBBT presolve, without any paritioning applied to the @@ -33,7 +33,8 @@ const alpine = JuMP.optimizer_with_attributes( "nlp_solver" => nlp_solver, "mip_solver" => mip_solver, "presolve_bt" => true, - "disc_ratio" => 10, + "apply_partitioning" => true, + "partition_scaling_factor" => 10, ) m = nlp3(solver = alpine) diff --git a/examples/run_examples_linking.jl b/examples/run_examples_linking.jl deleted file mode 100644 index 980c52a0..00000000 --- a/examples/run_examples_linking.jl +++ /dev/null @@ -1,59 +0,0 @@ -# - Necessary - # -using Alpine -using JuMP -using Gurobi -using Ipopt -using Juniper -using Logging - -# Install library package. To install, at your Julia command prompt, -# Pkg.add(path="https://github.com/lanl-ansi/MINLPLib.jl.git") -# Reference: https://github.com/lanl-ansi/MINLPLib.jl -import MINLPLib - -# Choose underlying solvers for Alpine -ipopt = get_ipopt() -gurobi = get_gurobi() -juniper = get_juniper(gurobi, ipopt) - -#= Global solver - Hints: - => Try different integer values (>=4) for `disc_ratio` to potentially observe - better Alpine run times (can be instance specific). - => Choose `presolve_bt` to `false` if you prefer the bound tightening (OBBT) presolve to be turned off. - => If you prefer to use Alpine for only OBBT presolve, without any paritioning applied to the - nonlinear terms, include option "apply_partitioning" below and set it to false. -=# - -function run(use_linking_constraints, time_limit, instance_name) - alpine = JuMP.optimizer_with_attributes( - Alpine.Optimizer, - "minlp_solver" => juniper, - "nlp_solver" => ipopt, - "mip_solver" => gurobi, - "presolve_bt" => true, - "disc_ratio" => 10, - "time_limit" => time_limit, - "linking_constraints" => use_linking_constraints, - ) - m = MINLPLib.fetch_model(instance_name) - JuMP.set_optimizer(m, alpine) - - t_begin = time() - JuMP.optimize!(m) - objval = JuMP.objective_value(m) - soltime = time() - t_begin - - return objval, soltime -end - -# Linking constraints are only added when there are multilinear terms whose degree is at least 3. -# Choose instances in `mult3`` or `mult4`` libraries to see the improvement. -const instance_name = "mult3/m_10_3_10_100_1" -const time_limit = 60 - -objval_nolink, soltime_nolink = run(false, time_limit, instance_name) -objval_link, soltime_link = run(true, time_limit, instance_name) - -@info "Solution Time:\t link = $soltime_link, nolink = $soltime_nolink" -@info "Objective Value:\t link = $objval_link, nolink = $objval_nolink" diff --git a/src/Alpine.jl b/src/Alpine.jl index 58cc8740..44390e39 100644 --- a/src/Alpine.jl +++ b/src/Alpine.jl @@ -16,7 +16,7 @@ include("const.jl") # Engine for high-level algorithmic control and user-interface -include("solver.jl") +include("solver_options.jl") include("MOI_wrapper/MOI_wrapper.jl") include("MOI_wrapper/MOI_function2expr.jl") @@ -27,17 +27,16 @@ include("operators.jl") # Main algorithm include("algorithm.jl") include("presolve.jl") -include("amp.jl") +include("bounding_model.jl") include("embedding.jl") include("heuristics.jl") -include("linking.jl") # Convexification -include("multi.jl") -include("tmc.jl") +include("relaxations.jl") +include("multilinear.jl") # Model manipulation and utilities -include("bounds.jl") +include("variable_bounds.jl") include("utility.jl") # Logging diff --git a/src/MOI_wrapper/MOI_wrapper.jl b/src/MOI_wrapper/MOI_wrapper.jl index 88de75e7..c0a47a4d 100644 --- a/src/MOI_wrapper/MOI_wrapper.jl +++ b/src/MOI_wrapper/MOI_wrapper.jl @@ -95,6 +95,9 @@ mutable struct Optimizer <: MOI.AbstractOptimizer bound_sol_history::Vector{Vector{Float64}} # History of bounding solutions limited by "parameter disc_consecutive_forbid" bound_sol_pool::Dict{Any,Any} # A pool of solutions from solving model_mip + # Linking constraints info for Multilinear terms + linking_constraints_info::Union{Nothing, Dict{Any, Any}} # Stored multilinear linking constraints info + # Logging information and status logs::Dict{Symbol,Any} # Logging information detected_feasible_solution::Bool @@ -231,6 +234,8 @@ function MOI.empty!(m::Optimizer) m.best_abs_gap = Inf m.alpine_status = MOI.OPTIMIZE_NOT_CALLED + m.linking_constraints_info = nothing + create_status!(m) return create_logs!(m) end diff --git a/src/algorithm.jl b/src/algorithm.jl index 2e33957b..e41ef737 100644 --- a/src/algorithm.jl +++ b/src/algorithm.jl @@ -95,10 +95,8 @@ function load!(m::Optimizer) Alp.recategorize_var(m) # Initial round of variable re-categorization :Int in m.var_type_orig && error( - "Alpine does not support MINLPs with generic integer (non-binary) variables yet! Try Juniper.jl for finding a local feasible solution", + "Alpine does not support MINLPs with generic integer (non-binary) variables yet!", ) - :Int in m.var_type_orig ? Alp.set_option(m, :int_enable, true) : - Alp.set_option(m, :int_enable, false) # Separator for safer runs # Solver-dependent detection Alp._fetch_mip_solver_identifier(m) @@ -126,9 +124,9 @@ function load!(m::Optimizer) if length(m.bin_vars) > 200 || m.num_var_orig > 2000 println( - "Automatically turning OFF 'disc_ratio_branch' due to the size of the problem", + "Automatically turning OFF 'partition_scaling_factor_branch' due to the size of the problem", ) - Alp.set_option(m, :disc_ratio_branch, false) + Alp.set_option(m, :partition_scaling_factor_branch, false) end # Initialize the solution pool @@ -215,16 +213,16 @@ function presolve(m::Optimizer) ) Alp.bound_tightening(m, use_bound = true) # performs bound-tightening with the local solve objective value Alp.get_option(m, :presolve_bt) && init_disc(m) # Re-initialize discretization dictionary on tight bounds - Alp.get_option(m, :disc_ratio_branch) && - (Alp.set_option(m, :disc_ratio, Alp.update_disc_ratio(m, true))) + Alp.get_option(m, :partition_scaling_factor_branch) && + (Alp.set_option(m, :partition_scaling_factor, Alp.update_partition_scaling_factor(m, true))) Alp.add_partition(m, use_solution = m.best_sol) # Setting up the initial discretization elseif m.status[:local_solve] in STATUS_INF (Alp.get_option(m, :log_level) > 0) && println(" Bound tightening without objective bounds (OBBT)") Alp.bound_tightening(m, use_bound = false) # do bound tightening without objective value - (Alp.get_option(m, :disc_ratio_branch)) && - (Alp.set_option(m, :disc_ratio, Alp.update_disc_ratio(m, true))) + (Alp.get_option(m, :partition_scaling_factor_branch)) && + (Alp.set_option(m, :partition_scaling_factor, Alp.update_partition_scaling_factor(m, true))) Alp.get_option(m, :presolve_bt) && Alp.init_disc(m) elseif m.status[:local_solve] == MOI.INVALID_MODEL @@ -255,10 +253,9 @@ end """ function algorithm_automation(m::Optimizer) Alp.get_option(m, :disc_var_pick) == 3 && Alp.update_disc_cont_var(m) - Alp.get_option(m, :int_cumulative_disc) && Alp.update_disc_int_var(m) - if Alp.get_option(m, :disc_ratio_branch) - Alp.set_option(m, :disc_ratio, Alp.update_disc_ratio(m, true)) # Only perform for a maximum three times + if Alp.get_option(m, :partition_scaling_factor_branch) + Alp.set_option(m, :partition_scaling_factor, Alp.update_partition_scaling_factor(m, true)) # Only perform for a maximum three times end return diff --git a/src/amp.jl b/src/bounding_model.jl similarity index 91% rename from src/amp.jl rename to src/bounding_model.jl index 2e5a455a..f5afb77c 100644 --- a/src/amp.jl +++ b/src/bounding_model.jl @@ -1,5 +1,5 @@ """ - create_bounding_mip(m::Optimizer; use_disc::Dict) + create_bounding_mip(m::Optimizer; use_disc = nothing) Set up a MILP bounding model base on variable domain partitioning information stored in `use_disc`. By default, if `use_disc` is not provided, it will use `m.discretizations` store in the Alpine model. @@ -7,13 +7,6 @@ The basic idea of this MILP bounding model is to use Tighten McCormick to convex Among all presented partitions, the bounding model will choose one specific partition as the lower bound solution. The more partitions there are, the better or finer bounding model relax the original MINLP while the more efforts required to solve this MILP is required. - -This function is implemented in the following manner: - - * [`amp_post_vars`](@ref): post original and lifted variables - * [`amp_post_lifted_constraints`](@ref): post original and lifted constraints - * [`amp_post_lifted_obj`](@ref): post original or lifted objective function - * [`amp_post_tmc_mccormick`](@ref): post Tighten McCormick variables and constraints base on `discretization` information """ function create_bounding_mip(m::Optimizer; use_disc = nothing) use_disc === nothing ? discretization = m.discretization : discretization = use_disc @@ -22,9 +15,9 @@ function create_bounding_mip(m::Optimizer; use_disc = nothing) start_build = time() # ------- Model Construction ------ # Alp.amp_post_vars(m) # Post original and lifted variables - Alp.amp_post_lifted_constraints(m) # Post lifted constraints - Alp.amp_post_lifted_objective(m) # Post objective - Alp.amp_post_convexification(m, use_disc = discretization) # Convexify problem + Alp.amp_post_lifted_constraints(m) # Post original and lifted constraints + Alp.amp_post_lifted_objective(m) # Post original and/or objective + Alp.amp_post_convexification(m, use_disc = discretization) # Post convexification constraints # --------------------------------- # cputime_build = time() - start_build m.logs[:total_time] += cputime_build @@ -34,23 +27,16 @@ function create_bounding_mip(m::Optimizer; use_disc = nothing) end """ - amp_post_convexification(m::Optimizer; kwargs...) + amp_post_convexification(m::Optimizer; use_disc = nothing) -wrapper function to convexify the problem for a bounding model. This function talks to nonconvex_terms and convexification methods +Wrapper function to apply piecewise convexification of the problem for the bounding MIP model. This function talks to nonconvex_terms and convexification methods to finish the last step required during the construction of bounding model. """ function amp_post_convexification(m::Optimizer; use_disc = nothing) use_disc === nothing ? discretization = m.discretization : discretization = use_disc - # for i in 1:length(Alp.get_option(m, :method_convexification)) # Additional user-defined convexification method - # eval(Alp.get_option(m, :method_convexification)[i])(m) - # Alp.get_option(m, :method_convexification)[i](m) - # end - - Alp.amp_post_mccormick(m, use_disc = discretization) # handles all bi-linear and monomial convexificaitons - Alp.amp_post_convhull(m, use_disc = discretization) # convex hull representation - - Alp.is_fully_convexified(m) # Ensure if all the non-linear terms are convexified + Alp.amp_post_convhull(m, use_disc = discretization) # convex hull representation + Alp._is_fully_convexified(m) # Ensure if all the non-linear terms are convexified return end @@ -266,7 +252,7 @@ A built-in method used to add a new partition on feasible domains of variables c This can be illustrated by the following example. Let the previous iteration's partition vector on variable "x" be given by [0, 3, 7, 9]. And say, the lower bounding solution has a value of 4 for variable "x". -In the case when `disc_ratio=4`, this function creates the new partition vector as follows: [0, 3, 3.5, 4, 4.5, 7, 9] +In the case when `partition_scaling_factor=4`, this function creates the new partition vector as follows: [0, 3, 3.5, 4, 4.5, 7, 9] There are two options for this function, @@ -284,7 +270,7 @@ function add_adaptive_partition(m::Optimizer; kwargs...) haskey(options, :use_solution) ? point_vec = copy(options[:use_solution]) : point_vec = copy(m.best_bound_sol) haskey(options, :use_ratio) ? ratio = options[:use_ratio] : - ratio = Alp.get_option(m, :disc_ratio) + ratio = Alp.get_option(m, :partition_scaling_factor) haskey(options, :branching) ? branching = options[:branching] : branching = false if length(point_vec) < m.num_var_orig + m.num_var_linear_mip + m.num_var_nonlinear_mip @@ -443,8 +429,8 @@ function add_uniform_partition(m::Optimizer; kwargs...) return discretization end -function update_disc_ratio(m::Optimizer, presolve = false) - m.logs[:n_iter] > 2 && return Alp.get_option(m, :disc_ratio) # Stop branching after the second iterations +function update_partition_scaling_factor(m::Optimizer, presolve = false) + m.logs[:n_iter] > 2 && return Alp.get_option(m, :partition_scaling_factor) # Stop branching after the second iterations ratio_pool = [8:2:20;] # Built-in try range convertor = Dict(MOI.MAX_SENSE => :<, MOI.MIN_SENSE => :>) @@ -491,7 +477,7 @@ function update_disc_ratio(m::Optimizer, presolve = false) if Statistics.std(res_collector) >= 1e-2 # Detect if all solutions are similar to each other Alp.get_option(m, :log_level) > 0 && println("RATIO BRANCHING OFF due to solution variance test passed.") - Alp.set_option(m, :disc_ratio_branch, false) # If an incumbent ratio is selected, then stop the branching scheme + Alp.set_option(m, :partition_scaling_factor_branch, false) # If an incumbent ratio is selected, then stop the branching scheme end if !isempty(m.best_sol) diff --git a/src/embedding.jl b/src/embedding.jl index 9edccc96..cd056fbe 100644 --- a/src/embedding.jl +++ b/src/embedding.jl @@ -145,7 +145,7 @@ function ebd_link_xα( base_name = "αA$(var_idx)" ) for i in keys(lifters) # Build first-level evaluation - Alp.binprod_relax(m.model_mip, α_A[lifters[i]-L], [α[j] for j in i]) + Alp.relaxation_multilinear_binary(m.model_mip, α_A[lifters[i]-L], [α[j] for j in i]) end α_R = [α; α_A] # Initialize/re-arrgange the variable sequence diff --git a/src/heuristics.jl b/src/heuristics.jl index 9713c049..777094db 100644 --- a/src/heuristics.jl +++ b/src/heuristics.jl @@ -48,17 +48,6 @@ function update_disc_cont_var(m::Optimizer) return end -function update_disc_int_var(m::Optimizer) - length(m.candidate_disc_vars) <= 15 && return # Algorithm Separation Point - - # Additional error checking scheme - :Int in m.var_type && error( - "Alpine does not support MINLPs with geenric integer (non-binary) variables yet! Try Juniper.jl for finding a local feasible solution", - ) - - return -end - """ Use solutions from the MIP solution pool as starting points """ diff --git a/src/linking.jl b/src/linking.jl deleted file mode 100644 index 3928956e..00000000 --- a/src/linking.jl +++ /dev/null @@ -1,75 +0,0 @@ -function add_linking_constraints(m::Optimizer, λ::Dict) - """ - Add linking constraints between λ[i], λ[j] variables. - - Reference information: - Jongeun Kim, Jean-Philippe P. Richard, Mohit Tawarmalani, Piecewise Polyhedral Relaxations of Multilinear Optimization, - http://www.optimization-online.org/DB_HTML/2022/07/8974.html - - For example, suppose we have λ[i], λ[j], and λ[k] where i=(1,2,3), j=(1,2,4), and k=(1,2,5). - λ[i] contains all multipliers for the extreme points in the space of (x1,x2,x3). - λ[j] contains all multipliers for the extreme points in the space of (x1,x2,x4). - λ[k] contains all multipliers for the extreme points in the space of (x1,x2,x5). - - Using λ[i], λ[j], or λ[k], we can express multilinear function x1*x2. - We define a linking variable μ(1,2) that represents the value of x1*x2. - Linking constraints are - μ(1,2) == convex combination expression for x1*x2 using λ[i], - μ(1,2) == convex combination expression for x1*x2 using λ[j], and - μ(1,2) == convex combination expression for x1*x2 using λ[k]. - - Then, these constraints link between λ[i], λ[j], and λ[k] variables. - """ - - # (Step 0) Define informational paramters used in the report in the end of the function. - t_begin = time() - num_added_constraints = 0 - - # (Step 1) Define link_info::Dict - # - key: linking variable indices - # - value: the subset of key(λ) where each element is a superset of the linking variable indices - maxdeg = maximum([length(k) for k in keys(λ)]) # Compute maximum degree of multilinear terms - if maxdeg <= 2 - # @info "no linking constraint is added because the maximum degree of multilinear term is $(maxdeg)." - return - end - all_vars_idx = sort(collect(union(collect(keys(λ))...))) # Collect all variable indices used in multilinear terms - link_info = Dict( - link_var_idx => filter(r -> issubset(link_var_idx, r), keys(λ)) for - deg in 2:maxdeg-1 for - link_var_idx in Combinatorics.combinations(all_vars_idx, deg) - ) - filter!(r -> length(r.second) >= 2, link_info) - if isempty(link_info) - # @info "no linking constraint is added because there is no multilinear terms that shaer more than two variables." - return - end - - # (Step 2) Add linking (decision) variables to the mip model - link_vars = @variable(m.model_mip, [collect(keys(link_info))]) - - # (Step 3) Add linking constraints to the mip model - for (link_var_idx, list_multi_idx) in link_info, - (i, multi_idx) in enumerate(list_multi_idx) - # Define `linkidx2multiidx` to know where `link_var_idx` and `list_multi_idx` have the same value. - # `linkidx2multiidx` satisfies that link_var_idx[i] = list_multi_idx[linkidx2multiidx[i]] for all i. - # By the definition of `link_info`, it always holds that issubset(link_var_idx, list_multi_idx). - linkidx2multiidx = [findfirst(multi_idx .== i) for i in link_var_idx] - - # We define the RHS of linking constraints (convex combination expression for prod(x[link_var_idx]) using λ[multi_idx]) - expr = 0 - for idx in Iterators.product([1:d for d in λ[multi_idx][:dim]]...) - var = λ[multi_idx][:vars][λ[multi_idx][:indices][idx...]] - func_value = prod( - m.discretization[i][idx[j]] for - (i, j) in zip(link_var_idx, linkidx2multiidx) - ) - expr += func_value * var - end - - @constraint(m.model_mip, link_vars[link_var_idx] == expr) - num_added_constraints += 1 - end - - # @info "$num_added_constraints linking constraints are added in $(time() - t_begin) seconds." -end diff --git a/src/log.jl b/src/log.jl index d7962bca..4b302db7 100644 --- a/src/log.jl +++ b/src/log.jl @@ -3,8 +3,8 @@ function create_logs!(m) logs = Dict{Symbol,Any}() # Timers - logs[:presolve_time] = 0.0 # Total presolve-time of the algorithm - logs[:total_time] = 0.0 # Total run-time of the algorithm + logs[:presolve_time] = 0.0 # Total presolve-time of the algorithm + logs[:total_time] = 0.0 # Total run-time of the algorithm logs[:time_left] = Alp.get_option(m, :time_limit) # Total remaining time of the algorithm if time-out is specified # Values @@ -64,14 +64,15 @@ function logging_summary(m::Optimizer) println(" MIP solver = ", m.mip_solver_id) printstyled("ALPINE CONFIGURATION\n", color = :cyan) + println(" Alpine version = ", _ALPINE_VERSION) if Alp.is_min_sense(m) println( - " Maximum iterations (lower-bounding MIPs) = ", + " Maximum iterations (lower-bounding MIPs) = ", Alp.get_option(m, :max_iter), ) elseif Alp.is_max_sense(m) println( - " Maximum iterations (upper-bounding MIPs) = ", + " Maximum iterations (upper-bounding MIPs) = ", Alp.get_option(m, :max_iter), ) else @@ -95,10 +96,10 @@ function logging_summary(m::Optimizer) ) end - if Alp.get_option(m, :disc_ratio_branch) - println(" Discretization ratio branch activated") + if Alp.get_option(m, :partition_scaling_factor_branch) + println(" Partition scaling factor branch activated") else - println(" Discretization ratio = ", Alp.get_option(m, :disc_ratio)) + println(" Partition scaling factor = ", Alp.get_option(m, :partition_scaling_factor)) end (Alp.get_option(m, :convhull_ebd)) && println(" Using convhull_ebd formulation") (Alp.get_option(m, :convhull_ebd)) && diff --git a/src/multi.jl b/src/multilinear.jl similarity index 81% rename from src/multi.jl rename to src/multilinear.jl index dff5d324..88f36795 100644 --- a/src/multi.jl +++ b/src/multilinear.jl @@ -7,32 +7,24 @@ function amp_post_convhull(m::Optimizer; kwargs...) α = Dict() # Partitioning Variables β = Dict() # Lifted variables for exact formulation - # Convexification Treatment for Complex Non-Convex Terms + # Convexification for non-convex terms for k in keys(m.nonconvex_terms) nl_type = m.nonconvex_terms[k][:nonlinear_type] if ((nl_type == :MULTILINEAR) || (nl_type == :BILINEAR)) && (m.nonconvex_terms[k][:convexified] == false) λ, α = Alp.amp_convexify_multilinear(m, k, λ, α, d) elseif nl_type == :MONOMIAL && !m.nonconvex_terms[k][:convexified] - λ, α = Alp.amp_convexify_monomial(m, k, λ, α, d) + λ, α = Alp.amp_convexify_quadratic_univariate(m, k, λ, α, d) elseif nl_type == :BINLIN && !m.nonconvex_terms[k][:convexified] β = Alp.amp_convexify_binlin(m, k, β) elseif nl_type == :BINPROD && !m.nonconvex_terms[k][:convexified] - β = Alp.amp_convexify_binprod(m, k, β) - elseif nl_type == :BININT && !m.nonconvex_terms[k][:convexified] - β = Alp.amp_convexify_binint(m, k, β) - elseif nl_type == :INTPROD && !m.nonconvex_terms[k][:convexified] - error("Integer features are OFF. No support for INTPROD at this moment.") - elseif nl_type == :INTLIN && !m.nonconvex_terms[k][:convexified] - error("Integer features are OFF. No support for INTLIN at this moment.") - elseif nl_type in [:sin, :cos] && !m.nonconvex_terms[k][:convexified] - error("Integer features are OFF. No support for INTLIN at this moment.") + β = Alp.amp_convexify_multilinear_binary(m, k, β) end end # Add lambda linking constraints if m.options.linking_constraints - Alp.add_linking_constraints(m, λ) + Alp._add_multilinear_linking_constraints(m, λ) end # Code for warm starting bounding MIP iterations @@ -76,7 +68,7 @@ function amp_convexify_multilinear( return λ, α end -function amp_convexify_monomial( +function amp_convexify_quadratic_univariate( m::Optimizer, k::Any, λ::Dict, @@ -90,7 +82,7 @@ function amp_convexify_monomial( λ = Alp.amp_convhull_λ(m, k, monomial_index, λ, extreme_point_cnt, dim) λ = Alp.populate_convhull_extreme_values(m, discretization, monomial_index, λ, 2) α = Alp.amp_convhull_α(m, [monomial_index], α, dim, discretization) - Alp.amp_post_convhull_constrs(m, λ, α, monomial_index, dim, discretization) + Alp.amp_post_convhull_constrs(m, λ, α, monomial_index, discretization) return λ, α end @@ -116,11 +108,13 @@ function amp_convexify_binlin(m::Optimizer, k::Any, β::Dict) bin_idx = bin_idx[1] cont_idx = cont_idx[1] - Alp.mccormick_binlin( + Alp.relaxation_bilinear( m.model_mip, _index_to_variable_ref(m.model_mip, lift_idx), _index_to_variable_ref(m.model_mip, bin_idx), _index_to_variable_ref(m.model_mip, cont_idx), + 0, + 1, m.l_var_tight[cont_idx], m.u_var_tight[cont_idx], ) @@ -128,11 +122,7 @@ function amp_convexify_binlin(m::Optimizer, k::Any, β::Dict) return β end -function amp_convexify_binint(m::Optimizer, k::Any, β::Dict) - return amp_convexify_binlin(m, k, β) -end - -function amp_convexify_binprod(m::Optimizer, k::Any, β::Dict) +function amp_convexify_multilinear_binary(m::Optimizer, k::Any, β::Dict) m.nonconvex_terms[k][:convexified] = true # Bookeeping the convexified terms lift_idx = m.nonconvex_terms[k][:y_idx] @@ -144,10 +134,10 @@ function amp_convexify_binprod(m::Optimizer, k::Any, β::Dict) z = _index_to_variable_ref(m.model_mip, m.nonconvex_terms[k][:y_idx]) x = [_index_to_variable_ref(m.model_mip, i) for i in m.nonconvex_terms[k][:var_idxs]] - for i in x - JuMP.@constraint(m.model_mip, z <= i) + + if length(x) >= 1 + Alp.relaxation_multilinear_binary(m.model_mip, z, x) end - JuMP.@constraint(m.model_mip, z >= sum(x) - (length(x) - 1)) return β end @@ -238,7 +228,7 @@ function populate_convhull_extreme_values( end """ - Method for regular muiltilinear terms + Method for regular multilinear terms """ function populate_convhull_extreme_values( m::Optimizer, @@ -392,7 +382,7 @@ function amp_warmstart_α(m::Optimizer, α::Dict) end """ - Method for general multilinear terms with/without integer variables + Method for general multilinear terms """ function amp_post_convhull_constrs( m::Optimizer, @@ -437,14 +427,13 @@ function amp_post_convhull_constrs( end """ - Method for power-2 term + Constraints for univariate quadratic terms """ function amp_post_convhull_constrs( m::Optimizer, λ::Dict, α::Dict, monomial_idx::Int, - dim::Tuple, discretization::Dict, ) partition_cnt = length(discretization[monomial_idx]) - 1 @@ -696,102 +685,96 @@ function collect_indices(l::Array, fixed_dim::Int, fixed_partition::Array, dim:: return indices end -#= -function collect_indices(l::Array, locator::Tuple, dim::Tuple) +""" + _add_multilinear_linking_constraints(m::Optimizer, λ::Dict) - k = 0 - indices = Vector{Int}(2^length(dim)) - for i in 1:prod(dim) - ind = Tuple(CartesianIndices(l)[i]) - diff = [((ind[i] - locator[i] == 0) || (ind[i] - locator[i] == 1)) for i in 1:length(dim)] - if prod(diff) - k +=1 - indices[k] = i - end - end +This internal function adds linking constraints between λ multipliers corresponding to multilinear terms +that share more than two variables and are partitioned. For example, suppose we have λ[i], λ[j], and +λ[k] where i=(1,2,3), j=(1,2,4), and k=(1,2,5). λ[i] contains all multipliers for the extreme points +in the space of (x1,x2,x3). λ[j] contains all multipliers for the extreme points in the space of (x1,x2,x4). +λ[k] contains all multipliers for the extreme points in the space of (x1,x2,x5). - return indices -end +Using λ[i], λ[j], or λ[k], we can express multilinear function x1*x2. +We define a linking variable μ(1,2) that represents the value of x1*x2. +Linking constraints are + μ(1,2) == convex combination expr for x1*x2 using λ[i], + μ(1,2) == convex combination expr for x1*x2 using λ[j], and + μ(1,2) == convex combination expr for x1*x2 using λ[k]. -""" - [Experimental Function] - Method for multilinear terms with discrete variables -""" -function amp_post_inequalities_int(m::Optimizer, d::Dict, λ::Dict, α::Dict, indices::Any, dim::Tuple, var_ind::Int, cnt::Int) +Thus, these constraints link between λ[i], λ[j], and λ[k] variables. - l_cnt = length(d[var_ind]) - p_cnt = l_cnt - 1 +Reference: J. Kim, J.P. Richard, M. Tawarmalani, Piecewise Polyhedral Relaxations of Multilinear Optimization, +http://www.optimization-online.org/DB_HTML/2022/07/8974.html +""" +function _add_multilinear_linking_constraints(m::Optimizer, λ::Dict) - # Embedding formulation - Alp.get_option(m, :convhull_ebd) && @warn "Embedding is currently not supported for multilinear terms with discrete variables" + if isnothing(m.linking_constraints_info) + m.linking_constraints_info = Alp._get_shared_multilinear_terms_info(λ, m.options.linking_constraints_degree_limit) + end - # SOS-2 Formulation - if Alp.get_option(m, :convhull_formulation) == "sos2" - for j in 1:l_cnt - sliced_indices = collect_indices(λ[indices][:indices], cnt, [j], dim) - if (j == 1) - rate_r = amp_pick_ratevec(d[var_ind], j) - JuMP.@constraint(m.model_mip, sum(λ[indices][:vars][sliced_indices]) <= α[var_ind][j] * rate_r) - elseif (j == l_cnt) - rate_l = amp_pick_ratevec(d[var_ind], j) - JuMP.@constraint(m.model_mip, sum(λ[indices][:vars][sliced_indices]) <= α[var_ind][p_cnt] * rate_l) - else - rate_l, rate_r = amp_pick_ratevec(d[var_ind], j) - JuMP.@constraint(m.model_mip, sum(λ[indices][:vars][sliced_indices]) <= α[var_ind][j-1] * rate_l + α[var_ind][j] * rate_r) - end + if isnothing(m.linking_constraints_info) + return + end + + # Additional linking variables (μ) to the MIP model to keep the constraints sparse + linking_variables = JuMP.@variable(m.model_mip, [i in keys(m.linking_constraints_info)]) + + # Add linking constraints to the MIP model + for (shared_multilinear_idx, multilinear_terms_idx) in m.linking_constraints_info, + (i, multilinear_idx) in enumerate(multilinear_terms_idx) + var_location = [findfirst(multilinear_idx .== i) for i in shared_multilinear_idx] + + lambda_expr = 0 + for idx in Iterators.product([1:d for d in λ[multilinear_idx][:dim]]...) + var = λ[multilinear_idx][:vars][λ[multilinear_idx][:indices][idx...]] + partitions_info = prod( + m.discretization[i][idx[j]] for + (i, j) in zip(shared_multilinear_idx, var_location) + ) + lambda_expr += partitions_info * var end - else - error("Only SOS-2 formulation supports convexification of terms with integer variables.") - end - return + JuMP.@constraint(m.model_mip, linking_variables[shared_multilinear_idx] == lambda_expr) + end end """ - [Experimental Function] - This is a utility function that can be used to measure the coefficients for formulations that convexify terms with integer variables. -""" -function amp_pick_ratevec(partvec::Vector, i::Int) + _get_shared_multilinear_terms_info(λ, linking_constraints_degree_limit) - λCnt = length(partvec) +This function checks to see if linking constraints are +necessary for a given vector of each multilinear terms and returns the approapriate +linking constraints information. +""" +function _get_shared_multilinear_terms_info( + λ::Dict, + linking_constraints_degree_limit::Union{Nothing,T} where {T<:Int64} = nothing +) + + # Compute maximum degree of multilinear terms and return if bilinear + max_degree = maximum([length(k) for k in keys(λ)]) - if i == 1 - mod(partvec[i], 0.5) == 0.0 && partvec[i+1] - partvec[i] == 1.0 && return 0.5 - elseif i == λCnt - mod(partvec[i], 0.5) == 0.0 && partvec[i] - partvec[i-1] == 1.0 && return 0.5 - else - if mod(partvec[i], 0.5) == 0.0 && partvec[i] - partvec[i-1] == 1.0 - l = 0.5 - else - l = 1.0 - end - if mod(partvec[i], 0.5) == 0.0 && partvec[i+1] - partvec[i] == 1.0 - r = 0.5 - else - r = 1.0 - end - return l, r + if max_degree <= 2 + return (linking_constraints_info = nothing) end - return 1.0 -end + # Limit the linking constraints to a prescribed multilinear degree + if !isnothing(linking_constraints_degree_limit) && (linking_constraints_degree_limit < max_degree) + max_degree = linking_constraints_degree_limit + end -function amp_collect_tight_regions(partvec::Vector) + # Collect all variable indices appearing in multilinear terms + all_variables_idx = collect(union((keys(λ) |> collect)...)) |> sort - PCnt = length(partvec) - 1 - PCnt == 1 && return [] + linking_constraints_info = Dict( + shared_multilinear_idx => filter(r -> issubset(shared_multilinear_idx, r), keys(λ)) for + deg in 2:(max_degree-1) for + shared_multilinear_idx in Combinatorics.combinations(all_variables_idx, deg) + ) - tight_regions = [] - for i in 1:PCnt - if i == 1 - (partvec[i]+1.0==partvec[i+1]) && (partvec[i+1]+1.0==partvec[i+2]) && push!(tight_regions,i) - elseif i == PCnt - (partvec[i]+1.0==partvec[i+1]) && (partvec[i]-1.0==partvec[i-1]) && push!(tight_regions, i) - else - (partvec[i]+1.0==partvec[i+1]) && (partvec[i+1]+1.0==partvec[i+2]) && (partvec[i]-1.0==partvec[i-1]) && push!(tight_regions, i) - end + filter!(r -> length(r.second) >= 2, linking_constraints_info) + if isempty(linking_constraints_info) + return (linking_constraints_info = nothing) end - return tight_regions -end -=# + return (linking_constraints_info = linking_constraints_info) +end \ No newline at end of file diff --git a/src/relaxations.jl b/src/relaxations.jl new file mode 100644 index 00000000..96f853ad --- /dev/null +++ b/src/relaxations.jl @@ -0,0 +1,81 @@ +""" + relaxation_bilinear( + m::JuMP.Model, + z::JuMP.VariableRef, + x::JuMP.VariableRef, + y::JuMP.VariableRef, + lb_x::Number, + ub_x::Number, + lb_y::Number, + ub_y::Number) + +General relaxation of a binlinear term (McCormick relaxation). +``` +z >= JuMP.lower_bound(x)*y + JuMP.lower_bound(y)*x - JuMP.lower_bound(x)*JuMP.lower_bound(y) +z >= JuMP.upper_bound(x)*y + JuMP.upper_bound(y)*x - JuMP.upper_bound(x)*JuMP.upper_bound(y) +z <= JuMP.lower_bound(x)*y + JuMP.upper_bound(y)*x - JuMP.lower_bound(x)*JuMP.upper_bound(y) +z <= JuMP.upper_bound(x)*y + JuMP.lower_bound(y)*x - JuMP.upper_bound(x)*JuMP.lower_bound(y) +``` +""" +function relaxation_bilinear( + m::JuMP.Model, + z::JuMP.VariableRef, + x::JuMP.VariableRef, + y::JuMP.VariableRef, + lb_x::Number, + ub_x::Number, + lb_y::Number, + ub_y::Number +) + + JuMP.@constraint(m, z >= lb_x * y + lb_y * x - lb_x * lb_y) + JuMP.@constraint(m, z >= ub_x * y + ub_y * x - ub_x * ub_y) + JuMP.@constraint(m, z <= lb_x * y + ub_y * x - lb_x * ub_y) + JuMP.@constraint(m, z <= ub_x * y + lb_y * x - ub_x * lb_y) + + return +end + +""" + relaxation_multilinear_binary( + m::JuMP.Model, + z::JuMP.VariableRef, + x::Vector{VariableRef}) + +Applies Fortet linearization (see https://doi.org/10.1007/s10288-006-0015-3) for z = prod(x), +where x is a vector of binary variables. +""" +function relaxation_multilinear_binary(m::JuMP.Model, z::JuMP.VariableRef, x::Vector{VariableRef}) + for i in x + JuMP.@constraint(m, z <= i) + end + JuMP.@constraint(m, z >= sum(x) - (length(x) - 1)) + + return +end + +#= +""" + relaxation_quadratic_univariate( + m::JuMP.Model, + z::JuMP.VariableRef, + x::JuMP.VariableRef, + lb_x::Number, + ub_x::Number, + ) + +Applies convex hull relaxation for z = x^2, where x is a variable. +""" +function relaxation_quadratic_univariate( + m::JuMP.Model, + z::JuMP.VariableRef, + x::JuMP.VariableRef, + lb_x::Number, + ub_x::Number, +) + JuMP.@constraint(m, z >= x^2) + JuMP.@constraint(m, z <= (lb_x + ub_x) * x - (lb_x * ub_x)) + + return +end +=# \ No newline at end of file diff --git a/src/solver.jl b/src/solver_options.jl similarity index 80% rename from src/solver.jl rename to src/solver_options.jl index 30850dce..9fdba88b 100644 --- a/src/solver.jl +++ b/src/solver_options.jl @@ -1,4 +1,4 @@ -# Optimizer struct and options to tune Alpine, a global solver for MINLPs +# Optimizer struct and user-defined options (with default settings) to tune Alpine solver mutable struct OptimizerOptions # Parameters for tuning Alpine @@ -19,9 +19,6 @@ mutable struct OptimizerOptions # Convexification methods recognize_convex::Bool # Recognize convex expressions in parsing objective functions and constraints - bilinear_mccormick::Bool # Convexify bilinear terms using piecwise McCormick representation - bilinear_convexhull::Bool # Convexify bilinear terms using lambda representation - monomial_convexhull::Bool # Convexify monomial terms using convex-hull representation # Expression-based user-inputs # method_convexification :: Array{Function} # Array of functions that user can choose to convexify specific non-linear terms : no over-ride privilege @@ -29,14 +26,14 @@ mutable struct OptimizerOptions # Parameters used in Alpine's MIP-based partitioning algorithm apply_partitioning::Bool # Apply the partitioning algorithm only if thhis true, else terminate after presolve disc_var_pick::Any # Algorithm for choosing the variables to discretize: 1 for minimum vertex cover, 0 for all variables - disc_ratio::Int # Discretization ratio parameter, which is critical for convergence (using a fixed value for now, later switch to a function) + partition_scaling_factor::Int # Partition scaling parameter, which is critical for convergence (using a fixed value for now, later switch to a function) disc_uniform_rate::Int # Discretization rate parameter when using uniform partitions disc_add_partition_method::Any # Additional methods to add discretization disc_divert_chunks::Int # How many uniform partitions to construct disc_abs_width_tol::Float64 # Absolute tolerance used when setting up a partition disc_rel_width_tol::Float64 # Relative width tolerance when setting up a partition disc_consecutive_forbid::Int # Prevent bounding model to add partitions consecutively in the same region when bounds do not improve - disc_ratio_branch::Bool # Branching tests for picking fixed discretization ratio + partition_scaling_factor_branch::Bool # Branching tests for picking fixed discretization ratio # MIP formulation parameters convhull_formulation::String # MIP Formulation for the relaxation @@ -46,6 +43,8 @@ mutable struct OptimizerOptions convhull_ebd_link::Bool # Linking constraints between x and α, type 1 uses hierarchical and type 2 uses big-m convhull_warmstart::Bool # Warm start the bounding MIP convhull_no_good_cuts::Bool # Add no-good cuts to MIP based on the pool solutions + linking_constraints::Bool # Multilinear linking constraint feature + linking_constraints_degree_limit::Int64 # Degree of shared multilinear terms up to which the linking constraints are built and added # Bound-tightening parameters presolve_track_time::Bool # Account presolve time for total time usage @@ -61,14 +60,8 @@ mutable struct OptimizerOptions presolve_bt_mip_time_limit::Float64 # Time limit for a single MIP solved in the built-in bound tightening algorithm (with partitions) # Domain Reduction - presolve_bp::Bool # Conduct basic bound propagation + presolve_bp::Bool # Conduct basic bound propagation - # Features for integer variable problems - int_enable::Bool # Convert integer problem into binary problem - int_cumulative_disc::Bool # Cumulatively involve integer variables for discretization - - # Linking constraint feature - linking_constraints::Bool end function get_default_options() @@ -85,25 +78,17 @@ function get_default_options() mip_solver = nothing recognize_convex = true - bilinear_mccormick = false - bilinear_convexhull = true - monomial_convexhull = true - - # method_convexification = Array{Function}(undef, 0) - # method_partition_injection = Array{Function}(undef, 0) - # term_patterns = Array{Function}(undef, 0) - # constr_patterns = Array{Function}(undef, 0) apply_partitioning = true disc_var_pick = 2 # By default, uses the 15-variable selective rule - disc_ratio = 10 + partition_scaling_factor = 10 disc_uniform_rate = 2 disc_add_partition_method = "adaptive" disc_divert_chunks = 5 disc_abs_width_tol = 1e-4 disc_rel_width_tol = 1e-6 disc_consecutive_forbid = false - disc_ratio_branch = false + partition_scaling_factor_branch = false convhull_formulation = "sos2" convhull_ebd = false @@ -112,6 +97,8 @@ function get_default_options() convhull_ebd_link = false convhull_warmstart = true convhull_no_good_cuts = false + linking_constraints = true + linking_constraints_degree_limit = 4 # check up to quadrilinear sharing across terms presolve_track_time = true presolve_bt = true @@ -126,11 +113,6 @@ function get_default_options() presolve_bt_mip_time_limit = Inf presolve_bp = false - int_enable = false - int_cumulative_disc = true - - linking_constraints = false - return OptimizerOptions( log_level, time_limit, @@ -143,19 +125,16 @@ function get_default_options() minlp_solver, mip_solver, recognize_convex, - bilinear_mccormick, - bilinear_convexhull, - monomial_convexhull, apply_partitioning, disc_var_pick, - disc_ratio, + partition_scaling_factor, disc_uniform_rate, disc_add_partition_method, disc_divert_chunks, disc_abs_width_tol, disc_rel_width_tol, disc_consecutive_forbid, - disc_ratio_branch, + partition_scaling_factor_branch, convhull_formulation, convhull_ebd, convhull_ebd_encode, @@ -163,6 +142,8 @@ function get_default_options() convhull_ebd_link, convhull_warmstart, convhull_no_good_cuts, + linking_constraints, + linking_constraints_degree_limit, presolve_track_time, presolve_bt, presolve_bt_time_limit, @@ -174,9 +155,6 @@ function get_default_options() presolve_bt_algo, presolve_bt_relax_integrality, presolve_bt_mip_time_limit, - presolve_bp, - int_enable, - int_cumulative_disc, - linking_constraints, + presolve_bp ) end diff --git a/src/tmc.jl b/src/tmc.jl deleted file mode 100644 index 7088b808..00000000 --- a/src/tmc.jl +++ /dev/null @@ -1,475 +0,0 @@ -function amp_post_mccormick(m::Optimizer; kwargs...) - options = Dict(kwargs) - - # detect whether to use specific discretization information - haskey(options, :use_disc) ? discretization = options[:use_disc] : - discretization = m.discretization - - λ = Dict() - λλ = Dict() - λX = Dict() - lb = Dict() - ub = Dict() - - for bi in keys(m.nonconvex_terms) - nl_type = m.nonconvex_terms[bi][:nonlinear_type] - if ( - (!Alp.get_option(m, :monomial_convexhull)) * (nl_type == :MONOMIAL) || - (!Alp.get_option(m, :bilinear_convexhull)) * (nl_type == :BILINEAR) - ) && (m.nonconvex_terms[bi][:convexified] == false) - @assert length(bi) == 2 - m.nonconvex_terms[bi][:convexified] = true # Bookkeeping the examined terms - idx_a = bi[1].args[2] - idx_b = bi[2].args[2] - idx_ab = m.nonconvex_terms[bi][:lifted_var_ref].args[2] - - part_cnt_a = length(discretization[idx_a]) - 1 - part_cnt_b = length(discretization[idx_b]) - 1 - - lb[idx_a] = discretization[idx_a][1:(end-1)] - ub[idx_a] = discretization[idx_a][2:end] - lb[idx_b] = discretization[idx_b][1:(end-1)] - ub[idx_b] = discretization[idx_b][2:end] - - (lb[idx_a][1] == -Inf) && - error("Infinite lower bound detected on VAR$idx_a, resolve it please") - (lb[idx_b][1] == -Inf) && - error("Infinite lower bound detected on VAR$idx_b, resolve it please") - (ub[idx_a][end] == +Inf) && - error("Infinite upper bound detected on VAR$idx_a, resolve it please") - (ub[idx_b][end] == +Inf) && - error("Infinite upper bound detected on VAR$idx_b, resolve it please") - - if (length(lb[idx_a]) == 1) && (length(lb[idx_b]) == 1) # Basic McCormick - if m.nonconvex_terms[bi][:nonlinear_type] == :MONOMIAL - Alp.mccormick_monomial( - m.model_mip, - _index_to_variable_ref(m.model_mip, idx_ab), - _index_to_variable_ref(m.model_mip, idx_a), - lb[idx_a][1], - ub[idx_a][1], - ) - elseif m.nonconvex_terms[bi][:nonlinear_type] == :BILINEAR - Alp.mccormick( - m.model_mip, - _index_to_variable_ref(m.model_mip, idx_ab), - _index_to_variable_ref(m.model_mip, idx_a), - _index_to_variable_ref(m.model_mip, idx_b), - lb[idx_a][1], - ub[idx_a][1], - lb[idx_b][1], - ub[idx_b][1], - ) - end - else # Tighten McCormick - - # if m.nonconvex_terms[bi][:MONOMIAL_satus] - if m.nonconvex_terms[bi][:nonlinear_type] == :MONOMIAL - λ = Alp.amp_post_tmc_λ(m.model_mip, λ, lb, ub, part_cnt_a, idx_a) - λX = Alp.amp_post_tmc_λX(m.model_mip, λX, part_cnt_a, idx_a, idx_b) - Alp.amp_post_tmc_λxX_mc(m.model_mip, λX, λ, lb, ub, idx_a, idx_b) - Alp.amp_post_tmc_monomial_mc( - m.model_mip, - idx_ab, - λ, - λX, - lb, - ub, - part_cnt_a, - idx_a, - ) - # else - elseif m.nonconvex_terms[bi][:nonlinear_type] == :BILINEAR - # Partitioning on left - if (idx_a in m.disc_vars) && - !(idx_b in m.disc_vars) && - (part_cnt_b == 1) - λ = Alp.amp_post_tmc_λ(m.model_mip, λ, lb, ub, part_cnt_a, idx_a) - λX = - Alp.amp_post_tmc_λX(m.model_mip, λX, part_cnt_a, idx_a, idx_b) - λX[(idx_b, idx_a)] = [_index_to_variable_ref(m.model_mip, idx_a)] - λλ = Alp.amp_post_tmc_λλ(λλ, λ, idx_a, idx_b) - Alp.amp_post_tmc_λxX_mc(m.model_mip, λX, λ, lb, ub, idx_a, idx_b) - Alp.amp_post_tmc_XX_mc( - m.model_mip, - idx_ab, - λX, - λλ, - lb, - ub, - idx_a, - idx_b, - ) - end - - # Partitioning of right - if !(idx_a in m.disc_vars) && - (idx_b in m.disc_vars) && - (part_cnt_a == 1) - λ = Alp.amp_post_tmc_λ(m.model_mip, λ, lb, ub, part_cnt_b, idx_b) - λX = - Alp.amp_post_tmc_λX(m.model_mip, λX, part_cnt_b, idx_b, idx_a) - λX[(idx_a, idx_b)] = [_index_to_variable_ref(m.model_mip, idx_b)] - λλ = Alp.amp_post_tmc_λλ(λλ, λ, idx_b, idx_a) - Alp.amp_post_tmc_λxX_mc(m.model_mip, λX, λ, lb, ub, idx_b, idx_a) - Alp.amp_post_tmc_XX_mc( - m.model_mip, - idx_ab, - λX, - λλ, - lb, - ub, - idx_b, - idx_a, - ) - end - - # Partitioning on both variables - if (idx_a in m.disc_vars) && (idx_b in m.disc_vars) - λ = Alp.amp_post_tmc_λ(m.model_mip, λ, lb, ub, part_cnt_a, idx_a) - λ = Alp.amp_post_tmc_λ(m.model_mip, λ, lb, ub, part_cnt_b, idx_b) - λX = - Alp.amp_post_tmc_λX(m.model_mip, λX, part_cnt_a, idx_a, idx_b) - λX = - Alp.amp_post_tmc_λX(m.model_mip, λX, part_cnt_b, idx_b, idx_a) - λλ = Alp.amp_post_tmc_λλ( - m.model_mip, - λλ, - part_cnt_a, - part_cnt_b, - idx_a, - idx_b, - ) - Alp.amp_post_tmc_λxX_mc(m.model_mip, λX, λ, lb, ub, idx_a, idx_b) - Alp.amp_post_tmc_λxX_mc(m.model_mip, λX, λ, lb, ub, idx_b, idx_a) - Alp.amp_post_tmc_λxλ_mc(m.model_mip, λλ, λ, idx_a, idx_b) - Alp.amp_post_tmc_XX_mc( - m.model_mip, - idx_ab, - λX, - λλ, - lb, - ub, - idx_a, - idx_b, - ) - end - - # Error condition - #if !(idx_a in m.disc_vars) && !(idx_b in m.disc_vars) - # error("Error case. At least one term should show up in discretization choices.") - #end - end - end - end - end - return -end - -function amp_post_tmc_λ( - m::JuMP.Model, - λ::Dict, - lb::Dict, - ub::Dict, - dim::Int, - idx::Int, - relax = false, -) - if !haskey(λ, idx) - λ[idx] = JuMP.@variable(m, [1:dim], Bin, base_name = string("L", idx)) - JuMP.@constraint(m, sum(λ[idx]) == 1) # SOS-1 Constraints - JuMP.@constraint(m, _index_to_variable_ref(m, idx) >= dot(lb[idx], λ[idx])) - JuMP.@constraint(m, _index_to_variable_ref(m, idx) <= dot(ub[idx], λ[idx])) - end - - return λ -end - -function amp_post_tmc_monomial_mc( - m::JuMP.Model, - idx_aa::Int, - λ::Dict, - λX::Dict, - LB::Dict, - UB::Dict, - dim::Int, - idx_a::Int, -) - JuMP.@constraint( - m, - _index_to_variable_ref(m, idx_aa) >= _index_to_variable_ref(m, idx_a)^(2) - ) - JuMP.@constraint( - m, - _index_to_variable_ref(m, idx_aa) <= - dot(λX[(idx_a, idx_a)], LB[idx_a]) + dot(λX[(idx_a, idx_a)], UB[idx_a]) - - dot(λ[idx_a], *(Matrix(Diagonal(LB[idx_a])), UB[idx_a])) - ) - - return -end - -function amp_post_tmc_λX(m::JuMP.Model, λX::Dict, dim::Int, idx_a::Int, idx_b::Int) - if !haskey(λX, (idx_a, idx_b)) - λX[(idx_a, idx_b)] = - JuMP.@variable(m, [1:dim], base_name = string("L", idx_a, "X", idx_b)) - end - - return λX -end - -function amp_post_tmc_λλ( - m::JuMP.Model, - λλ::Dict, - dim_a::Int, - dim_b::Int, - idx_a::Int, - idx_b::Int, -) - if !haskey(λλ, (idx_a, idx_b)) - λλ[(idx_a, idx_b)] = JuMP.@variable( - m, - [1:dim_a, 1:dim_b], - base_name = string("L", idx_a, "L", idx_b) - ) - for i in 1:dim_a - for j in 1:dim_b - JuMP.set_lower_bound(λλ[(idx_a, idx_b)][i, j], 0) - JuMP.set_upper_bound(λλ[(idx_a, idx_b)][i, j], 1) - end - end - λλ[(idx_b, idx_a)] = λλ[(idx_a, idx_b)]' - end - - return λλ -end - -function amp_post_tmc_λλ(λλ::Dict, λ::Dict, idx_a::Int, idx_b::Int) - if !haskey(λλ, (idx_a, idx_b)) - λλ[(idx_a, idx_b)] = λ[idx_a] - λλ[(idx_a, idx_b)] = reshape(λλ[(idx_a, idx_b)], (length(λ[idx_a]), 1)) - λλ[(idx_b, idx_a)] = λλ[(idx_a, idx_b)]' - end - - return λλ -end - -function amp_post_tmc_XX_mc(m::JuMP.Model, ab, λX, λλ, LB, UB, a, b) - @assert length(LB[a]) == length(UB[a]) - @assert length(LB[b]) == length(UB[b]) - dim_A = length(LB[a]) - dim_B = length(LB[b]) - JuMP.@constraint( - m, - _index_to_variable_ref(m, ab) .>= - dot(λX[(a, b)], LB[a]) + dot(λX[(b, a)], LB[b]) - - reshape(LB[a], (1, dim_A)) * λλ[(a, b)] * reshape(LB[b], (dim_B, 1)) - ) - JuMP.@constraint( - m, - _index_to_variable_ref(m, ab) .>= - dot(λX[(a, b)], UB[a]) + dot(λX[(b, a)], UB[b]) - - reshape(UB[a], (1, dim_A)) * λλ[(a, b)] * reshape(UB[b], (dim_B, 1)) - ) - JuMP.@constraint( - m, - _index_to_variable_ref(m, ab) .<= - dot(λX[(a, b)], LB[a]) + dot(λX[(b, a)], UB[b]) - - reshape(LB[a], (1, dim_A)) * λλ[(a, b)] * reshape(UB[b], (dim_B, 1)) - ) - JuMP.@constraint( - m, - _index_to_variable_ref(m, ab) .<= - dot(λX[(a, b)], UB[a]) + dot(λX[(b, a)], LB[b]) - - reshape(UB[a], (1, dim_A)) * λλ[(a, b)] * reshape(LB[b], (dim_B, 1)) - ) - - return -end - -_lower_bound(x) = JuMP.is_binary(x) ? 0.0 : JuMP.lower_bound(x) -_upper_bound(x) = JuMP.is_binary(x) ? 1.0 : JuMP.upper_bound(x) - -function amp_post_tmc_λxX_mc( - m::JuMP.Model, - λX::Dict, - λ::Dict, - lb::Dict, - ub::Dict, - ind_λ::Int, - ind_X::Int, -) - - # X_u and λ here are vectors, and X is one variable, - # After the product, we have a polynomial to multiply X, - # forming |λ| new variables stored in λX dictionary - - dim_λ = length(λ[ind_λ]) # This is how many new variables to be generated - for i in 1:dim_λ - v = _index_to_variable_ref(m, ind_X) - lb_X = JuMP.lower_bound(v) - ub_X = JuMP.upper_bound(v) - lb_λ = _lower_bound(λ[ind_λ][i]) - ub_λ = _upper_bound(λ[ind_λ][i]) - @assert (lb_λ == 0.0) && (ub_λ == 1.0) - Alp.mccormick(m, λX[(ind_λ, ind_X)][i], λ[ind_λ][i], v, lb_λ, ub_λ, lb_X, ub_X) - end - - return -end - -function amp_post_tmc_λxλ_mc(m::JuMP.Model, λλ::Dict, λ::Dict, ind_A::Int, ind_B::Int) - - #= - A 3 x 2 example, some new variables are formed - | y11y21 y11y22 | | y11 | | y21 |T - | y12y21 y12y22 | = | y12 | x | | - | y13y21 y13y22 | | y13 | | y22 | - =# - - # Prepare the new variable, these two counts track the total count of new variables - dim_A = length(λ[ind_A]) - dim_B = length(λ[ind_B]) - for i in 1:dim_A - for j in 1:dim_B - JuMP.set_lower_bound(λλ[(ind_A, ind_B)][i, j], 0) - JuMP.set_upper_bound(λλ[(ind_A, ind_B)][i, j], 1) - end - end - - for i in 1:dim_A - for j in 1:dim_B - Alp.mccormick_bin(m, λλ[(ind_A, ind_B)][i, j], λ[ind_A][i], λ[ind_B][j]) - end - end - - return -end - -""" - mccormick(m::JuMP.Model, xy, x, y, x_l, x_u, y_l, y_u) - -Generic function to add a McCormick convex envelop, where `xy=x*y` and `x_l, x_u, y_l, y_u` are variable bounds. -""" -function mccormick( - m::JuMP.Model, - xy::JuMP.VariableRef, - x::JuMP.VariableRef, - y::JuMP.VariableRef, - lb_x, - ub_x, - lb_y, - ub_y, -) - JuMP.@constraint(m, xy >= lb_x * y + lb_y * x - lb_x * lb_y) - JuMP.@constraint(m, xy >= ub_x * y + ub_y * x - ub_x * ub_y) - JuMP.@constraint(m, xy <= lb_x * y + ub_y * x - lb_x * ub_y) - JuMP.@constraint(m, xy <= ub_x * y + lb_y * x - ub_x * lb_y) - - return -end - -function mccormick_binlin( - m::JuMP.Model, - binlin::JuMP.VariableRef, - bin::JuMP.VariableRef, - lin::JuMP.VariableRef, - lb, - ub, -) - - # TODO think about how to address this issue - warnuser = false - if ub == Inf - ub = 1e6 - warnuser = true - end - - if lb == -Inf - lb = -1e6 - warnuser = true - end - - if lb >= 0 - JuMP.@constraint(m, binlin <= ub * bin) - JuMP.@constraint(m, binlin <= lin) - JuMP.@constraint(m, binlin >= lin - (1 - bin) * ub) - else - JuMP.@constraint(m, binlin <= ub) - JuMP.@constraint(m, binlin >= lb) - JuMP.@constraint(m, binlin <= bin * ub) - JuMP.@constraint(m, binlin >= bin * lb) - JuMP.@constraint(m, binlin <= lin - (1 - bin) * lb) - JuMP.@constraint(m, binlin >= lin - (1 - bin) * ub) - end - - # Second position to handle inf bounds - warnuser && @warn "BINLIN term exception using -1e6/1e6 as lb/ub" - - return -end - -function mccormick_bin( - m::JuMP.Model, - xy::JuMP.VariableRef, - x::JuMP.VariableRef, - y::JuMP.VariableRef, -) - JuMP.@constraint(m, xy <= x) - JuMP.@constraint(m, xy <= y) - JuMP.@constraint(m, xy >= x + y - 1) - return -end - -# [TODO] Unused functions but will be used for later -function mccormick_monomial( - m::JuMP.Model, - xy::JuMP.VariableRef, - x::JuMP.VariableRef, - lb_x, - ub_x, -) - JuMP.@constraint(m, xy >= x^2) - JuMP.@constraint(m, xy <= (lb_x + ub_x) * x - (lb_x * ub_x)) - - return -end - -# Fortet linearization -# Reference: https://doi.org/10.1007/s10288-006-0015-3 -function binprod_relax(m::JuMP.Model, z::JuMP.VariableRef, x::Vector) - for i in x - JuMP.@constraint(m, z <= i) - end - JuMP.@constraint(m, z >= sum(x) - (length(x) - 1)) - - return -end - -#= -function tightmccormick_monomial(m,x_p,x,xz,lb_x,ub_x,z,p,lazy,quad) # if p=2, tightened_lazycuts = tightmccormick_quad - if lazy == 1 - function GetLazyCuts_quad(cb) - TOL1 = 1e-6 - if (getvalue(x)^p > (getvalue(x_p) + TOL1)) - a = p*getvalue(x)^(p-1) - b = (1-p)*getvalue(x)^p - @lazyconstraint(cb, a*x + b <= x_p) - end - end - addlazycallback(m, GetLazyCuts_quad) - elseif p == 2 && quad == 1 - JuMP.@constraint(m, x_p >= x^2) - else - x0_vec = sort(union(lb_x, ub_x)) - for x0 in x0_vec - JuMP.@constraint(m, x_p >= (1-p)*(x0)^p + p*(x0)^(p-1)*x) - end - end - - A = ((ub_x).^p-(lb_x).^p)./(ub_x-lb_x) - JuMP.@constraint(m, x_p .<= A'*xz - (A.*lb_x)'*z + ((lb_x).^p)'*z) - - return -end -=# diff --git a/src/utility.jl b/src/utility.jl index ddfc7f9f..dff7eed3 100644 --- a/src/utility.jl +++ b/src/utility.jl @@ -239,9 +239,9 @@ function fix_domains(m::Optimizer; discrete_sol = nothing, use_orig = false) end """ - is_fully_convexified(m::Optimizer) + _is_fully_convexified(m::Optimizer) """ -function is_fully_convexified(m::Optimizer) +function _is_fully_convexified(m::Optimizer) # Other more advanced convexification check goes here for term in keys(m.nonconvex_terms) @@ -345,16 +345,6 @@ function ncvar_collect_arcs(m::Optimizer, nodes::Vector) push!(arcs, sort([varidxs[1]; varidxs[1]])) end - # elseif m.nonconvex_terms[k][:nonlinear_type] == :INTLIN - # var_idxs = copy(m.nonconvex_terms[k][:var_idxs]) - # push!(arcs, sort(var_idxs)) - # elseif m.nonconvex_terms[k][:nonlinear_type] == :INTPROD - # var_idxs = m.nonconvex_terms[k][:var_idxs] - # for i in 1:length(var_idxs) - # for j in 1:length(var_idxs) - # i != j && push!(arcs, sort([var_idxs[i]; var_idxs[j]])) - # end - # end # elseif m.nonconvex_terms[k][:nonlinear_type] in [:cos, :sin] # @assert length(m.nonconvex_terms[k][:var_idxs]) == 1 # var_idx = m.nonconvex_terms[k][:var_idxs][1] diff --git a/src/bounds.jl b/src/variable_bounds.jl similarity index 96% rename from src/bounds.jl rename to src/variable_bounds.jl index df7bf7fe..e7786de6 100644 --- a/src/bounds.jl +++ b/src/variable_bounds.jl @@ -38,12 +38,6 @@ function init_disc(m::Optimizer) lb = m.l_var_tight[var] ub = m.u_var_tight[var] m.discretization[var] = [lb, ub] - elseif m.var_type[var] in [:Int] - Alp.get_option(m, :int_enable) ? lb = floor(m.l_var_tight[var]) - 0.5 : - lb = floor(m.l_var_tight[var]) - Alp.get_option(m, :int_enable) ? ub = ceil(m.u_var_tight[var]) + 0.5 : - ub = floor(m.u_var_tight[var]) - m.discretization[var] = [lb, ub] else error( "[EXCEPTION] Unexpected variable type when initializing discretization dictionary.", @@ -111,7 +105,6 @@ end Detect bounds from parse affine constraint. This function examines the one variable constraints such as x >= 5, x <= 5 or x == 5 and fetch the information to m.l_var_tight and m.u_var_tight. -This function can potential grow to be smarter. """ function bound_propagation(m::Optimizer) exhausted = false @@ -417,14 +410,8 @@ function resolve_var_bounds(m::Optimizer, d::Dict; kwargs...) d = Alp.basic_binint_bounds(m, nlk, d) elseif m.nonconvex_terms[nlk][:nonlinear_type] in [:BINPROD] d = Alp.basic_binprod_bounds(m, nlk, d) - # elseif m.nonconvex_terms[nlk][:nonlinear_type] in ALPINE_C_TRIGONOMETRIC - # d = basic_sincos_bounds(m, nlk, d) elseif m.nonconvex_terms[nlk][:nonlinear_type] in [:BINLIN] d = Alp.basic_binlin_bounds(m, nlk, d) - # elseif m.nonconvex_terms[nlk][:nonlinear_type] in [:INTLIN] - # d = basic_intlin_bounds(m, nlk, d) - # elseif m.nonconvex_terms[nlk][:nonlinear_type] in [:INTPROD] - # d = basic_intprod_bounds(m, nlk, d) else error("EXPECTED ERROR : NEED IMPLEMENTATION") end diff --git a/test/runtests.jl b/test/runtests.jl index 2464a074..9035a6bc 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -51,8 +51,8 @@ end # Perform Tests @testset "Alpine tests" begin - include(joinpath(@__DIR__, "test_solver.jl")) + # include(joinpath(@__DIR__, "test_solver.jl")) include(joinpath(@__DIR__, "test_expression.jl")) - include(joinpath(@__DIR__, "test_algorithm.jl")) - include(joinpath(@__DIR__, "test_utility.jl")) + # include(joinpath(@__DIR__, "test_algorithm.jl")) + # include(joinpath(@__DIR__, "test_utility.jl")) end diff --git a/test/test_algorithm.jl b/test/test_algorithm.jl index c10f7a15..f3b1878a 100644 --- a/test/test_algorithm.jl +++ b/test/test_algorithm.jl @@ -1,967 +1,973 @@ -@testset " Validation Test || AMP-TMC || basic solve || examples/nlp1.jl" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => PAVITO, - "bilinear_convexhull" => false, - "monomial_convexhull" => false, - "presolve_bt" => false, - "presolve_bp" => true, - "presolve_bt_bound_tol" => 1e-1, - "disc_ratio" => 10, - "log_level" => 100, - ) - m = nlp1(solver = test_solver) - JuMP.optimize!(m) - - @test termination_status(m) == MOI.OPTIMAL - @test isapprox(objective_value(m), 58.38367169858795; atol = 1e-4) - @test MOI.get(m, Alpine.NumberOfIterations()) == 4 -end - -@testset " Validation Test || AMP-TMC || basic solve || examples/nlp3.jl (2 iterations)" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "bilinear_convexhull" => false, - "monomial_convexhull" => false, - "presolve_bp" => true, - "log_level" => 100, - "max_iter" => 2, - "presolve_bt_width_tol" => 1e-3, - "presolve_bt" => false, - "disc_ratio" => 10, - "disc_var_pick" => 0, - ) - m = nlp3(solver = test_solver) - JuMP.optimize!(m) - - @test termination_status(m) == MOI.OTHER_LIMIT - - @test isapprox(objective_value(m), 7049.247897696512; atol = 1e-4) - @test MOI.get(m, Alpine.NumberOfIterations()) == 2 -end - -@testset " Validation Test || AMP-TMC || minimum-vertex solving || examples/nlp3.jl (3 iterations)" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "bilinear_convexhull" => false, - "monomial_convexhull" => false, - "presolve_bp" => true, - "disc_var_pick" => 1, - "log_level" => 100, - "max_iter" => 2, - "disc_ratio" => 10, - "presolve_bt_width_tol" => 1e-3, - "presolve_bt" => false, - ) - m = nlp3(solver = test_solver) - JuMP.optimize!(m) - - @test termination_status(m) == MOI.OTHER_LIMIT - @test isapprox(objective_value(m), 7049.247897696512; atol = 1e-4) - @test MOI.get(m, Alpine.NumberOfIterations()) == 2 -end - -@testset " Validation Test || BT-AMP-TMC || basic solve || examples/nlp3.jl" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "bilinear_convexhull" => false, - "log_level" => 100, - "max_iter" => 2, - "disc_ratio" => 10, - "presolve_bt_width_tol" => 1e-3, - "presolve_bt_bound_tol" => 1e-1, - "presolve_bt" => true, - "presolve_bt_algo" => 1, - "presolve_bp" => true, - "presolve_bt_max_iter" => 2, - "presolve_track_time" => true, - "disc_var_pick" => max_cover_var_picker, - ) - m = nlp3(solver = test_solver) - - JuMP.optimize!(m) - - @test termination_status(m) == MOI.OTHER_LIMIT - @test MOI.get(m, Alpine.NumberOfIterations()) == 2 - @test MOI.get(m, Alpine.NumberOfPresolveIterations()) == 2 - - vars = all_variables(m) - LB = [100, 1000, 1000, 10, 150.2, 10, 35.4, 168] - UB = [4573.6, 5547.8, 5913.3, 332.4, 551, 390, 571.1, 638.7] - @test isapprox(MOI.get.(m, Alpine.TightenedLowerBound(), vars), LB, atol = 1E-6) - @test isapprox(MOI.get.(m, Alpine.TightenedUpperBound(), vars), UB, atol = 1E-6) -end - -# FIXME Pavito terminates with `NUMERICAL_ERROR` on Julia v1.0: -@testset " Validation Test || PBT-AMP-TMC || basic solve || examples/nlp3.jl" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "bilinear_convexhull" => false, - "log_level" => 100, - "max_iter" => 2, - "disc_ratio" => 10, - "presolve_bt" => true, - "presolve_bt_width_tol" => 1e-3, - "presolve_bt_bound_tol" => 1e-1, - "presolve_bt_algo" => 2, - "presolve_bp" => true, - "presolve_bt_max_iter" => 2, - "disc_var_pick" => max_cover_var_picker, - ) - - m = nlp3(solver = test_solver) - JuMP.optimize!(m) - @test termination_status(m) == MOI.OTHER_LIMIT - @test MOI.get(m, Alpine.NumberOfIterations()) == 2 -end - -@testset " Validation Test || AMP-CONV || basic solve || examples/nlp1.jl" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => PAVITO, - "bilinear_convexhull" => true, - "monomial_convexhull" => true, - "presolve_bt" => false, - "presolve_bp" => true, - "disc_ratio" => 12, - ) - m = nlp1(solver = test_solver) - JuMP.optimize!(m) - - @test termination_status(m) == MOI.OPTIMAL - @test isapprox(objective_value(m), 58.38367169858795; atol = 1e-5) - @test MOI.get(m, Alpine.NumberOfIterations()) == 3 -end - -@testset " Validation Test || AMP-CONV || basic solve || examples/nlp3.jl" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "bilinear_convexhull" => true, - "monomial_convexhull" => true, - "presolve_bt" => false, - "presolve_bp" => false, - "disc_ratio" => 14, - "max_iter" => 4, - "log_level" => 100, - ) - m = nlp3(solver = test_solver) - JuMP.optimize!(m) - - @test termination_status(m) == MOI.OTHER_LIMIT - @test isapprox(objective_value(m), 7049.24789; atol = 1e-4) - @test isapprox(objective_bound(m), 6839.487709940, atol = 1E-4) - @test MOI.get(m, Alpine.NumberOfIterations()) == 4 -end - -@testset " Validation Test || AMP || basic solve || examples/circle.jl" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => PAVITO, - "disc_abs_width_tol" => 1e-3, - "disc_ratio" => 8, - "max_iter" => 6, - "presolve_bt" => false, - "log_level" => 100, - ) - - m = circle(solver = test_solver) - # This is fixed in Alpine - TODO (odow): cycling detected in Pavito when disc_abs_width_tol = 1E-2 - JuMP.optimize!(m) - @test isapprox(objective_value(m), 1.4142135534556992; atol = 1e-3) -end - -@testset " Validation Test || AMP || basic solve || examples/circle_MINLPLib.jl" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => PAVITO, - "presolve_bt" => false, - "disc_ratio" => 15, - "max_iter" => 2, - ) - - m = circle_MINLPLib(solver = test_solver) - - JuMP.optimize!(m) - @test termination_status(m) == MOI.OTHER_LIMIT - @test isapprox(objective_value(m), 4.45670663096; atol = 1E-6) -end - -@testset " Validation Test || AMP-CONV-FACET || basic solve || examples/nlp3.jl" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "bilinear_convexhull" => true, - "monomial_convexhull" => true, - "presolve_bt" => false, - "presolve_bp" => true, - "convhull_formulation" => "facet", - "max_iter" => 3, - "log_level" => 100, - ) - m = nlp3(solver = test_solver) - JuMP.optimize!(m) - - @test isapprox(objective_value(m), 7049.247897696188; atol = 1e-4) - @test isapprox(objective_bound(m), 6654.6983279983; atol = 1e-4) - @test MOI.get(m, Alpine.NumberOfIterations()) == 3 -end - -@testset " Validation Test || AMP || multi4N || N = 2 || exprmode=1:11" begin - n_instances = 5 - objValVec = 2.0 * ones(n_instances) - - for i in 1:n_instances - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "disc_abs_width_tol" => 1e-2, - "max_iter" => 4, - "disc_ratio" => 4, - "presolve_bp" => false, - "presolve_bt" => false, - "log_level" => 1, - ) - - m = multi4N(solver = test_solver, N = 2, exprmode = i) - JuMP.optimize!(m) - - @test termination_status(m) == MOI.OTHER_LIMIT - @test isapprox(objective_value(m), objValVec[i]; atol = 1e-3) - end -end - -@testset " Validation Test || AMP || multi2 || exprmode=1:11" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "disc_abs_width_tol" => 1e-2, - "max_iter" => 5, - "presolve_bt" => false, - "log_level" => 1, - ) - - m = multi2(solver = test_solver) - JuMP.optimize!(m) - @test termination_status(m) == MOI.OPTIMAL - @test isapprox(objective_value(m), 0.92906489; atol = 1e-3) -end - -@testset " Validation Test || AMP || multi3N || N = 2 || exprmode=1:11" begin - n_instances = 3 - objValVec = 2.0 * ones(n_instances) - - objBoundVec = Any[2.97186, 3.85492, 4.23375] - - for i in 1:n_instances - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "disc_abs_width_tol" => 1e-2, - "max_iter" => 4, - "disc_ratio" => 4, - "presolve_bp" => false, - "presolve_bt" => false, - "log_level" => 1, - ) - - m = multi3N(solver = test_solver, N = 2, exprmode = i) - JuMP.optimize!(m) - - @test termination_status(m) == MOI.OTHER_LIMIT - @test isapprox(objective_value(m), objValVec[i]; atol = 1e-3) - @test objective_bound(m) <= objBoundVec[i] + 1e-3 - end -end - -@testset " Validation Test || AMP || multiKND || K = 3, N = 3, D = 0 " begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "disc_abs_width_tol" => 1e-2, - "max_iter" => 3, - "disc_ratio" => 4, - "presolve_bp" => false, - "presolve_bt" => false, - "log_level" => 1, - ) - - m = multiKND(solver = test_solver, randomub = 50, K = 3, N = 3, D = 0) - JuMP.optimize!(m) - - @test termination_status(m) == MOI.OTHER_LIMIT - @test isapprox(objective_value(m), 3.0000000824779454; atol = 1e-3) - @test isapprox(objective_bound(m), 12.054604248046875; atol = 1e-3) -end - -@testset " Validation Test || AMP-CONV-FACET || basic solve || examples/nlp3.jl" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "bilinear_convexhull" => true, - "monomial_convexhull" => true, - "presolve_bt" => false, - "presolve_bp" => false, - "max_iter" => 3, - "disc_ratio" => 4, - "convhull_formulation" => "facet", - "log_level" => 100, - ) - m = nlp3(solver = test_solver) - JuMP.optimize!(m) - - @test termination_status(m) == MOI.OTHER_LIMIT - @test isapprox(objective_value(m), 7049.247897696188; atol = 1e-4) - @test isapprox(objective_bound(m), 5871.530692199214; atol = 1E-5) - @test MOI.get(m, Alpine.NumberOfIterations()) == 3 -end - -@testset " Validation Test || AMP || DISC-RATIO || examples/nlp3.jl " begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "disc_abs_width_tol" => 1e-2, - "disc_ratio_branch" => false, - "disc_ratio" => 18, - "max_iter" => 1, - "presolve_bp" => true, - "presolve_bt" => false, - "log_level" => 100, - ) - - m = nlp3(solver = test_solver) - JuMP.optimize!(m) - - @test MOI.get(m, Alpine.NumberOfIterations()) == 1 - @test MOI.get(m, MOI.RawOptimizerAttribute("disc_ratio")) == 18 -end - -@testset " Validation Test || AMP || DISC-RATIO-BRANCH || examples/nlp3.jl " begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "disc_abs_width_tol" => 1e-2, - "disc_ratio_branch" => true, - "max_iter" => 1, - "presolve_bp" => true, - "presolve_bt" => false, - "log_level" => 100, - ) - - m = nlp3(solver = test_solver) - JuMP.optimize!(m) - - @test MOI.get(m, Alpine.NumberOfIterations()) == 1 - @test MOI.get(m, MOI.RawOptimizerAttribute("disc_ratio")) == 14 -end - -@testset " Validation Test || AMP || DISC-RATIO-BRANCH || examples/castro2m2.jl " begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "disc_abs_width_tol" => 1e-2, - "disc_ratio_branch" => true, - "max_iter" => 1, - "presolve_bp" => true, - "presolve_bt" => false, - "log_level" => 100, - ) - - m = castro2m2(solver = test_solver) - JuMP.optimize!(m) - - @test MOI.get(m, Alpine.NumberOfIterations()) == 1 - @test MOI.get(m, MOI.RawOptimizerAttribute("disc_ratio")) == 8 -end - -@testset " Validation Test || AMP || DISC-RATIO-BRANCH || examples/multi3N.jl exprmode=2" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "disc_abs_width_tol" => 1e-2, - "disc_ratio_branch" => true, - "max_iter" => 1, - "presolve_bp" => true, - "presolve_bt" => false, - "log_level" => 100, - ) - - m = multi3N(solver = test_solver, N = 3, exprmode = 1) - JuMP.optimize!(m) - - @test MOI.get(m, Alpine.NumberOfIterations()) == 1 - @test MOI.get(m, MOI.RawOptimizerAttribute("disc_ratio")) == 16 -end - -@testset " Validation Test || AMP || DISC-RATIO-BRANCH || examples/multi3N.jl exprmode=2" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "disc_abs_width_tol" => 1e-2, - "disc_ratio_branch" => true, - "max_iter" => 1, - "presolve_bp" => false, - "presolve_bt" => false, - "log_level" => 100, - ) - - m = multi3N(solver = test_solver, N = 3, exprmode = 1) - JuMP.optimize!(m) - - @test MOI.get(m, Alpine.NumberOfIterations()) == 1 - @test MOI.get(m, MOI.RawOptimizerAttribute("disc_ratio")) == 20 -end - -@testset " Validation Test || AMP || DISC-RATIO-BRANCH || examples/multi4N.jl exprmode=1" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "disc_abs_width_tol" => 1e-2, - "disc_ratio_branch" => true, - "max_iter" => 1, - "presolve_bp" => true, - "presolve_bt" => false, - "log_level" => 100, - ) - - m = multi4N(solver = test_solver, N = 2, exprmode = 1) - JuMP.optimize!(m) - - @test MOI.get(m, Alpine.NumberOfIterations()) == 1 - @test MOI.get(m, MOI.RawOptimizerAttribute("disc_ratio")) == 12 -end - -@testset " Validation Test || AMP || DISC-RATIO-BRANCH || examples/multi4N.jl exprmode=2" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "disc_abs_width_tol" => 1e-2, - "disc_ratio_branch" => true, - "max_iter" => 1, - "presolve_bp" => false, - "presolve_bt" => false, - "log_level" => 100, - ) - - m = multi4N(solver = test_solver, N = 2, exprmode = 1) - JuMP.optimize!(m) - - @test MOI.get(m, Alpine.NumberOfIterations()) == 1 - @test MOI.get(m, MOI.RawOptimizerAttribute("disc_ratio")) == 20 -end - -@testset " Validation Test || AMP || DISC-RATIO-BRANCH || examples/multi4N.jl exprmode=2" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "disc_abs_width_tol" => 1e-2, - "disc_ratio_branch" => true, - "max_iter" => 1, - "presolve_bp" => true, - "presolve_bt" => false, - "log_level" => 100, - ) - - m = multi4N(solver = test_solver, N = 2, exprmode = 2) - JuMP.optimize!(m) - - @test MOI.get(m, Alpine.NumberOfIterations()) == 1 - @test MOI.get(m, MOI.RawOptimizerAttribute("disc_ratio")) == 20 -end - -@testset "Operator :: bmpl && binlin && binprod solve test I" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "minlp_solver" => PAVITO, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "presolve_bt" => false, - "log_level" => 100, - ) - - m = bpml_lnl(solver = test_solver) - JuMP.optimize!(m) - @test isapprox(objective_value(m), 0.3; atol = 1e-6) - alpine = JuMP.backend(m).optimizer.model - @test haskey(alpine.nonconvex_terms, Expr[:(x[1]), :(x[6])]) - @test haskey(alpine.nonconvex_terms, Expr[:(x[2]), :(x[7])]) - @test haskey(alpine.nonconvex_terms, Expr[:(x[3]), :(x[8])]) - @test haskey(alpine.nonconvex_terms, Expr[:(x[4]), :(x[9])]) - @test haskey(alpine.nonconvex_terms, Expr[:(x[5]), :(x[10])]) - - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[6])]][:nonlinear_type] == :BINLIN - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[7])]][:nonlinear_type] == :BINLIN - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[8])]][:nonlinear_type] == :BINLIN - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[9])]][:nonlinear_type] == :BINLIN - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[10])]][:nonlinear_type] == :BINLIN -end - -@testset "Operator :: bmpl && binlin && binprod solve test II" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "minlp_solver" => JUNIPER, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "presolve_bt" => false, - "disc_ratio" => 4, - "log_level" => 100, - ) - - m = bpml_binl(solver = test_solver) - - # FIXME: Deactivating this until Juniper v0.9.0's numerical issues are fixed. - # JuMP.optimize!(m) - # @test isapprox(JuMP.objective_value(m), 22812.76415926; atol=1e-6) - # alpine = JuMP.backend(m).optimizer.model - - alpine = _build(m) - @test haskey(alpine.nonconvex_terms, Expr[:(x[6]), :(x[7])]) - @test haskey(alpine.nonconvex_terms, Expr[:(x[7]), :(x[8])]) - @test haskey(alpine.nonconvex_terms, Expr[:(x[8]), :(x[9])]) - @test haskey(alpine.nonconvex_terms, Expr[:(x[9]), :(x[10])]) - @test haskey(alpine.nonconvex_terms, Expr[:(x[10]), :(x[6])]) - @test haskey(alpine.nonconvex_terms, Expr[:(x[1]), :(x[11])]) - @test haskey(alpine.nonconvex_terms, Expr[:(x[2]), :(x[13])]) - @test haskey(alpine.nonconvex_terms, Expr[:(x[3]), :(x[15])]) - @test haskey(alpine.nonconvex_terms, Expr[:(x[4]), :(x[17])]) - @test haskey(alpine.nonconvex_terms, Expr[:(x[5]), :(x[19])]) - - @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[7])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[7]), :(x[8])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[8]), :(x[9])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[6])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[11])]][:nonlinear_type] == :BINLIN - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[13])]][:nonlinear_type] == :BINLIN - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[15])]][:nonlinear_type] == :BINLIN - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[17])]][:nonlinear_type] == :BINLIN - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[19])]][:nonlinear_type] == :BINLIN -end - -@testset "Embedding Test || AMP-CONV || basic solve || examples/nlp1.jl" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => PAVITO, - "bilinear_convexhull" => true, - "monomial_convexhull" => true, - "presolve_bt" => false, - "presolve_bp" => true, - "convhull_ebd" => true, - "max_iter" => 4, - "disc_ratio" => 4, - "log_level" => 100, - ) - - m = nlp1(solver = test_solver) - JuMP.optimize!(m) - - @test termination_status(m) == MOI.OTHER_LIMIT - @test isapprox(objective_value(m), 58.38367169858795; atol = 1e-4) - @test MOI.get(m, Alpine.NumberOfIterations()) == 4 -end - -@testset "Embedding IBS Test || AMP-CONV || basic solve || examples/nlp1.jl" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => PAVITO, - "bilinear_convexhull" => true, - "monomial_convexhull" => true, - "presolve_bt" => false, - "presolve_bp" => true, - "convhull_ebd" => true, - "convhull_ebd_ibs" => true, - "disc_ratio" => 8, - "log_level" => 100, - ) - m = nlp1(solver = test_solver) - JuMP.optimize!(m) - - @test termination_status(m) == MOI.OPTIMAL - @test isapprox(objective_value(m), 58.38367169858795; atol = 1e-5) - @test MOI.get(m, Alpine.NumberOfIterations()) == 4 -end - -@testset "Embedding IBS Test || AMP-CONV || basic solve || examples/nlp3.jl" begin - test_solver = optimizer_with_attributes( +# @testset " Validation Test || AMP-TMC || basic solve || examples/nlp3.jl (2 iterations)" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# # "bilinear_convexhull" => false, +# # "monomial_convexhull" => false, +# "presolve_bp" => true, +# "max_iter" => 2, +# "presolve_bt_width_tol" => 1e-3, +# "presolve_bt" => false, +# "partition_scaling_factor" => 10, +# "disc_var_pick" => 0, +# ) +# m = nlp3(solver = test_solver) +# JuMP.optimize!(m) + +# @test termination_status(m) == MOI.OTHER_LIMIT + +# @test isapprox(objective_value(m), 7049.247897696512; atol = 1e-4) +# @test MOI.get(m, Alpine.NumberOfIterations()) == 2 +# end + +# @testset " Validation Test || AMP-TMC || minimum-vertex solving || examples/nlp3.jl (3 iterations)" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# # "bilinear_convexhull" => false, +# # "monomial_convexhull" => false, +# "presolve_bp" => true, +# "disc_var_pick" => 1, +# "max_iter" => 2, +# "partition_scaling_factor" => 10, +# "presolve_bt_width_tol" => 1e-3, +# "presolve_bt" => false, +# ) +# m = nlp3(solver = test_solver) +# JuMP.optimize!(m) + +# @test termination_status(m) == MOI.OTHER_LIMIT +# @test isapprox(objective_value(m), 7049.247897696512; atol = 1e-4) +# @test MOI.get(m, Alpine.NumberOfIterations()) == 2 +# end + +# @testset " Validation Test || BT-AMP-TMC || basic solve || examples/nlp3.jl" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# # "bilinear_convexhull" => false, +# "log_level" => 100, +# "max_iter" => 2, +# "partition_scaling_factor" => 10, +# "presolve_bt_width_tol" => 1e-3, +# "presolve_bt_bound_tol" => 1e-1, +# "presolve_bt" => true, +# "presolve_bt_algo" => 1, +# "presolve_bp" => true, +# "presolve_bt_max_iter" => 2, +# "presolve_track_time" => true, +# "disc_var_pick" => max_cover_var_picker, +# ) +# m = nlp3(solver = test_solver) + +# JuMP.optimize!(m) + +# @test termination_status(m) == MOI.OTHER_LIMIT +# @test MOI.get(m, Alpine.NumberOfIterations()) == 2 +# @test MOI.get(m, Alpine.NumberOfPresolveIterations()) == 2 + +# vars = all_variables(m) +# LB = [100, 1000, 1000, 10, 150.2, 10, 35.4, 168] +# UB = [4573.6, 5547.8, 5913.3, 332.4, 551, 390, 571.1, 638.7] +# @test isapprox(MOI.get.(m, Alpine.TightenedLowerBound(), vars), LB, atol = 1E-6) +# @test isapprox(MOI.get.(m, Alpine.TightenedUpperBound(), vars), UB, atol = 1E-6) +# end + +# # FIXME Pavito terminates with `NUMERICAL_ERROR` on Julia v1.0: +# @testset " Validation Test || PBT-AMP-TMC || basic solve || examples/nlp3.jl" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# # "bilinear_convexhull" => false, +# "log_level" => 100, +# "max_iter" => 2, +# "partition_scaling_factor" => 10, +# "presolve_bt" => true, +# "presolve_bt_width_tol" => 1e-3, +# "presolve_bt_bound_tol" => 1e-1, +# "presolve_bt_algo" => 2, +# "presolve_bp" => true, +# "presolve_bt_max_iter" => 2, +# "disc_var_pick" => max_cover_var_picker, +# ) + +# m = nlp3(solver = test_solver) +# JuMP.optimize!(m) +# @test termination_status(m) == MOI.OTHER_LIMIT +# @test MOI.get(m, Alpine.NumberOfIterations()) == 2 +# end + +# @testset " Validation Test || AMP-CONV || basic solve || examples/nlp1.jl" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => PAVITO, +# # "bilinear_convexhull" => true, +# # "monomial_convexhull" => true, +# "presolve_bt" => false, +# "presolve_bp" => true, +# "partition_scaling_factor" => 12, +# "max_iter" => 1, +# ) +# m = nlp1(solver = test_solver) +# JuMP.optimize!(m) + +# @test termination_status(m) == MOI.OTHER_LIMIT +# @test isapprox(objective_value(m), 58.38367169858795; atol = 1e-5) +# @test MOI.get(m, Alpine.NumberOfIterations()) == 1 +# end + +# @testset " Validation Test || AMP-CONV || basic solve || examples/nlp3.jl" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# # "bilinear_convexhull" => true, +# # "monomial_convexhull" => true, +# "presolve_bt" => false, +# "presolve_bp" => false, +# "partition_scaling_factor" => 14, +# "max_iter" => 4, +# "log_level" => 100, +# ) +# m = nlp3(solver = test_solver) +# JuMP.optimize!(m) + +# @test termination_status(m) == MOI.OTHER_LIMIT +# @test isapprox(objective_value(m), 7049.24789; atol = 1e-4) +# @test isapprox(objective_bound(m), 6839.487709940, atol = 1E-4) +# @test MOI.get(m, Alpine.NumberOfIterations()) == 4 +# end + +# @testset " Validation Test || AMP || basic solve || examples/circle.jl" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => PAVITO, +# "disc_abs_width_tol" => 1e-3, +# "partition_scaling_factor" => 8, +# "max_iter" => 6, +# "presolve_bt" => false, +# "log_level" => 100, +# ) + +# m = circle(solver = test_solver) +# # This is fixed in Alpine - TODO (odow): cycling detected in Pavito when disc_abs_width_tol = 1E-2 +# JuMP.optimize!(m) +# @test isapprox(objective_value(m), 1.4142135534556992; atol = 1e-3) +# end + +# @testset " Validation Test || AMP || basic solve || examples/circle_MINLPLib.jl" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => PAVITO, +# "presolve_bt" => false, +# "partition_scaling_factor" => 15, +# "max_iter" => 2, +# ) + +# m = circle_MINLPLib(solver = test_solver) + +# JuMP.optimize!(m) +# @test termination_status(m) == MOI.OPTIMAL +# @test isapprox(objective_value(m), 4.45670663096; atol = 1E-6) +# end + +# @testset " Validation Test || AMP-CONV-FACET || basic solve || examples/nlp3.jl" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# # "bilinear_convexhull" => true, +# # "monomial_convexhull" => true, +# "presolve_bt" => false, +# "presolve_bp" => true, +# "convhull_formulation" => "facet", +# "max_iter" => 3, +# "log_level" => 100, +# ) +# m = nlp3(solver = test_solver) +# JuMP.optimize!(m) + +# @test isapprox(objective_value(m), 7049.247897696188; atol = 1e-4) +# @test isapprox(objective_bound(m), 6654.6983279983; atol = 1e-4) +# @test MOI.get(m, Alpine.NumberOfIterations()) == 3 +# end + +# @testset " Validation Test || AMP || multi4N || N = 2 || exprmode=1:11" begin +# n_instances = 5 +# objValVec = 2.0 * ones(n_instances) + +# for i in 1:n_instances +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "disc_abs_width_tol" => 1e-2, +# "max_iter" => 4, +# "partition_scaling_factor" => 4, +# "presolve_bp" => false, +# "presolve_bt" => false, +# "log_level" => 1, +# ) + +# m = multi4N(solver = test_solver, N = 2, exprmode = i) +# JuMP.optimize!(m) + +# @test termination_status(m) == MOI.OTHER_LIMIT +# @test isapprox(objective_value(m), objValVec[i]; atol = 1e-3) +# end +# end + +# @testset " Validation Test || AMP || multi2 || exprmode=1:11" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "disc_abs_width_tol" => 1e-2, +# "max_iter" => 5, +# "presolve_bt" => false, +# "log_level" => 1, +# ) + +# m = multi2(solver = test_solver) +# JuMP.optimize!(m) +# @test termination_status(m) == MOI.OPTIMAL +# @test isapprox(objective_value(m), 0.92906489; atol = 1e-3) +# end + +# @testset " Validation Test || AMP || multi3N || N = 2 || exprmode=1:11" begin +# n_instances = 3 +# objValVec = 2.0 * ones(n_instances) + +# objBoundVec = Any[2.97186, 3.85492, 4.23375] + +# for i in 1:n_instances +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "disc_abs_width_tol" => 1e-2, +# "max_iter" => 4, +# "partition_scaling_factor" => 4, +# "presolve_bp" => false, +# "presolve_bt" => false, +# "log_level" => 1, +# ) + +# m = multi3N(solver = test_solver, N = 2, exprmode = i) +# JuMP.optimize!(m) + +# @test termination_status(m) == MOI.OTHER_LIMIT +# @test isapprox(objective_value(m), objValVec[i]; atol = 1e-3) +# @test objective_bound(m) <= objBoundVec[i] + 1e-3 +# end +# end + +# @testset " Validation Test || AMP || multiKND || K = 3, N = 3, D = 0 " begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "disc_abs_width_tol" => 1e-2, +# "max_iter" => 3, +# "partition_scaling_factor" => 4, +# "presolve_bp" => false, +# "presolve_bt" => false, +# "log_level" => 1, +# ) + +# m = multiKND(solver = test_solver, randomub = 50, K = 3, N = 3, D = 0) +# JuMP.optimize!(m) + +# @test termination_status(m) == MOI.OTHER_LIMIT +# @test isapprox(objective_value(m), 3.0000000824779454; atol = 1e-3) +# @test isapprox(objective_bound(m), 12.054604248046875; atol = 1e-3) +# end + +# @testset " Validation Test || AMP-CONV-FACET || basic solve || examples/nlp3.jl" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# # "bilinear_convexhull" => true, +# # "monomial_convexhull" => true, +# "presolve_bt" => false, +# "presolve_bp" => false, +# "max_iter" => 3, +# "partition_scaling_factor" => 4, +# "convhull_formulation" => "facet", +# "log_level" => 100, +# ) +# m = nlp3(solver = test_solver) +# JuMP.optimize!(m) + +# @test termination_status(m) == MOI.OTHER_LIMIT +# @test isapprox(objective_value(m), 7049.247897696188; atol = 1e-4) +# @test isapprox(objective_bound(m), 5871.530692199214; atol = 1E-5) +# @test MOI.get(m, Alpine.NumberOfIterations()) == 3 +# end + +# @testset " Validation Test || AMP || PARTITION-SCALING-FACTOR || examples/nlp3.jl " begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "disc_abs_width_tol" => 1e-2, +# "partition_scaling_factor_branch" => false, +# "partition_scaling_factor" => 18, +# "max_iter" => 1, +# "presolve_bp" => true, +# "presolve_bt" => false, +# "log_level" => 100, +# ) + +# m = nlp3(solver = test_solver) +# JuMP.optimize!(m) + +# @test MOI.get(m, Alpine.NumberOfIterations()) == 1 +# @test MOI.get(m, MOI.RawOptimizerAttribute("partition_scaling_factor")) == 18 +# end + +# @testset " Validation Test || AMP || PARTITION-SCALING-FACTOR-BRANCH || examples/nlp3.jl " begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "disc_abs_width_tol" => 1e-2, +# "partition_scaling_factor_branch" => true, +# "max_iter" => 1, +# "presolve_bp" => true, +# "presolve_bt" => false, +# "log_level" => 100, +# ) + +# m = nlp3(solver = test_solver) +# JuMP.optimize!(m) + +# @test MOI.get(m, Alpine.NumberOfIterations()) == 1 +# @test MOI.get(m, MOI.RawOptimizerAttribute("partition_scaling_factor")) == 14 +# end + +# @testset " Validation Test || AMP || PARTITION-SCALING-FACTOR-BRANCH || examples/castro2m2.jl " begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "disc_abs_width_tol" => 1e-2, +# "partition_scaling_factor_branch" => true, +# "max_iter" => 1, +# "presolve_bp" => true, +# "presolve_bt" => false, +# "log_level" => 100, +# ) + +# m = castro2m2(solver = test_solver) +# JuMP.optimize!(m) + +# @test MOI.get(m, Alpine.NumberOfIterations()) == 1 +# @test MOI.get(m, MOI.RawOptimizerAttribute("partition_scaling_factor")) == 8 +# end + +# @testset " Validation Test || AMP || PARTITION-SCALING-FACTOR-BRANCH || examples/multi3N.jl exprmode=2" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "disc_abs_width_tol" => 1e-2, +# "partition_scaling_factor_branch" => true, +# "max_iter" => 1, +# "presolve_bp" => true, +# "presolve_bt" => false, +# "log_level" => 100, +# ) + +# m = multi3N(solver = test_solver, N = 3, exprmode = 1) +# JuMP.optimize!(m) + +# @test MOI.get(m, Alpine.NumberOfIterations()) == 1 +# @test MOI.get(m, MOI.RawOptimizerAttribute("partition_scaling_factor")) == 16 +# end + +# @testset " Validation Test || AMP || PARTITION-SCALING-FACTOR-BRANCH || examples/multi3N.jl exprmode=2" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "disc_abs_width_tol" => 1e-2, +# "partition_scaling_factor_branch" => true, +# "max_iter" => 1, +# "presolve_bp" => false, +# "presolve_bt" => false, +# "log_level" => 100, +# ) + +# m = multi3N(solver = test_solver, N = 3, exprmode = 1) +# JuMP.optimize!(m) + +# @test MOI.get(m, Alpine.NumberOfIterations()) == 1 +# @test MOI.get(m, MOI.RawOptimizerAttribute("partition_scaling_factor")) == 20 +# end + +# @testset " Validation Test || AMP || PARTITION-SCALING-FACTOR-BRANCH || examples/multi4N.jl exprmode=1" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "disc_abs_width_tol" => 1e-2, +# "partition_scaling_factor_branch" => true, +# "max_iter" => 1, +# "presolve_bp" => true, +# "presolve_bt" => false, +# "log_level" => 100, +# ) + +# m = multi4N(solver = test_solver, N = 2, exprmode = 1) +# JuMP.optimize!(m) + +# @test MOI.get(m, Alpine.NumberOfIterations()) == 1 +# @test MOI.get(m, MOI.RawOptimizerAttribute("partition_scaling_factor")) == 12 +# end + +# @testset " Validation Test || AMP || PARTITION-SCALING-FACTOR-BRANCH || examples/multi4N.jl exprmode=2" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "disc_abs_width_tol" => 1e-2, +# "partition_scaling_factor_branch" => true, +# "max_iter" => 1, +# "presolve_bp" => false, +# "presolve_bt" => false, +# "log_level" => 100, +# ) + +# m = multi4N(solver = test_solver, N = 2, exprmode = 1) +# JuMP.optimize!(m) + +# @test MOI.get(m, Alpine.NumberOfIterations()) == 1 +# @test MOI.get(m, MOI.RawOptimizerAttribute("partition_scaling_factor")) == 20 +# end + +# @testset " Validation Test || AMP || PARTITION-SCALING-FACTOR-BRANCH || examples/multi4N.jl exprmode=2" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "disc_abs_width_tol" => 1e-2, +# "partition_scaling_factor_branch" => true, +# "max_iter" => 1, +# "presolve_bp" => true, +# "presolve_bt" => false, +# "log_level" => 100, +# ) + +# m = multi4N(solver = test_solver, N = 2, exprmode = 2) +# JuMP.optimize!(m) + +# @test MOI.get(m, Alpine.NumberOfIterations()) == 1 +# @test MOI.get(m, MOI.RawOptimizerAttribute("partition_scaling_factor")) == 20 +# end + +# @testset "Operator :: bmpl && binlin && binprod solve test I" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "minlp_solver" => PAVITO, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "presolve_bt" => false, +# "log_level" => 100, +# ) + +# m = bpml_lnl(solver = test_solver) +# JuMP.optimize!(m) +# @test isapprox(objective_value(m), 0.3; atol = 1e-6) +# alpine = JuMP.backend(m).optimizer.model +# @test haskey(alpine.nonconvex_terms, Expr[:(x[1]), :(x[6])]) +# @test haskey(alpine.nonconvex_terms, Expr[:(x[2]), :(x[7])]) +# @test haskey(alpine.nonconvex_terms, Expr[:(x[3]), :(x[8])]) +# @test haskey(alpine.nonconvex_terms, Expr[:(x[4]), :(x[9])]) +# @test haskey(alpine.nonconvex_terms, Expr[:(x[5]), :(x[10])]) + +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[6])]][:nonlinear_type] == :BINLIN +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[7])]][:nonlinear_type] == :BINLIN +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[8])]][:nonlinear_type] == :BINLIN +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[9])]][:nonlinear_type] == :BINLIN +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[10])]][:nonlinear_type] == :BINLIN +# end + +# @testset "Operator :: bmpl && binlin && binprod solve test II" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "minlp_solver" => JUNIPER, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "presolve_bt" => false, +# "partition_scaling_factor" => 4, +# "log_level" => 100, +# ) + +# m = bpml_binl(solver = test_solver) + +# # FIXME: Deactivating this until Juniper v0.9.0's numerical issues are fixed. +# # JuMP.optimize!(m) +# # @test isapprox(JuMP.objective_value(m), 22812.76415926; atol=1e-6) +# # alpine = JuMP.backend(m).optimizer.model + +# alpine = _build(m) +# @test haskey(alpine.nonconvex_terms, Expr[:(x[6]), :(x[7])]) +# @test haskey(alpine.nonconvex_terms, Expr[:(x[7]), :(x[8])]) +# @test haskey(alpine.nonconvex_terms, Expr[:(x[8]), :(x[9])]) +# @test haskey(alpine.nonconvex_terms, Expr[:(x[9]), :(x[10])]) +# @test haskey(alpine.nonconvex_terms, Expr[:(x[10]), :(x[6])]) +# @test haskey(alpine.nonconvex_terms, Expr[:(x[1]), :(x[11])]) +# @test haskey(alpine.nonconvex_terms, Expr[:(x[2]), :(x[13])]) +# @test haskey(alpine.nonconvex_terms, Expr[:(x[3]), :(x[15])]) +# @test haskey(alpine.nonconvex_terms, Expr[:(x[4]), :(x[17])]) +# @test haskey(alpine.nonconvex_terms, Expr[:(x[5]), :(x[19])]) + +# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[7])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[7]), :(x[8])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[8]), :(x[9])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[6])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[11])]][:nonlinear_type] == :BINLIN +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[13])]][:nonlinear_type] == :BINLIN +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[15])]][:nonlinear_type] == :BINLIN +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[17])]][:nonlinear_type] == :BINLIN +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[19])]][:nonlinear_type] == :BINLIN +# end + +# @testset "Embedding Test || AMP-CONV || basic solve || examples/nlp1.jl" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => PAVITO, +# # "bilinear_convexhull" => true, +# # "monomial_convexhull" => true, +# "presolve_bt" => false, +# "presolve_bp" => true, +# "convhull_ebd" => true, +# "max_iter" => 1, +# "partition_scaling_factor" => 4, +# "log_level" => 100, +# ) + +# m = nlp1(solver = test_solver) +# JuMP.optimize!(m) +# alp = JuMP.backend(m).optimizer.model + +# @test termination_status(m) == MOI.OTHER_LIMIT +# @test isapprox(objective_value(m), 58.38367169858795; atol = 1e-4) +# @test isapprox(alp.best_bound, 52.9702, atol = 1E-4) +# @test MOI.get(m, Alpine.NumberOfIterations()) == 1 +# end + +# @testset "Embedding IBS Test || AMP-CONV || basic solve || examples/nlp1.jl" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => PAVITO, +# # "bilinear_convexhull" => true, +# # "monomial_convexhull" => true, +# "presolve_bt" => false, +# "presolve_bp" => true, +# "convhull_ebd" => true, +# "convhull_ebd_ibs" => true, +# "partition_scaling_factor" => 8, +# "max_iter" => 1, +# "log_level" => 100, +# ) +# m = nlp1(solver = test_solver) +# JuMP.optimize!(m) +# alp = JuMP.backend(m).optimizer.model + +# @test termination_status(m) == MOI.OTHER_LIMIT +# @test isapprox(objective_value(m), 58.38367169858795; atol = 1e-5) +# @test isapprox(alp.best_bound, 57.012, atol = 1E-4) + +# @test MOI.get(m, Alpine.NumberOfIterations()) == 1 +# end + +# @testset "Embedding IBS Test || AMP-CONV || basic solve || examples/nlp3.jl" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# # "bilinear_convexhull" => true, +# # "monomial_convexhull" => true, +# "presolve_bt" => false, +# "presolve_bp" => false, +# "convhull_ebd" => true, +# "convhull_ebd_ibs" => true, +# "max_iter" => 3, +# ) +# m = nlp3(solver = test_solver) +# JuMP.optimize!(m) +# alp = JuMP.backend(m).optimizer.model + +# @test termination_status(m) == MOI.OTHER_LIMIT +# @test isapprox(objective_value(m), 7049.247897696188; atol = 1e-5) +# @test MOI.get(m, Alpine.NumberOfIterations()) == 3 +# @test isapprox(alp.best_bound, 6893.2067, atol = 1E-4) +# end + +# @testset "Embedding IBS Test || AMP || special problem || ... " begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => PAVITO, +# "disc_abs_width_tol" => 1e-3, +# "partition_scaling_factor" => 8, +# "max_iter" => 6, +# "presolve_bt" => false, +# "presolve_bp" => true, +# "presolve_bt_algo" => 1, +# "presolve_bt_bound_tol" => 1e-1, +# "convhull_ebd" => true, +# "convhull_ebd_ibs" => true, +# "log_level" => 100, +# ) + +# m = circle(solver = test_solver) +# # This is fixed in Alpine - TODO(odow): mixed-integer cycling detected, terminating Pavito +# JuMP.optimize!(m) +# @test isapprox(objective_value(m), 1.41421355; atol = 1e-3) +# end + +# @testset "Embedding LINK Test || AMP-CONV || basic solve || examples/nlp3.jl" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# # "bilinear_convexhull" => true, +# # "monomial_convexhull" => true, +# "presolve_bt" => false, +# "presolve_bp" => false, +# "convhull_ebd" => true, +# "convhull_ebd_link" => true, +# "partition_scaling_factor" => 10, +# "max_iter" => 3, +# "log_level" => 100, +# ) +# m = nlp3(solver = test_solver) +# JuMP.optimize!(m) + +# @test termination_status(m) == MOI.OTHER_LIMIT +# @test isapprox(objective_value(m), 7049.247897696188; atol = 1e-4) +# @test MOI.get(m, Alpine.NumberOfIterations()) == 3 +# end + +# @testset "Algorithm Logic Test || castro4m2 || 1 iteration || Error case" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "max_iter" => 1, +# "presolve_bt" => false, +# "partition_scaling_factor" => 10, +# "log_level" => 100, +# ) + +# m = castro4m2(solver = test_solver) +# JuMP.optimize!(m) +# @test termination_status(m) == MOI.OTHER_LIMIT +# end + +# @testset " Algorithm Logic Test || blend029_gl || 3 iterations || Infeasible Case" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "minlp_solver" => PAVITO, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "presolve_bp" => true, +# "disc_var_pick" => 1, +# "log_level" => 100, +# "max_iter" => 3, +# "partition_scaling_factor" => 10, +# "presolve_bt_width_tol" => 1e-3, +# "presolve_bt" => false, +# ) +# m = blend029_gl(solver = test_solver) +# JuMP.optimize!(m) + +# @test termination_status(m) == MOI.OTHER_LIMIT +# @test MOI.get(m, Alpine.NumberOfIterations()) == 3 +# @test objective_bound(m) <= 14.0074 +# end + +# @testset "Convex Model Solve" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => PAVITO, +# "max_iter" => 1, +# "presolve_bt" => false, +# "log_level" => 100, +# ) +# m = convex_solve(solver = test_solver) +# JuMP.optimize!(m) +# @test termination_status(m) == MOI.OPTIMAL +# end + +# @testset "Uniform partitioning" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "disc_add_partition_method" => "uniform", +# "disc_uniform_rate" => 10, +# "max_iter" => 1, +# "presolve_bt" => false, +# "time_limit" => 100000, +# "log_level" => 100, +# ) +# m = nlp3(solver = test_solver) +# JuMP.optimize!(m) +# @test isapprox(objective_bound(m), 6561.7841; atol = 1e-3) +# end + +# @testset "Algorithm Test with binprod terms" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "minlp_solver" => PAVITO, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# # "bilinear_convexhull" => true, +# # "monomial_convexhull" => true, +# "presolve_bp" => true, +# "presolve_bt" => false, +# "partition_scaling_factor" => 10, +# "log_level" => 100, +# ) +# m = binprod_nlp3(solver = test_solver) +# JuMP.optimize!(m) + +# @test termination_status(m) == MOI.OPTIMAL +# @test isapprox(objective_value(m), 3651.020370626844; atol = 1e-4) +# @test isapprox(objective_bound(m), 3650.786358471944; atol = 1e-4) + +# alpine = JuMP.backend(m).optimizer.model +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4])]][:y_idx] == 19 +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4])]][:id] == 6 +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4])]][:lifted_constr_ref] == +# :(x[19] == x[2] * x[4]) +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[8])]][:y_idx] == 25 +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[8])]][:id] == 12 +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[8])]][:lifted_constr_ref] == +# :(x[25] == x[3] * x[8]) +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[8])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5])]][:y_idx] == 22 +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5])]][:id] == 9 +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5])]][:lifted_constr_ref] == +# :(x[22] == x[3] * x[5]) +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[19])]][:y_idx] == 20 +# @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[19])]][:id] == 7 +# @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[19])]][:lifted_constr_ref] == +# :(x[20] == x[12] * x[19]) +# @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[19])]][:nonlinear_type] == :BINLIN +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[4])]][:y_idx] == 14 +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[4])]][:id] == 1 +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[4])]][:lifted_constr_ref] == +# :(x[14] == x[9] * x[4]) +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[4])]][:nonlinear_type] == :BINLIN +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[6])]][:y_idx] == 17 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[6])]][:id] == 4 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[6])]][:lifted_constr_ref] == +# :(x[17] == x[1] * x[6]) +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[6])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[11]), :(x[5])]][:y_idx] == 16 +# @test alpine.nonconvex_terms[Expr[:(x[11]), :(x[5])]][:id] == 3 +# @test alpine.nonconvex_terms[Expr[:(x[11]), :(x[5])]][:lifted_constr_ref] == +# :(x[16] == x[11] * x[5]) +# @test alpine.nonconvex_terms[Expr[:(x[11]), :(x[5])]][:nonlinear_type] == :BINLIN +# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[11])]][:y_idx] == 30 +# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[11])]][:id] == 17 +# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[11])]][:lifted_constr_ref] == +# :(x[30] == x[10] * x[11]) +# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[11])]][:nonlinear_type] == :BINPROD +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[11])]][:y_idx] == 29 +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[11])]][:id] == 16 +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[11])]][:lifted_constr_ref] == +# :(x[29] == x[9] * x[10] * x[11]) +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[11])]][:nonlinear_type] == +# :BINPROD +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[7])]][:y_idx] == 21 +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[7])]][:id] == 8 +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[7])]][:lifted_constr_ref] == +# :(x[21] == x[2] * x[7]) +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[7])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[13])]][:y_idx] == 32 +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[13])]][:id] == 19 +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[13])]][:lifted_constr_ref] == +# :(x[32] == x[9] * x[13]) +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[13])]][:nonlinear_type] == :BINPROD +# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[6])]][:y_idx] == 15 +# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[6])]][:id] == 2 +# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[6])]][:lifted_constr_ref] == +# :(x[15] == x[10] * x[6]) +# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[6])]][:nonlinear_type] == :BINLIN +# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[12])]][:y_idx] == 33 +# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[12])]][:id] == 20 +# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[12])]][:lifted_constr_ref] == +# :(x[33] == x[10] * x[12]) +# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[12])]][:nonlinear_type] == :BINPROD +# @test alpine.nonconvex_terms[Expr[:(x[27]), :(x[5])]][:y_idx] == 28 +# @test alpine.nonconvex_terms[Expr[:(x[27]), :(x[5])]][:id] == 15 +# @test alpine.nonconvex_terms[Expr[:(x[27]), :(x[5])]][:lifted_constr_ref] == +# :(x[28] == x[27] * x[5]) +# @test alpine.nonconvex_terms[Expr[:(x[27]), :(x[5])]][:nonlinear_type] == :BINLIN +# @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[25])]][:y_idx] == 26 +# @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[25])]][:id] == 13 +# @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[25])]][:lifted_constr_ref] == +# :(x[26] == x[13] * x[25]) +# @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[25])]][:nonlinear_type] == :BINLIN +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[12])]][:y_idx] == 27 +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[12])]][:id] == 14 +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[12])]][:lifted_constr_ref] == +# :(x[27] == x[9] * x[12]) +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[12])]][:nonlinear_type] == :BINPROD +# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[13])]][:y_idx] == 23 +# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[13])]][:id] == 10 +# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[13])]][:lifted_constr_ref] == +# :(x[23] == x[10] * x[13]) +# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[13])]][:nonlinear_type] == :BINPROD +# @test alpine.nonconvex_terms[Expr[:(x[23]), :(x[22])]][:y_idx] == 24 +# @test alpine.nonconvex_terms[Expr[:(x[23]), :(x[22])]][:id] == 11 +# @test alpine.nonconvex_terms[Expr[:(x[23]), :(x[22])]][:lifted_constr_ref] == +# :(x[24] == x[23] * x[22]) +# @test alpine.nonconvex_terms[Expr[:(x[23]), :(x[22])]][:nonlinear_type] == :BINLIN +# @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[13])]][:y_idx] == 31 +# @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[13])]][:id] == 18 +# @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[13])]][:lifted_constr_ref] == +# :(x[31] == x[12] * x[13]) +# @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[13])]][:nonlinear_type] == :BINPROD +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[17])]][:y_idx] == 18 +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[17])]][:id] == 5 +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[17])]][:lifted_constr_ref] == +# :(x[18] == x[9] * x[17]) +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[17])]][:nonlinear_type] == :BINLIN +# @test alpine.bounding_constr_mip[1][:rhs] == 1.0 +# @test alpine.bounding_constr_mip[1][:vars] == Any[:(x[14]), :(x[15])] +# @test alpine.bounding_constr_mip[1][:coefs] == Any[0.0025, 0.0025] +# @test alpine.bounding_constr_mip[1][:sense] == :(<=) +# @test alpine.bounding_constr_mip[1][:cnt] == 2 +# @test alpine.bounding_constr_mip[2][:rhs] == 1.0 +# @test alpine.bounding_constr_mip[2][:vars] == Any[:(x[14]), :(x[5]), :(x[7])] +# @test alpine.bounding_constr_mip[2][:coefs] == Any[-0.0025, 0.0025, 0.0025] +# @test alpine.bounding_constr_mip[2][:sense] == :(<=) +# @test alpine.bounding_constr_mip[2][:cnt] == 3 +# @test alpine.bounding_constr_mip[3][:rhs] == 1.0 +# @test alpine.bounding_constr_mip[3][:vars] == Any[:(x[16]), :(x[8])] +# @test alpine.bounding_constr_mip[3][:coefs] == Any[-0.01, 0.01] +# @test alpine.bounding_constr_mip[3][:sense] == :(<=) +# @test alpine.bounding_constr_mip[3][:cnt] == 2 +# @test alpine.bounding_constr_mip[4][:rhs] == 83333.333 +# @test alpine.bounding_constr_mip[4][:vars] == Any[:(x[1]), :(x[18]), :(x[14])] +# @test alpine.bounding_constr_mip[4][:sense] == :(<=) +# @test alpine.bounding_constr_mip[4][:cnt] == 3 +# @test alpine.bounding_constr_mip[5][:rhs] == 0.0 +# @test alpine.bounding_constr_mip[5][:vars] == +# Any[:(x[20]), :(x[21]), :(x[4]), :(x[5])] +# @test alpine.bounding_constr_mip[5][:coefs] == Any[1.0, -1.0, -1250.0, 1250.0] +# @test alpine.bounding_constr_mip[5][:sense] == :(<=) +# @test alpine.bounding_constr_mip[5][:cnt] == 4 +# @test alpine.bounding_constr_mip[6][:rhs] == -1.25e6 +# @test alpine.bounding_constr_mip[6][:vars] == Any[:(x[24]), :(x[26]), :(x[28])] +# @test alpine.bounding_constr_mip[6][:coefs] == Any[1.0, -1.0, -2500.0] +# @test alpine.bounding_constr_mip[6][:sense] == :(<=) +# @test alpine.bounding_constr_mip[6][:cnt] == 3 +# @test alpine.bounding_constr_mip[7][:rhs] == 0.0 +# @test alpine.bounding_constr_mip[7][:vars] == Any[:(x[29])] +# @test alpine.bounding_constr_mip[7][:coefs] == Any[1.0] +# @test alpine.bounding_constr_mip[7][:sense] == :(<=) +# @test alpine.bounding_constr_mip[7][:cnt] == 1 +# @test alpine.bounding_constr_mip[8][:rhs] == 0.0 +# @test alpine.bounding_constr_mip[8][:vars] == Any[:(x[30]), :(x[31])] +# @test alpine.bounding_constr_mip[8][:coefs] == Any[1.0, -1.0] +# @test alpine.bounding_constr_mip[8][:sense] == :(>=) +# @test alpine.bounding_constr_mip[8][:cnt] == 2 +# @test alpine.bounding_constr_mip[9][:rhs] == 0.0 +# @test alpine.bounding_constr_mip[9][:vars] == Any[:(x[32]), :(x[33])] +# @test alpine.bounding_constr_mip[9][:coefs] == Any[1.0, -1.0] +# @test alpine.bounding_constr_mip[9][:sense] == :(<=) +# @test alpine.bounding_constr_mip[9][:cnt] == 2 +# end + +# @testset "TESTS for closing the optimality gap in OBBT" begin +# test_solver = JuMP.optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => PAVITO, +# "presolve_bt" => true, +# "presolve_bt_max_iter" => 2, +# "log_level" => 1, +# ) +# m = JuMP.Model(test_solver) + +# # From issue #108 +# @variable(m, -2 <= x[1:2] <= 2) +# @variable(m, -10 <= y[1:3] <= 10) +# @NLobjective(m, Min, y[2] + y[1] * y[2] * y[3]) +# @constraint(m, y[1] == x[1]) +# @constraint(m, y[2] == x[2]) +# @NLconstraint(m, y[3] == x[2]^2) + +# JuMP.optimize!(m) +# alp = JuMP.backend(m).optimizer.model +# @test isapprox(JuMP.objective_value(m), -18, atol = 1E-6) +# @test isapprox(value.(m[:x]), [2, -2], atol = 1E-6) +# @test alp.logs[:n_iter] == 0 +# @test MOI.get(m, Alpine.NumberOfIterations()) == 0 +# end + +@testset "Linking constraints for multilinear terms" begin + + # Without linking constraints + test_solver = JuMP.optimizer_with_attributes( Alpine.Optimizer, "nlp_solver" => IPOPT, "mip_solver" => HIGHS, - "bilinear_convexhull" => true, - "monomial_convexhull" => true, "presolve_bt" => false, - "presolve_bp" => false, - "convhull_ebd" => true, - "convhull_ebd_ibs" => true, - "max_iter" => 3, + "apply_partitioning" => true, + "linking_constraints" => false ) - m = nlp3(solver = test_solver) + m = linking_constraints_testing(solver = test_solver) JuMP.optimize!(m) alp = JuMP.backend(m).optimizer.model - - @test termination_status(m) == MOI.OTHER_LIMIT - @test isapprox(objective_value(m), 7049.247897696188; atol = 1e-5) - @test MOI.get(m, Alpine.NumberOfIterations()) == 3 - @test isapprox(alp.best_bound, 6893.2067, atol = 1E-4) -end - -@testset "Embedding IBS Test || AMP || special problem || ... " begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => PAVITO, - "disc_abs_width_tol" => 1e-3, - "disc_ratio" => 8, - "max_iter" => 6, - "presolve_bt" => false, - "presolve_bp" => true, - "presolve_bt_algo" => 1, - "presolve_bt_bound_tol" => 1e-1, - "convhull_ebd" => true, - "convhull_ebd_ibs" => true, - "log_level" => 100, - ) - - m = circle(solver = test_solver) - # This is fixed in Alpine - TODO(odow): mixed-integer cycling detected, terminating Pavito - JuMP.optimize!(m) - @test isapprox(objective_value(m), 1.41421355; atol = 1e-3) -end - -@testset "Embedding LINK Test || AMP-CONV || basic solve || examples/nlp1.jl" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => PAVITO, - "bilinear_convexhull" => true, - "monomial_convexhull" => true, - "presolve_bt" => false, - "presolve_bp" => true, - "convhull_ebd" => true, - "convhull_ebd_link" => true, - "disc_ratio" => 10, - "max_iter" => 2, - ) - m = nlp1(solver = test_solver) - JuMP.optimize!(m) - - @test termination_status(m) == MOI.OTHER_LIMIT - @test isapprox(objective_value(m), 58.38367169858795; atol = 1e-5) + @test isapprox(JuMP.objective_value(m), -0.5294000135, atol = 1E-5) + @test isnothing(alp.linking_constraints_info) @test MOI.get(m, Alpine.NumberOfIterations()) == 2 -end - -@testset "Embedding LINK Test || AMP-CONV || basic solve || examples/nlp3.jl" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "bilinear_convexhull" => true, - "monomial_convexhull" => true, - "presolve_bt" => false, - "presolve_bp" => false, - "convhull_ebd" => true, - "convhull_ebd_link" => true, - "disc_ratio" => 10, - "max_iter" => 3, - "log_level" => 100, - ) - m = nlp3(solver = test_solver) - JuMP.optimize!(m) - - @test termination_status(m) == MOI.OTHER_LIMIT - @test isapprox(objective_value(m), 7049.247897696188; atol = 1e-4) - @test MOI.get(m, Alpine.NumberOfIterations()) == 3 -end - -@testset "Algorithm Logic Test || castro4m2 || 1 iteration || Error case" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "max_iter" => 1, - "presolve_bt" => false, - "disc_ratio" => 10, - "log_level" => 100, - ) - - m = castro4m2(solver = test_solver) - JuMP.optimize!(m) - @test termination_status(m) == MOI.OTHER_LIMIT -end - -@testset " Algorithm Logic Test || blend029_gl || 3 iterations || Infeasible Case" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "minlp_solver" => PAVITO, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "presolve_bp" => true, - "disc_var_pick" => 1, - "log_level" => 100, - "max_iter" => 3, - "disc_ratio" => 10, - "presolve_bt_width_tol" => 1e-3, - "presolve_bt" => false, - ) - m = blend029_gl(solver = test_solver) - JuMP.optimize!(m) - - @test termination_status(m) == MOI.OTHER_LIMIT - @test MOI.get(m, Alpine.NumberOfIterations()) == 3 - @test objective_bound(m) <= 14.0074 -end - -@testset "Convex Model Solve" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => PAVITO, - "max_iter" => 1, - "presolve_bt" => false, - "log_level" => 100, - ) - m = convex_solve(solver = test_solver) - JuMP.optimize!(m) - @test termination_status(m) == MOI.OPTIMAL -end -@testset "Uniform partitioning" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "disc_add_partition_method" => "uniform", - "disc_uniform_rate" => 10, - "max_iter" => 1, - "presolve_bt" => false, - "time_limit" => 100000, - "log_level" => 100, - ) - m = nlp3(solver = test_solver) - JuMP.optimize!(m) - @test isapprox(objective_bound(m), 6561.7841; atol = 1e-3) -end - -@testset "Algorithm Test with binprod terms" begin - test_solver = optimizer_with_attributes( + # With linking constraints + test_solver = JuMP.optimizer_with_attributes( Alpine.Optimizer, - "minlp_solver" => PAVITO, "nlp_solver" => IPOPT, "mip_solver" => HIGHS, - "bilinear_convexhull" => true, - "monomial_convexhull" => true, - "presolve_bp" => true, "presolve_bt" => false, - "disc_ratio" => 10, - "log_level" => 100, + "apply_partitioning" => true, + "linking_constraints" => true ) - m = binprod_nlp3(solver = test_solver) - JuMP.optimize!(m) - - @test termination_status(m) == MOI.OPTIMAL - @test isapprox(objective_value(m), 3651.020370626844; atol = 1e-4) - @test isapprox(objective_bound(m), 3650.786358471944; atol = 1e-4) - - alpine = JuMP.backend(m).optimizer.model - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4])]][:y_idx] == 19 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4])]][:id] == 6 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4])]][:lifted_constr_ref] == - :(x[19] == x[2] * x[4]) - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[8])]][:y_idx] == 25 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[8])]][:id] == 12 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[8])]][:lifted_constr_ref] == - :(x[25] == x[3] * x[8]) - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[8])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5])]][:y_idx] == 22 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5])]][:id] == 9 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5])]][:lifted_constr_ref] == - :(x[22] == x[3] * x[5]) - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[19])]][:y_idx] == 20 - @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[19])]][:id] == 7 - @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[19])]][:lifted_constr_ref] == - :(x[20] == x[12] * x[19]) - @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[19])]][:nonlinear_type] == :BINLIN - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[4])]][:y_idx] == 14 - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[4])]][:id] == 1 - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[4])]][:lifted_constr_ref] == - :(x[14] == x[9] * x[4]) - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[4])]][:nonlinear_type] == :BINLIN - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[6])]][:y_idx] == 17 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[6])]][:id] == 4 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[6])]][:lifted_constr_ref] == - :(x[17] == x[1] * x[6]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[6])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[11]), :(x[5])]][:y_idx] == 16 - @test alpine.nonconvex_terms[Expr[:(x[11]), :(x[5])]][:id] == 3 - @test alpine.nonconvex_terms[Expr[:(x[11]), :(x[5])]][:lifted_constr_ref] == - :(x[16] == x[11] * x[5]) - @test alpine.nonconvex_terms[Expr[:(x[11]), :(x[5])]][:nonlinear_type] == :BINLIN - @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[11])]][:y_idx] == 30 - @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[11])]][:id] == 17 - @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[11])]][:lifted_constr_ref] == - :(x[30] == x[10] * x[11]) - @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[11])]][:nonlinear_type] == :BINPROD - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[11])]][:y_idx] == 29 - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[11])]][:id] == 16 - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[11])]][:lifted_constr_ref] == - :(x[29] == x[9] * x[10] * x[11]) - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[11])]][:nonlinear_type] == - :BINPROD - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[7])]][:y_idx] == 21 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[7])]][:id] == 8 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[7])]][:lifted_constr_ref] == - :(x[21] == x[2] * x[7]) - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[7])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[13])]][:y_idx] == 32 - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[13])]][:id] == 19 - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[13])]][:lifted_constr_ref] == - :(x[32] == x[9] * x[13]) - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[13])]][:nonlinear_type] == :BINPROD - @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[6])]][:y_idx] == 15 - @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[6])]][:id] == 2 - @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[6])]][:lifted_constr_ref] == - :(x[15] == x[10] * x[6]) - @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[6])]][:nonlinear_type] == :BINLIN - @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[12])]][:y_idx] == 33 - @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[12])]][:id] == 20 - @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[12])]][:lifted_constr_ref] == - :(x[33] == x[10] * x[12]) - @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[12])]][:nonlinear_type] == :BINPROD - @test alpine.nonconvex_terms[Expr[:(x[27]), :(x[5])]][:y_idx] == 28 - @test alpine.nonconvex_terms[Expr[:(x[27]), :(x[5])]][:id] == 15 - @test alpine.nonconvex_terms[Expr[:(x[27]), :(x[5])]][:lifted_constr_ref] == - :(x[28] == x[27] * x[5]) - @test alpine.nonconvex_terms[Expr[:(x[27]), :(x[5])]][:nonlinear_type] == :BINLIN - @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[25])]][:y_idx] == 26 - @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[25])]][:id] == 13 - @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[25])]][:lifted_constr_ref] == - :(x[26] == x[13] * x[25]) - @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[25])]][:nonlinear_type] == :BINLIN - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[12])]][:y_idx] == 27 - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[12])]][:id] == 14 - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[12])]][:lifted_constr_ref] == - :(x[27] == x[9] * x[12]) - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[12])]][:nonlinear_type] == :BINPROD - @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[13])]][:y_idx] == 23 - @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[13])]][:id] == 10 - @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[13])]][:lifted_constr_ref] == - :(x[23] == x[10] * x[13]) - @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[13])]][:nonlinear_type] == :BINPROD - @test alpine.nonconvex_terms[Expr[:(x[23]), :(x[22])]][:y_idx] == 24 - @test alpine.nonconvex_terms[Expr[:(x[23]), :(x[22])]][:id] == 11 - @test alpine.nonconvex_terms[Expr[:(x[23]), :(x[22])]][:lifted_constr_ref] == - :(x[24] == x[23] * x[22]) - @test alpine.nonconvex_terms[Expr[:(x[23]), :(x[22])]][:nonlinear_type] == :BINLIN - @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[13])]][:y_idx] == 31 - @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[13])]][:id] == 18 - @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[13])]][:lifted_constr_ref] == - :(x[31] == x[12] * x[13]) - @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[13])]][:nonlinear_type] == :BINPROD - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[17])]][:y_idx] == 18 - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[17])]][:id] == 5 - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[17])]][:lifted_constr_ref] == - :(x[18] == x[9] * x[17]) - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[17])]][:nonlinear_type] == :BINLIN - @test alpine.bounding_constr_mip[1][:rhs] == 1.0 - @test alpine.bounding_constr_mip[1][:vars] == Any[:(x[14]), :(x[15])] - @test alpine.bounding_constr_mip[1][:coefs] == Any[0.0025, 0.0025] - @test alpine.bounding_constr_mip[1][:sense] == :(<=) - @test alpine.bounding_constr_mip[1][:cnt] == 2 - @test alpine.bounding_constr_mip[2][:rhs] == 1.0 - @test alpine.bounding_constr_mip[2][:vars] == Any[:(x[14]), :(x[5]), :(x[7])] - @test alpine.bounding_constr_mip[2][:coefs] == Any[-0.0025, 0.0025, 0.0025] - @test alpine.bounding_constr_mip[2][:sense] == :(<=) - @test alpine.bounding_constr_mip[2][:cnt] == 3 - @test alpine.bounding_constr_mip[3][:rhs] == 1.0 - @test alpine.bounding_constr_mip[3][:vars] == Any[:(x[16]), :(x[8])] - @test alpine.bounding_constr_mip[3][:coefs] == Any[-0.01, 0.01] - @test alpine.bounding_constr_mip[3][:sense] == :(<=) - @test alpine.bounding_constr_mip[3][:cnt] == 2 - @test alpine.bounding_constr_mip[4][:rhs] == 83333.333 - @test alpine.bounding_constr_mip[4][:vars] == Any[:(x[1]), :(x[18]), :(x[14])] - @test alpine.bounding_constr_mip[4][:sense] == :(<=) - @test alpine.bounding_constr_mip[4][:cnt] == 3 - @test alpine.bounding_constr_mip[5][:rhs] == 0.0 - @test alpine.bounding_constr_mip[5][:vars] == - Any[:(x[20]), :(x[21]), :(x[4]), :(x[5])] - @test alpine.bounding_constr_mip[5][:coefs] == Any[1.0, -1.0, -1250.0, 1250.0] - @test alpine.bounding_constr_mip[5][:sense] == :(<=) - @test alpine.bounding_constr_mip[5][:cnt] == 4 - @test alpine.bounding_constr_mip[6][:rhs] == -1.25e6 - @test alpine.bounding_constr_mip[6][:vars] == Any[:(x[24]), :(x[26]), :(x[28])] - @test alpine.bounding_constr_mip[6][:coefs] == Any[1.0, -1.0, -2500.0] - @test alpine.bounding_constr_mip[6][:sense] == :(<=) - @test alpine.bounding_constr_mip[6][:cnt] == 3 - @test alpine.bounding_constr_mip[7][:rhs] == 0.0 - @test alpine.bounding_constr_mip[7][:vars] == Any[:(x[29])] - @test alpine.bounding_constr_mip[7][:coefs] == Any[1.0] - @test alpine.bounding_constr_mip[7][:sense] == :(<=) - @test alpine.bounding_constr_mip[7][:cnt] == 1 - @test alpine.bounding_constr_mip[8][:rhs] == 0.0 - @test alpine.bounding_constr_mip[8][:vars] == Any[:(x[30]), :(x[31])] - @test alpine.bounding_constr_mip[8][:coefs] == Any[1.0, -1.0] - @test alpine.bounding_constr_mip[8][:sense] == :(>=) - @test alpine.bounding_constr_mip[8][:cnt] == 2 - @test alpine.bounding_constr_mip[9][:rhs] == 0.0 - @test alpine.bounding_constr_mip[9][:vars] == Any[:(x[32]), :(x[33])] - @test alpine.bounding_constr_mip[9][:coefs] == Any[1.0, -1.0] - @test alpine.bounding_constr_mip[9][:sense] == :(<=) - @test alpine.bounding_constr_mip[9][:cnt] == 2 -end - -@testset "TESTS for closing the optimality gap in OBBT" begin - test_solver = JuMP.optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => PAVITO, - "presolve_bt" => true, - "presolve_bt_max_iter" => 2, - "log_level" => 1, - ) - m = JuMP.Model(test_solver) - - # From issue #108 - @variable(m, -2 <= x[1:2] <= 2) - @variable(m, -10 <= y[1:3] <= 10) - @NLobjective(m, Min, y[2] + y[1] * y[2] * y[3]) - @constraint(m, y[1] == x[1]) - @constraint(m, y[2] == x[2]) - @NLconstraint(m, y[3] == x[2]^2) - + m = linking_constraints_testing(solver = test_solver) JuMP.optimize!(m) alp = JuMP.backend(m).optimizer.model - @test isapprox(JuMP.objective_value(m), -18, atol = 1E-6) - @test isapprox(value.(m[:x]), [2, -2], atol = 1E-6) - @test alp.logs[:n_iter] == 0 - @test MOI.get(m, Alpine.NumberOfIterations()) == 0 -end + @test isapprox(JuMP.objective_value(m), -0.5294000135, atol = 1E-5) + @test MOI.get(m, Alpine.NumberOfIterations()) == 1 + @test in(Set{Any}([1,2]), alp.linking_constraints_info[[1,2]]) + @test in(Set{Any}([1,2,3]), alp.linking_constraints_info[[1,2]]) + @test in(Set{Any}([1,2,4]), alp.linking_constraints_info[[1,2]]) + @test in(Set{Any}([1,3]), alp.linking_constraints_info[[1,3]]) + @test in(Set{Any}([1,2,3]), alp.linking_constraints_info[[1,3]]) + @test in(Set{Any}([1,3,4]), alp.linking_constraints_info[[1,3]]) + @test in(Set{Any}([1,4]), alp.linking_constraints_info[[1,4]]) + @test in(Set{Any}([1,2,4]), alp.linking_constraints_info[[1,4]]) + @test in(Set{Any}([1,3,4]), alp.linking_constraints_info[[1,4]]) + +end \ No newline at end of file diff --git a/test/test_expression.jl b/test/test_expression.jl index 7db29727..154a9685 100644 --- a/test/test_expression.jl +++ b/test/test_expression.jl @@ -1,3643 +1,3643 @@ -@testset "Expression Parsing || bilinear || Affine || exprs.jl" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "log_level" => 100, - ) - - m = exprstest(solver = test_solver) - - alpine = _build(m) - - ex = alpine.bounding_constr_expr_mip[1] - affdict = Alpine.expr_linear_to_affine(ex) - @test affdict[:coefs] == [-1.0] - @test affdict[:coefs] == alpine.bounding_constr_mip[1][:coefs] - @test affdict[:vars] == [:(x[1])] - @test affdict[:vars] == alpine.bounding_constr_mip[1][:vars] - @test isapprox(affdict[:rhs], 109.0; atol = 1e-3) - @test affdict[:rhs] == alpine.bounding_constr_mip[1][:rhs] - @test affdict[:sense] == :(<=) - @test affdict[:sense] == alpine.bounding_constr_mip[1][:sense] - - ex = alpine.bounding_constr_expr_mip[2] - affdict = Alpine.expr_linear_to_affine(ex) - @test affdict[:coefs] == [3.0, 3.0, 3.0, 3.0] - @test affdict[:coefs] == alpine.bounding_constr_mip[2][:coefs] - @test affdict[:vars] == [:(x[8]), :(x[9]), :(x[10]), :(x[11])] - @test affdict[:vars] == alpine.bounding_constr_mip[2][:vars] - @test isapprox(affdict[:rhs], 111.0; atol = 1e-3) - @test affdict[:rhs] == alpine.bounding_constr_mip[2][:rhs] - @test affdict[:sense] == :(>=) - @test affdict[:sense] == alpine.bounding_constr_mip[2][:sense] - - ex = alpine.bounding_constr_expr_mip[3] - affdict = Alpine.expr_linear_to_affine(ex) - @test affdict[:coefs] == [-1.0, 20.0] - @test affdict[:coefs] == alpine.bounding_constr_mip[3][:coefs] - @test affdict[:vars] == [:(x[12]), :(x[13])] - @test affdict[:vars] == alpine.bounding_constr_mip[3][:vars] - @test isapprox(affdict[:rhs], 222.0; atol = 1e-3) - @test affdict[:rhs] == alpine.bounding_constr_mip[3][:rhs] - @test affdict[:sense] == :(>=) - @test affdict[:sense] == alpine.bounding_constr_mip[3][:sense] - - # 1.0 * x[12] - 115.0 >= 0.0 - ex = alpine.bounding_constr_expr_mip[4] - affdict = Alpine.expr_linear_to_affine(ex) - @test affdict[:coefs] == [-1.0] - @test affdict[:coefs] == alpine.bounding_constr_mip[4][:coefs] - @test affdict[:vars] == [:(x[12])] - @test affdict[:vars] == alpine.bounding_constr_mip[4][:vars] - @test isapprox(affdict[:rhs], 115.0; atol = 1e-3) - @test affdict[:rhs] == alpine.bounding_constr_mip[4][:rhs] - @test affdict[:sense] == :(<=) - @test affdict[:sense] == alpine.bounding_constr_mip[4][:sense] - - # 1.0 * x[12] - 115.0 <= 0.0 - ex = alpine.bounding_constr_expr_mip[5] - affdict = Alpine.expr_linear_to_affine(ex) - @test affdict[:coefs] == [1.0] - @test affdict[:coefs] == alpine.bounding_constr_mip[5][:coefs] - @test affdict[:vars] == [:(x[12])] - @test affdict[:vars] == alpine.bounding_constr_mip[5][:vars] - @test isapprox(affdict[:rhs], 115.0; atol = 1e-3) - @test affdict[:rhs] == alpine.bounding_constr_mip[5][:rhs] - @test affdict[:sense] == :(>=) - @test affdict[:sense] == alpine.bounding_constr_mip[5][:sense] - - # -1.0 * x[12] - 115.0 >= 0.0 - ex = alpine.bounding_constr_expr_mip[6] - affdict = Alpine.expr_linear_to_affine(ex) - @test affdict[:coefs] == [-1.0] - @test affdict[:coefs] == alpine.bounding_constr_mip[6][:coefs] - @test affdict[:vars] == [:(x[12])] - @test affdict[:vars] == alpine.bounding_constr_mip[6][:vars] - @test isapprox(affdict[:rhs], 115.0; atol = 1e-3) - @test affdict[:rhs] == alpine.bounding_constr_mip[6][:rhs] - @test affdict[:sense] == :(<=) - @test affdict[:sense] == alpine.bounding_constr_mip[6][:sense] - - # (x[1] + 1.0 * x[14]) - 555.0 >= 0.0 - ex = alpine.bounding_constr_expr_mip[7] - affdict = Alpine.expr_linear_to_affine(ex) - @test affdict[:coefs] == [1.0, 1.0] - @test affdict[:coefs] == alpine.bounding_constr_mip[7][:coefs] - @test affdict[:vars] == [:(x[1]), :(x[14])] - @test affdict[:vars] == alpine.bounding_constr_mip[7][:vars] - @test isapprox(affdict[:rhs], 555.0; atol = 1e-3) - @test affdict[:rhs] == alpine.bounding_constr_mip[7][:rhs] - @test affdict[:sense] == :(>=) - @test affdict[:sense] == alpine.bounding_constr_mip[7][:sense] - - # ((x[8] - 7.0 * x[9]) + x[10] + x[4]) - 6666.0 <= 0.0 - ex = alpine.bounding_constr_expr_mip[8] - affdict = Alpine.expr_linear_to_affine(ex) - @test affdict[:coefs] == [1.0, -7.0, 1.0, 1.0] - @test affdict[:coefs] == alpine.bounding_constr_mip[8][:coefs] - @test affdict[:vars] == [:(x[8]), :(x[9]), :(x[10]), :(x[4])] - @test affdict[:vars] == alpine.bounding_constr_mip[8][:vars] - @test isapprox(affdict[:rhs], 6666.0; atol = 1e-3) - @test affdict[:rhs] == alpine.bounding_constr_mip[8][:rhs] - @test affdict[:sense] == :(<=) - @test affdict[:sense] == alpine.bounding_constr_mip[8][:sense] - - # ((13.0 * x[1] - x[2]) + 30.0 * x[3] + x[4]) - 77.0 >= 0.0 - ex = alpine.bounding_constr_expr_mip[9] - affdict = Alpine.expr_linear_to_affine(ex) - @test affdict[:coefs] == [13.0, -1.0, 30.0, 1.0] - @test affdict[:coefs] == alpine.bounding_constr_mip[9][:coefs] - @test affdict[:vars] == [:(x[1]), :(x[2]), :(x[3]), :(x[4])] - @test affdict[:vars] == alpine.bounding_constr_mip[9][:vars] - @test isapprox(affdict[:rhs], 77.0; atol = 1e-3) - @test affdict[:rhs] == alpine.bounding_constr_mip[9][:rhs] - @test affdict[:sense] == :(>=) - @test affdict[:sense] == alpine.bounding_constr_mip[9][:sense] -end - -@testset "Expression Parsing || bilinear || Affine || nlp1.jl" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "log_level" => 100, - ) - m = nlp1(solver = test_solver) - - alpine = _build(m) - - ex = alpine.bounding_constr_expr_mip[1] - affdict = Alpine.expr_linear_to_affine(ex) - @test affdict[:coefs] == [1.0] - @test affdict[:coefs] == alpine.bounding_constr_mip[1][:coefs] - @test affdict[:vars] == [:(x[5])] - @test affdict[:vars] == alpine.bounding_constr_mip[1][:vars] - @test isapprox(affdict[:rhs], 8.0; atol = 1e-3) - @test affdict[:rhs] == alpine.bounding_constr_mip[1][:rhs] - @test affdict[:sense] == :(>=) - @test affdict[:sense] == alpine.bounding_constr_mip[1][:sense] -end - -@testset "Expression Parsing || bilinear || Affine || nlp3.jl" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "log_level" => 100, - ) - - m = nlp3(solver = test_solver) - - alpine = _build(m) - - ex = alpine.bounding_constr_expr_mip[1] - affdict = Alpine.expr_linear_to_affine(ex) - @test affdict[:coefs] == [0.0025, 0.0025] - @test affdict[:coefs] == alpine.bounding_constr_mip[1][:coefs] - @test affdict[:vars] == [:(x[4]), :(x[6])] - @test affdict[:vars] == alpine.bounding_constr_mip[1][:vars] - @test isapprox(affdict[:rhs], 1.0; atol = 1e-3) - @test affdict[:rhs] == alpine.bounding_constr_mip[1][:rhs] - @test affdict[:sense] == :(<=) - @test affdict[:sense] == alpine.bounding_constr_mip[1][:sense] - - ex = alpine.bounding_constr_expr_mip[2] - affdict = Alpine.expr_linear_to_affine(ex) - @test affdict[:coefs] == [-0.0025, 0.0025, 0.0025] - @test affdict[:coefs] == alpine.bounding_constr_mip[2][:coefs] - @test affdict[:vars] == [:(x[4]), :(x[5]), :(x[7])] - @test affdict[:vars] == alpine.bounding_constr_mip[2][:vars] - @test isapprox(affdict[:rhs], 1.0; atol = 1e-3) - @test affdict[:rhs] == alpine.bounding_constr_mip[2][:rhs] - @test affdict[:sense] == :(<=) - @test affdict[:sense] == alpine.bounding_constr_mip[2][:sense] - - ex = alpine.bounding_constr_expr_mip[3] - affdict = Alpine.expr_linear_to_affine(ex) - @test affdict[:coefs] == [-0.01, 0.01] - @test affdict[:coefs] == alpine.bounding_constr_mip[3][:coefs] - @test affdict[:vars] == [:(x[5]), :(x[8])] - @test affdict[:vars] == alpine.bounding_constr_mip[3][:vars] - @test isapprox(affdict[:rhs], 1.0; atol = 1e-3) - @test affdict[:rhs] == alpine.bounding_constr_mip[3][:rhs] - @test affdict[:sense] == :(<=) - @test affdict[:sense] == alpine.bounding_constr_mip[3][:sense] - - ex = alpine.bounding_constr_expr_mip[4] - affdict = Alpine.expr_linear_to_affine(ex) - @test (affdict[:coefs] .== [100.0, -1.0, 833.33252]) == [true, true, true] - @test affdict[:coefs] == alpine.bounding_constr_mip[4][:coefs] - @test affdict[:vars] == [:(x[1]), :(x[9]), :(x[4])] - @test affdict[:vars] == alpine.bounding_constr_mip[4][:vars] - @test isapprox(affdict[:rhs], 83333.333; atol = 1e-3) - @test affdict[:rhs] == alpine.bounding_constr_mip[4][:rhs] - @test affdict[:sense] == :(<=) - @test affdict[:sense] == alpine.bounding_constr_mip[4][:sense] - - ex = alpine.bounding_constr_expr_mip[5] - affdict = Alpine.expr_linear_to_affine(ex) - @test affdict[:coefs] == [1.0, -1.0, -1250.0, 1250.0] - @test affdict[:coefs] == alpine.bounding_constr_mip[5][:coefs] - @test affdict[:vars] == [:(x[10]), :(x[11]), :(x[4]), :(x[5])] - @test affdict[:vars] == alpine.bounding_constr_mip[5][:vars] - @test isapprox(affdict[:rhs], 0.0; atol = 1e-3) - @test affdict[:rhs] == alpine.bounding_constr_mip[5][:rhs] - @test affdict[:sense] == :(<=) - @test affdict[:sense] == alpine.bounding_constr_mip[5][:sense] - - ex = alpine.bounding_constr_expr_mip[6] - affdict = Alpine.expr_linear_to_affine(ex) - @test affdict[:coefs] == [1.0, -1.0, -2500.0] - @test affdict[:coefs] == alpine.bounding_constr_mip[6][:coefs] - @test affdict[:vars] == [:(x[12]), :(x[13]), :(x[5])] - @test affdict[:vars] == alpine.bounding_constr_mip[6][:vars] - @test isapprox(affdict[:rhs], -1.25e6; atol = 1e-3) - @test affdict[:rhs] == alpine.bounding_constr_mip[6][:rhs] - @test affdict[:sense] == :(<=) - @test affdict[:sense] == alpine.bounding_constr_mip[6][:sense] -end - -@testset "Expression Parsing || bilinear || Simple || bi1.jl " begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "log_level" => 100, - ) - - m = operator_c(solver = test_solver) - - alpine = _build(m) # Setup internal model - - @test length(keys(alpine.nonconvex_terms)) == 8 - @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 1), Expr(:ref, :x, 1)]) - @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 2), Expr(:ref, :x, 2)]) - @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 3), Expr(:ref, :x, 3)]) - @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 4), Expr(:ref, :x, 4)]) - @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 2), Expr(:ref, :x, 3)]) - @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 3), Expr(:ref, :x, 4)]) - - # TODO setup detailed check on this problem -end -@testset "Expression Parsing || bilinear || Complex || blend029.jl " begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "minlp_solver" => JUNIPER, - "mip_solver" => HIGHS, - "log_level" => 100, - ) - - m = blend029(solver = test_solver) - - alpine = _build(m) # Setup internal model - - @test length(keys(alpine.nonconvex_terms)) == 28 - @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 37), Expr(:ref, :x, 55)]) - @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 38), Expr(:ref, :x, 56)]) - @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 37), Expr(:ref, :x, 26)]) - @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 43), Expr(:ref, :x, 26)]) - @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 47), Expr(:ref, :x, 59)]) - @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 48), Expr(:ref, :x, 60)]) - @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 47), Expr(:ref, :x, 36)]) - - @test alpine.bounding_constr_mip[1][:rhs] == 1.0 - @test alpine.bounding_constr_mip[1][:vars] == - Any[:(x[1]), :(x[4]), :(x[7]), :(x[10]), :(x[49])] - @test alpine.bounding_constr_mip[1][:sense] == :(==) - @test alpine.bounding_constr_mip[1][:coefs] == Any[1.0, 1.0, 1.0, 1.0, 1.0] - @test alpine.bounding_constr_mip[1][:cnt] == 5 - - @test alpine.bounding_constr_mip[4][:rhs] == 0.1 - @test alpine.bounding_constr_mip[4][:vars] == - Any[:(x[4]), :(x[16]), :(x[25]), :(x[34]), :(x[58])] - @test alpine.bounding_constr_mip[4][:sense] == :(==) - @test alpine.bounding_constr_mip[4][:coefs] == Any[-1.0, -1.0, -1.0, 1.0, 1.0] - @test alpine.bounding_constr_mip[4][:cnt] == 5 - - @test alpine.bounding_constr_mip[17][:rhs] == -0.14 - @test alpine.bounding_constr_mip[17][:vars] == - Any[:(x[11]), :(x[23]), :(x[32]), :(x[64]), :(x[65])] - @test alpine.bounding_constr_mip[17][:sense] == :(==) - @test alpine.bounding_constr_mip[17][:coefs] == Any[-1.0, -1.0, -1.0, -1.0, 1.0] - @test alpine.bounding_constr_mip[17][:cnt] == 5 - - @test alpine.bounding_constr_mip[31][:rhs] == 0.0 - @test alpine.bounding_constr_mip[31][:vars] == Any[:(x[13])] - @test alpine.bounding_constr_mip[31][:sense] == :(>=) - @test alpine.bounding_constr_mip[31][:coefs] == Any[1.0] - @test alpine.bounding_constr_mip[31][:cnt] == 1 - - @test alpine.bounding_constr_mip[145][:rhs] == 1.0 - @test alpine.bounding_constr_mip[145][:vars] == Any[:(x[73])] - @test alpine.bounding_constr_mip[145][:sense] == :(<=) - @test alpine.bounding_constr_mip[145][:coefs] == Any[1.0] - @test alpine.bounding_constr_mip[145][:cnt] == 1 - - @test alpine.bounding_constr_mip[67][:rhs] == -1.0 - @test alpine.bounding_constr_mip[67][:vars] == Any[:(x[73])] - @test alpine.bounding_constr_mip[67][:sense] == :(>=) - @test alpine.bounding_constr_mip[67][:coefs] == Any[-1.0] - @test alpine.bounding_constr_mip[67][:cnt] == 1 - - @test alpine.bounding_constr_mip[187][:rhs] == 1.0 - @test alpine.bounding_constr_mip[187][:vars] == Any[:(x[79]), :(x[94])] - @test alpine.bounding_constr_mip[187][:sense] == :(<=) - @test alpine.bounding_constr_mip[187][:coefs] == Any[1.0, 1.0] - @test alpine.bounding_constr_mip[187][:cnt] == 2 - - @test alpine.bounding_constr_mip[202][:rhs] == 0.04 - @test alpine.bounding_constr_mip[202][:vars] == - Any[:(x[103]), :(x[1]), :(x[13]), :(x[25]), :(x[28]), :(x[31])] - @test alpine.bounding_constr_mip[202][:sense] == :(==) - @test alpine.bounding_constr_mip[202][:coefs] == Any[1.0, -0.6, -0.2, 0.2, 0.2, 0.2] - @test alpine.bounding_constr_mip[202][:cnt] == 6 - - @test alpine.nonconvex_terms[[:(x[37]), :(x[55])]][:id] == 1 - @test alpine.nonconvex_terms[[:(x[37]), :(x[55])]][:lifted_var_ref] == :(x[103]) - @test alpine.nonconvex_terms[[:(x[37]), :(x[55])]][:convexified] == false - @test alpine.nonconvex_terms[[:(x[37]), :(x[55])]][:nonlinear_type] == :BILINEAR - - @test alpine.bounding_constr_mip[206][:rhs] == 0.0 - @test alpine.bounding_constr_mip[206][:vars] == - Any[:(x[107]), :(x[103]), :(x[108]), :(x[109]), :(x[110]), :(x[2]), :(x[14])] - @test alpine.bounding_constr_mip[206][:sense] == :(==) - @test alpine.bounding_constr_mip[206][:coefs] == - Any[1.0, -1.0, 1.0, 1.0, 1.0, -0.6, -0.2] - @test alpine.bounding_constr_mip[206][:cnt] == 7 - - @test alpine.nonconvex_terms[[:(x[38]), :(x[56])]][:id] == 5 - @test alpine.nonconvex_terms[[:(x[38]), :(x[56])]][:lifted_var_ref] == :(x[107]) - @test alpine.nonconvex_terms[[:(x[38]), :(x[56])]][:convexified] == false - @test alpine.nonconvex_terms[[:(x[38]), :(x[56])]][:nonlinear_type] == :BILINEAR - - @test alpine.nonconvex_terms[[:(x[37]), :(x[26])]][:id] == 6 - @test alpine.nonconvex_terms[[:(x[37]), :(x[26])]][:lifted_var_ref] == :(x[108]) - @test alpine.nonconvex_terms[[:(x[37]), :(x[26])]][:convexified] == false - @test alpine.nonconvex_terms[[:(x[37]), :(x[26])]][:nonlinear_type] == :BILINEAR - - @test alpine.nonconvex_terms[[:(x[37]), :(x[32])]][:id] == 8 - @test alpine.nonconvex_terms[[:(x[37]), :(x[32])]][:lifted_var_ref] == :(x[110]) - @test alpine.nonconvex_terms[[:(x[37]), :(x[32])]][:convexified] == false - @test alpine.nonconvex_terms[[:(x[37]), :(x[32])]][:nonlinear_type] == :BILINEAR - - @test alpine.bounding_constr_mip[213][:rhs] == 0.0 - @test alpine.bounding_constr_mip[213][:vars] == - Any[:(x[129]), :(x[127]), :(x[124]), :(x[130]), :(x[6]), :(x[18])] - @test alpine.bounding_constr_mip[213][:sense] == :(==) - @test alpine.bounding_constr_mip[213][:coefs] == Any[1.0, -1.0, -1.0, 1.0, -0.4, -0.4] - @test alpine.bounding_constr_mip[213][:cnt] == 6 - - @test alpine.nonconvex_terms[[:(x[48]), :(x[60])]][:id] == 27 - @test alpine.nonconvex_terms[[:(x[48]), :(x[60])]][:lifted_var_ref] == :(x[129]) - @test alpine.nonconvex_terms[[:(x[48]), :(x[60])]][:convexified] == false - @test alpine.nonconvex_terms[[:(x[48]), :(x[60])]][:nonlinear_type] == :BILINEAR - - @test alpine.nonconvex_terms[[:(x[47]), :(x[59])]][:id] == 25 - @test alpine.nonconvex_terms[[:(x[47]), :(x[59])]][:lifted_var_ref] == :(x[127]) - @test alpine.nonconvex_terms[[:(x[47]), :(x[59])]][:convexified] == false - @test alpine.nonconvex_terms[[:(x[47]), :(x[59])]][:nonlinear_type] == :BILINEAR - - @test alpine.nonconvex_terms[[:(x[47]), :(x[36])]][:id] == 28 - @test alpine.nonconvex_terms[[:(x[47]), :(x[36])]][:lifted_var_ref] == :(x[130]) - @test alpine.nonconvex_terms[[:(x[47]), :(x[36])]][:convexified] == false - @test alpine.nonconvex_terms[[:(x[47]), :(x[36])]][:nonlinear_type] == :BILINEAR -end - -@testset "Expression Parsing || multilinear || Simple || multi.jl " begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "log_level" => 100, - ) - - m = multi3(solver = test_solver, exprmode = 1) - - alpine = _build(m) # Setup internal model - - @test length(keys(alpine.nonconvex_terms)) == 1 - @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3])]][:id] == 1 - @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3])]][:lifted_var_ref] == :(x[4]) - @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3])]][:nonlinear_type] == - :MULTILINEAR - - @test alpine.bounding_obj_mip[:rhs] == 0 - @test alpine.bounding_obj_mip[:vars] == Expr[:(x[4])] - @test alpine.bounding_obj_mip[:coefs] == [1.0] - @test alpine.bounding_obj_mip[:cnt] == 1 - @test alpine.bounding_obj_mip[:sense] === nothing - - @test alpine.bounding_constr_mip[1][:rhs] == 3.0 - @test alpine.bounding_constr_mip[1][:vars] == Any[:(x[1]), :(x[2]), :(x[3])] - @test alpine.bounding_constr_mip[1][:sense] == :(<=) - @test alpine.bounding_constr_mip[1][:coefs] == Any[1.0, 1.0, 1.0] - @test alpine.bounding_constr_mip[1][:cnt] == 3 - - m = multi3(solver = test_solver, exprmode = 2) - - alpine = _build(m) - - @test length(keys(alpine.nonconvex_terms)) == 2 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:id] == 1 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:lifted_var_ref] == - :(x[4]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[[Expr(:ref, :x, 4), Expr(:ref, :x, 3)]][:id] == 2 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 4), Expr(:ref, :x, 3)]][:lifted_var_ref] == - :(x[5]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 4), Expr(:ref, :x, 3)]][:nonlinear_type] == - :BILINEAR - - @test alpine.bounding_obj_mip[:rhs] == 0 - @test alpine.bounding_obj_mip[:vars] == Expr[:(x[5])] - @test alpine.bounding_obj_mip[:coefs] == [1.0] - @test alpine.bounding_obj_mip[:cnt] == 1 - @test alpine.bounding_obj_mip[:sense] === nothing - - m = multi3(solver = test_solver, exprmode = 3) - - alpine = _build(m) - - @test length(keys(alpine.nonconvex_terms)) == 2 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:id] == 1 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:lifted_var_ref] == - :(x[4]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 4)]][:id] == 2 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 4)]][:lifted_var_ref] == - :(x[5]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 4)]][:nonlinear_type] == - :BILINEAR - - @test alpine.bounding_obj_mip[:rhs] == 0 - @test alpine.bounding_obj_mip[:vars] == Expr[:(x[5])] - @test alpine.bounding_obj_mip[:coefs] == [1.0] - @test alpine.bounding_obj_mip[:cnt] == 1 - @test alpine.bounding_obj_mip[:sense] === nothing - - m = multi4(solver = test_solver, exprmode = 1) - - alpine = _build(m) - - @test length(keys(alpine.nonconvex_terms)) == 1 - - @test alpine.bounding_obj_mip[:rhs] == 0 - @test alpine.bounding_obj_mip[:vars] == Expr[:(x[5])] - @test alpine.bounding_obj_mip[:coefs] == [1.0] - @test alpine.bounding_obj_mip[:cnt] == 1 - @test alpine.bounding_obj_mip[:sense] === nothing - - @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:id] == 1 - @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:lifted_var_ref] == - :(x[5]) - @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:nonlinear_type] == - :MULTILINEAR - - @test alpine.bounding_constr_mip[1][:rhs] == 4.0 - @test alpine.bounding_constr_mip[1][:vars] == Any[:(x[1]), :(x[2]), :(x[3]), :(x[4])] - @test alpine.bounding_constr_mip[1][:sense] == :(<=) - @test alpine.bounding_constr_mip[1][:coefs] == Any[1.0, 1.0, 1.0, 1.0] - @test alpine.bounding_constr_mip[1][:cnt] == 4 - - m = multi4(solver = test_solver, exprmode = 2) - - alpine = _build(m) - - @test length(keys(alpine.nonconvex_terms)) == 3 - - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:id] == 1 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:lifted_var_ref] == - :(x[5]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:id] == 2 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:lifted_var_ref] == - :(x[6]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[[Expr(:ref, :x, 5), Expr(:ref, :x, 6)]][:id] == 3 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 5), Expr(:ref, :x, 6)]][:lifted_var_ref] == - :(x[7]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 5), Expr(:ref, :x, 6)]][:nonlinear_type] == - :BILINEAR - - @test alpine.bounding_obj_mip[:rhs] == 0 - @test alpine.bounding_obj_mip[:vars] == Expr[:(x[7])] - @test alpine.bounding_obj_mip[:coefs] == [1.0] - @test alpine.bounding_obj_mip[:cnt] == 1 - @test alpine.bounding_obj_mip[:sense] === nothing - - m = multi4(solver = test_solver, exprmode = 3) - - alpine = _build(m) - - @test length(keys(alpine.nonconvex_terms)) == 2 - - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:id] == 1 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:lifted_var_ref] == - :(x[5]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[[:(x[5]), :(x[3]), :(x[4])]][:id] == 2 - @test alpine.nonconvex_terms[[:(x[5]), :(x[3]), :(x[4])]][:lifted_var_ref] == :(x[6]) - @test alpine.nonconvex_terms[[:(x[5]), :(x[3]), :(x[4])]][:nonlinear_type] == - :MULTILINEAR - - @test alpine.bounding_obj_mip[:rhs] == 0 - @test alpine.bounding_obj_mip[:vars] == Expr[:(x[6])] - @test alpine.bounding_obj_mip[:coefs] == [1.0] - @test alpine.bounding_obj_mip[:cnt] == 1 - @test alpine.bounding_obj_mip[:sense] === nothing - - m = multi4(solver = test_solver, exprmode = 4) - - alpine = _build(m) - - @test length(keys(alpine.nonconvex_terms)) == 2 - - @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:id] == 1 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:lifted_var_ref] == - :(x[5]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[5])]][:id] == 2 - @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[5])]][:lifted_var_ref] == :(x[6]) - @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[5])]][:nonlinear_type] == - :MULTILINEAR - - @test alpine.bounding_obj_mip[:rhs] == 0 - @test alpine.bounding_obj_mip[:vars] == Expr[:(x[6])] - @test alpine.bounding_obj_mip[:coefs] == [1.0] - @test alpine.bounding_obj_mip[:cnt] == 1 - @test alpine.bounding_obj_mip[:sense] === nothing - - @test alpine.bounding_obj_mip[:rhs] == 0 - @test alpine.bounding_obj_mip[:vars] == Expr[:(x[6])] - @test alpine.bounding_obj_mip[:coefs] == [1.0] - @test alpine.bounding_obj_mip[:cnt] == 1 - @test alpine.bounding_obj_mip[:sense] === nothing - - m = multi4(solver = test_solver, exprmode = 5) - - alpine = _build(m) - - @test length(keys(alpine.nonconvex_terms)) == 3 - - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:id] == 1 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:lifted_var_ref] == - :(x[5]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 5)]][:id] == 2 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 5)]][:lifted_var_ref] == - :(x[6]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 5)]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[[Expr(:ref, :x, 6), Expr(:ref, :x, 4)]][:id] == 3 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 6), Expr(:ref, :x, 4)]][:lifted_var_ref] == - :(x[7]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 6), Expr(:ref, :x, 4)]][:nonlinear_type] == - :BILINEAR - - @test alpine.bounding_obj_mip[:rhs] == 0 - @test alpine.bounding_obj_mip[:vars] == Expr[:(x[7])] - @test alpine.bounding_obj_mip[:coefs] == [1.0] - @test alpine.bounding_obj_mip[:cnt] == 1 - @test alpine.bounding_obj_mip[:sense] === nothing - - @test alpine.bounding_obj_mip[:rhs] == 0 - @test alpine.bounding_obj_mip[:vars] == Expr[:(x[7])] - @test alpine.bounding_obj_mip[:coefs] == [1.0] - @test alpine.bounding_obj_mip[:cnt] == 1 - @test alpine.bounding_obj_mip[:sense] === nothing - - m = multi4(solver = test_solver, exprmode = 6) - - alpine = _build(m) - - @test length(keys(alpine.nonconvex_terms)) == 2 - - @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3])]][:id] == 1 - @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3])]][:lifted_var_ref] == :(x[5]) - @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[[Expr(:ref, :x, 5), Expr(:ref, :x, 4)]][:id] == 2 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 5), Expr(:ref, :x, 4)]][:lifted_var_ref] == - :(x[6]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 5), Expr(:ref, :x, 4)]][:nonlinear_type] == - :BILINEAR - - @test alpine.bounding_obj_mip[:rhs] == 0 - @test alpine.bounding_obj_mip[:vars] == Expr[:(x[6])] - @test alpine.bounding_obj_mip[:coefs] == [1.0] - @test alpine.bounding_obj_mip[:cnt] == 1 - @test alpine.bounding_obj_mip[:sense] === nothing - - m = multi4(solver = test_solver, exprmode = 7) - - alpine = _build(m) - - @test length(keys(alpine.nonconvex_terms)) == 3 - - @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:id] == 1 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:lifted_var_ref] == - :(x[5]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 5)]][:id] == 2 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 5)]][:lifted_var_ref] == - :(x[6]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 5)]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 6)]][:id] == 3 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 6)]][:lifted_var_ref] == - :(x[7]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 6)]][:nonlinear_type] == - :BILINEAR - - @test alpine.bounding_obj_mip[:rhs] == 0 - @test alpine.bounding_obj_mip[:vars] == Expr[:(x[7])] - @test alpine.bounding_obj_mip[:coefs] == [1.0] - @test alpine.bounding_obj_mip[:cnt] == 1 - @test alpine.bounding_obj_mip[:sense] === nothing - - m = multi4(solver = test_solver, exprmode = 8) - - alpine = _build(m) - - @test length(keys(alpine.nonconvex_terms)) == 2 - - @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:id] == 1 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:lifted_var_ref] == - :(x[5]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[[:(x[1]), :(x[5]), :(x[4])]][:id] == 2 - @test alpine.nonconvex_terms[[:(x[1]), :(x[5]), :(x[4])]][:lifted_var_ref] == :(x[6]) - @test alpine.nonconvex_terms[[:(x[1]), :(x[5]), :(x[4])]][:nonlinear_type] == - :MULTILINEAR - - @test alpine.bounding_obj_mip[:rhs] == 0 - @test alpine.bounding_obj_mip[:vars] == Expr[:(x[6])] - @test alpine.bounding_obj_mip[:coefs] == [1.0] - @test alpine.bounding_obj_mip[:cnt] == 1 - @test alpine.bounding_obj_mip[:sense] === nothing - - m = multi4(solver = test_solver, exprmode = 9) - - alpine = _build(m) - - @test length(keys(alpine.nonconvex_terms)) == 2 - - @test alpine.nonconvex_terms[[:(x[2]), :(x[3]), :(x[4])]][:id] == 1 - @test alpine.nonconvex_terms[[:(x[2]), :(x[3]), :(x[4])]][:lifted_var_ref] == :(x[5]) - @test alpine.nonconvex_terms[[:(x[2]), :(x[3]), :(x[4])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 5)]][:id] == 2 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 5)]][:lifted_var_ref] == - :(x[6]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 5)]][:nonlinear_type] == - :BILINEAR - - @test alpine.bounding_obj_mip[:rhs] == 0 - @test alpine.bounding_obj_mip[:vars] == Expr[:(x[6])] - @test alpine.bounding_obj_mip[:coefs] == [1.0] - @test alpine.bounding_obj_mip[:cnt] == 1 - @test alpine.bounding_obj_mip[:sense] === nothing - - m = multi4(solver = test_solver, exprmode = 10) - - alpine = _build(m) - @test length(keys(alpine.nonconvex_terms)) == 3 - - @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:id] == 1 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:lifted_var_ref] == - :(x[5]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[[Expr(:ref, :x, 4), Expr(:ref, :x, 5)]][:id] == 2 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 4), Expr(:ref, :x, 5)]][:lifted_var_ref] == - :(x[6]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 4), Expr(:ref, :x, 5)]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 6)]][:id] == 3 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 6)]][:lifted_var_ref] == - :(x[7]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 6)]][:nonlinear_type] == - :BILINEAR - - @test alpine.bounding_obj_mip[:rhs] == 0 - @test alpine.bounding_obj_mip[:vars] == Expr[:(x[7])] - @test alpine.bounding_obj_mip[:coefs] == [1.0] - @test alpine.bounding_obj_mip[:cnt] == 1 - @test alpine.bounding_obj_mip[:sense] === nothing - - m = multi4(solver = test_solver, exprmode = 11) - - alpine = _build(m) - - @test length(keys(alpine.nonconvex_terms)) == 3 - - @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:id] == 1 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:lifted_var_ref] == - :(x[5]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 5)]][:id] == 2 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 5)]][:lifted_var_ref] == - :(x[6]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 5)]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[[Expr(:ref, :x, 6), Expr(:ref, :x, 4)]][:id] == 3 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 6), Expr(:ref, :x, 4)]][:lifted_var_ref] == - :(x[7]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 6), Expr(:ref, :x, 4)]][:nonlinear_type] == - :BILINEAR - - @test alpine.bounding_obj_mip[:rhs] == 0 - @test alpine.bounding_obj_mip[:vars] == Expr[:(x[7])] - @test alpine.bounding_obj_mip[:coefs] == [1.0] - @test alpine.bounding_obj_mip[:cnt] == 1 - @test alpine.bounding_obj_mip[:sense] === nothing -end - -@testset "Expression Parsing || bilinear || Complex-div || div.jl" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "log_level" => 100, - ) - - m = div(solver = test_solver) - - alpine = _build(m) # Setup internal model - - @test length(keys(alpine.nonconvex_terms)) == 3 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 1)]][:id] == 1 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 1)]][:lifted_var_ref] == - :(x[3]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 1)]][:nonlinear_type] == - :MONOMIAL - - @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 2)]][:id] == 2 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 2)]][:lifted_var_ref] == - :(x[4]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 2)]][:nonlinear_type] == - :MONOMIAL - - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:id] == 3 - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:lifted_var_ref] == - :(x[5]) - @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:nonlinear_type] == - :BILINEAR - - aff_mip = alpine.bounding_constr_mip - - @test aff_mip[1][:rhs] == 0.0 - @test aff_mip[1][:vars] == Any[:(x[1])] - @test aff_mip[1][:sense] == :(>=) - @test round(aff_mip[1][:coefs][1]; digits = 1) == -3.0 - @test aff_mip[1][:cnt] == 1 - - @test aff_mip[2][:rhs] == 0.0 - @test aff_mip[2][:vars] == Any[:(x[2])] - @test aff_mip[2][:sense] == :(>=) - @test aff_mip[2][:coefs] == Any[0.25] - @test aff_mip[2][:cnt] == 1 - - @test aff_mip[3][:rhs] == 0.0 - @test aff_mip[3][:vars] == Any[:(x[2])] - @test aff_mip[3][:sense] == :(>=) - @test aff_mip[3][:coefs] == Any[5.0] - @test aff_mip[3][:cnt] == 1 - - @test aff_mip[4][:rhs] == 0.0 - @test aff_mip[4][:vars] == Any[:(x[2])] - @test aff_mip[4][:sense] == :(>=) - @test aff_mip[4][:coefs] == Any[-120.0] - @test aff_mip[4][:cnt] == 1 - - @test aff_mip[5][:rhs] == 0.0 - @test aff_mip[5][:vars] == Any[:(x[2])] - @test aff_mip[5][:sense] == :(>=) - @test aff_mip[5][:coefs] == Any[72000.0] - @test aff_mip[5][:cnt] == 1 - - @test aff_mip[6][:rhs] == 0.0 - @test aff_mip[6][:vars] == Any[:(x[1])] - @test aff_mip[6][:sense] == :(>=) - @test aff_mip[6][:coefs] == Any[72000.0] - @test aff_mip[6][:cnt] == 1 - - @test aff_mip[7][:rhs] == 8.0 - @test aff_mip[7][:vars] == Any[:(x[5])] - @test aff_mip[7][:sense] == :(>=) - @test aff_mip[7][:coefs] == Any[0.6] - @test aff_mip[7][:cnt] == 1 - - @test aff_mip[8][:rhs] == 0.0 - @test aff_mip[8][:vars] == Any[:(x[2]), :(x[5])] - @test aff_mip[8][:sense] == :(>=) - @test aff_mip[8][:coefs] == Any[5.6, -72000.0] - @test aff_mip[8][:cnt] == 2 - - @test aff_mip[9][:rhs] == 0.0 - @test aff_mip[9][:vars] == Any[:(x[2]), :(x[5])] - @test aff_mip[9][:sense] == :(>=) - @test aff_mip[9][:coefs] == Any[5.6, -36000.0] - @test aff_mip[9][:cnt] == 2 - - @test aff_mip[10][:rhs] == 0.0 - @test aff_mip[10][:vars] == Any[:(x[2]), :(x[5]), :(x[2])] - @test aff_mip[10][:sense] == :(>=) - @test aff_mip[10][:coefs] == Any[5.6, -300.0, -1.75] - @test aff_mip[10][:cnt] == 3 - - @test aff_mip[11][:rhs] == 0.0 - @test aff_mip[11][:vars] == Any[:(x[2]), :(x[1]), :(x[5])] - @test aff_mip[11][:sense] == :(>=) - @test aff_mip[11][:coefs] == Any[5.6, -0.5, 0.5] - @test aff_mip[11][:cnt] == 3 -end - -@testset "Expression Parsing || part1 " begin - m = Model( - optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "log_level" => 100, - ), - ) - @variable(m, x[1:4] >= 0) - @NLconstraint(m, x[1]^2 >= 1) # Basic monomial x[5]=x[1]^2 - @NLconstraint(m, x[1] * x[2] <= 1) # x[6] <= 1 : x[6] = x[1]*x[2] - @NLconstraint(m, x[1]^2 * x[2]^2 <= 1) # x[5] + x[7] <= 1 : x[7] = x[2]^2 - @NLconstraint(m, x[1] * (x[2] * x[3]) >= 1) # x[9] >= 1 : x[8] = x[2] * x[3] && x[9] = x[1]*x[8] - @NLconstraint(m, x[1]^2 * (x[2]^2 * x[3]^2) <= 1) # x[12] <= 1 : x[10] = x[3] ^ 2 && x[11] = x[7] * x[10] && x[12] = x[11]*[5] - - alpine = _build(m) - - @test alpine.bounding_constr_expr_mip[1] == :(x[5] - 1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[2] == :(x[6] - 1.0 <= 0.0) - @test alpine.bounding_constr_expr_mip[3] == :(x[8] - 1.0 <= 0.0) - @test alpine.bounding_constr_expr_mip[4] == :(x[10] - 1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[5] == :(x[13] - 1.0 <= 0.0) - @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[1])]) - @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2])]) - @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[2])]) - @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[3])]) - @test haskey(alpine.nonconvex_terms, [:(x[5]), :(x[7])]) - @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[9])]) - @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[3])]) - @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2])]) - @test haskey(alpine.nonconvex_terms, [:(x[5]), :(x[12])]) - - @test alpine.nonconvex_terms[[:(x[1]), :(x[1])]][:id] == 1 - @test alpine.nonconvex_terms[[:(x[1]), :(x[2])]][:id] == 2 - @test alpine.nonconvex_terms[[:(x[2]), :(x[2])]][:id] == 3 - @test alpine.nonconvex_terms[[:(x[5]), :(x[7])]][:id] == 4 - @test alpine.nonconvex_terms[[:(x[2]), :(x[3])]][:id] == 5 - @test alpine.nonconvex_terms[[:(x[1]), :(x[9])]][:id] == 6 - @test alpine.nonconvex_terms[[:(x[3]), :(x[3])]][:id] == 7 - @test alpine.nonconvex_terms[[:(x[7]), :(x[11])]][:id] == 8 - @test alpine.nonconvex_terms[[:(x[5]), :(x[12])]][:id] == 9 -end - -@testset "Expression Parsing || part2" begin - m = Model( - optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "log_level" => 100, - ), - ) - - @variable(m, x[1:4] >= 0) - @NLconstraint(m, (x[1] * x[2]) * x[3] >= 1) - @NLconstraint(m, (x[1]^2 * x[2]^2) * x[3]^2 <= 1) - - @NLconstraint(m, x[1] * (x[2]^2 * x[3]^2) >= 1) - @NLconstraint(m, (x[1]^2 * x[2]) * x[3]^2 <= 1) - @NLconstraint(m, x[1]^2 * (x[2] * x[3]) >= 1) - @NLconstraint(m, (x[1] * x[2]^2) * x[3] <= 1) - - alpine = _build(m) - - @test alpine.bounding_constr_expr_mip[1] == :(x[6] - 1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[2] == :(x[11] - 1.0 <= 0.0) - @test alpine.bounding_constr_expr_mip[3] == :(x[13] - 1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[4] == :(x[15] - 1.0 <= 0.0) - @test alpine.bounding_constr_expr_mip[5] == :(x[17] - 1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[6] == :(x[19] - 1.0 <= 0.0) - - @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2])]) #5 - @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[5])]) #6 - @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[1])]) #7 - @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[2])]) #8 - @test haskey(alpine.nonconvex_terms, [:(x[7]), :(x[8])]) #9 - @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[3])]) #10 - @test haskey(alpine.nonconvex_terms, [:(x[9]), :(x[10])]) #11 - @test haskey(alpine.nonconvex_terms, [:(x[8]), :(x[10])]) #12 - @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[12])]) #13 - @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[7])]) #14 - @test haskey(alpine.nonconvex_terms, [:(x[14]), :(x[10])]) #15 - @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[3])]) #16 - @test haskey(alpine.nonconvex_terms, [:(x[7]), :(x[16])]) #17 - @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[8])]) #18 - @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[18])]) #19 - - @test alpine.nonconvex_terms[[:(x[1]), :(x[2])]][:id] == 1 - @test alpine.nonconvex_terms[[:(x[3]), :(x[5])]][:id] == 2 - @test alpine.nonconvex_terms[[:(x[1]), :(x[1])]][:id] == 3 - @test alpine.nonconvex_terms[[:(x[2]), :(x[2])]][:id] == 4 - @test alpine.nonconvex_terms[[:(x[7]), :(x[8])]][:id] == 5 - @test alpine.nonconvex_terms[[:(x[3]), :(x[3])]][:id] == 6 - @test alpine.nonconvex_terms[[:(x[9]), :(x[10])]][:id] == 7 - @test alpine.nonconvex_terms[[:(x[8]), :(x[10])]][:id] == 8 - @test alpine.nonconvex_terms[[:(x[1]), :(x[12])]][:id] == 9 - @test alpine.nonconvex_terms[[:(x[2]), :(x[7])]][:id] == 10 - @test alpine.nonconvex_terms[[:(x[14]), :(x[10])]][:id] == 11 - @test alpine.nonconvex_terms[[:(x[2]), :(x[3])]][:id] == 12 - @test alpine.nonconvex_terms[[:(x[7]), :(x[16])]][:id] == 13 - @test alpine.nonconvex_terms[[:(x[1]), :(x[8])]][:id] == 14 - @test alpine.nonconvex_terms[[:(x[3]), :(x[18])]][:id] == 15 -end - -@testset "Expression Parsing || part3" begin - m = Model( - optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "log_level" => 100, - ), - ) - - @variable(m, x[1:4] >= 0) - @NLconstraint(m, ((x[1] * x[2]) * x[3]) * x[4] >= 1) - @NLconstraint(m, ((x[1]^2 * x[2]) * x[3]) * x[4] <= 1) - @NLconstraint(m, ((x[1] * x[2]^2) * x[3]) * x[4] >= 1) - @NLconstraint(m, ((x[1] * x[2]) * x[3]^2) * x[4] <= 1) - @NLconstraint(m, ((x[1] * x[2]) * x[3]) * x[4]^2 >= 1) - @NLconstraint(m, ((x[1]^2 * x[2]^2) * x[3]^2) * x[4]^2 <= 1) - - alpine = _build(m) - - @test alpine.bounding_constr_expr_mip[1] == :(x[7] - 1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[2] == :(x[11] - 1.0 <= 0.0) - @test alpine.bounding_constr_expr_mip[3] == :(x[15] - 1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[4] == :(x[18] - 1.0 <= 0.0) - @test alpine.bounding_constr_expr_mip[5] == :(x[20] - 1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[6] == :(x[23] - 1.0 <= 0.0) - - @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2])]) #5 - @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[5])]) #6 - @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[6])]) #7 - @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[1])]) #8 - @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[8])]) #9 - @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[9])]) #10 - @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[10])]) #11 - @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[2])]) #12 - @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[12])]) #13 - @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[13])]) #14 - @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[14])]) #15 - @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[3])]) #16 - @test haskey(alpine.nonconvex_terms, [:(x[5]), :(x[16])]) #17 - @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[17])]) #18 - @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[4])]) #19 - @test haskey(alpine.nonconvex_terms, [:(x[6]), :(x[19])]) #20 - @test haskey(alpine.nonconvex_terms, [:(x[8]), :(x[12])]) #21 - @test haskey(alpine.nonconvex_terms, [:(x[21]), :(x[16])]) #22 - @test haskey(alpine.nonconvex_terms, [:(x[22]), :(x[19])]) #23 - - @test alpine.nonconvex_terms[[:(x[1]), :(x[2])]][:id] == 1 - @test alpine.nonconvex_terms[[:(x[3]), :(x[5])]][:id] == 2 - @test alpine.nonconvex_terms[[:(x[4]), :(x[6])]][:id] == 3 - @test alpine.nonconvex_terms[[:(x[1]), :(x[1])]][:id] == 4 - @test alpine.nonconvex_terms[[:(x[2]), :(x[8])]][:id] == 5 - @test alpine.nonconvex_terms[[:(x[3]), :(x[9])]][:id] == 6 - @test alpine.nonconvex_terms[[:(x[4]), :(x[10])]][:id] == 7 - @test alpine.nonconvex_terms[[:(x[2]), :(x[2])]][:id] == 8 - @test alpine.nonconvex_terms[[:(x[1]), :(x[12])]][:id] == 9 - @test alpine.nonconvex_terms[[:(x[3]), :(x[13])]][:id] == 10 - @test alpine.nonconvex_terms[[:(x[4]), :(x[14])]][:id] == 11 - @test alpine.nonconvex_terms[[:(x[3]), :(x[3])]][:id] == 12 - @test alpine.nonconvex_terms[[:(x[5]), :(x[16])]][:id] == 13 - @test alpine.nonconvex_terms[[:(x[4]), :(x[17])]][:id] == 14 - @test alpine.nonconvex_terms[[:(x[4]), :(x[4])]][:id] == 15 - @test alpine.nonconvex_terms[[:(x[6]), :(x[19])]][:id] == 16 - @test alpine.nonconvex_terms[[:(x[8]), :(x[12])]][:id] == 17 - @test alpine.nonconvex_terms[[:(x[21]), :(x[16])]][:id] == 18 - @test alpine.nonconvex_terms[[:(x[22]), :(x[19])]][:id] == 19 -end - -@testset "Expression Parsing || part7" begin - m = Model( - optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "log_level" => 100, - ), - ) - @variable(m, x[1:4] >= 0) - - @NLconstraint(m, x[1] * x[2] * x[3] * x[4] >= 1) - @NLconstraint(m, x[1]^2 * x[2] * x[3] * x[4] >= 1) - @NLconstraint(m, x[1] * x[2]^2 * x[3] * x[4] >= 1) - @NLconstraint(m, x[1] * x[2] * x[3]^2 * x[4]^2 >= 1) - @NLconstraint(m, x[1] * x[2]^2 * x[3]^2 * x[4] >= 1) - @NLconstraint(m, x[1]^2 * x[2] * x[3] * x[4]^2 >= 1) - @NLconstraint(m, x[1]^2 * x[2]^2 * x[3]^2 * x[4]^2 >= 1) - - alpine = _build(m) - - @test alpine.bounding_constr_expr_mip[1] == :(x[5] - 1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[2] == :(x[7] - 1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[3] == :(x[9] - 1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[4] == :(x[12] - 1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[5] == :(x[13] - 1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[6] == :(x[14] - 1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[7] == :(x[15] - 1.0 >= 0.0) - - @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2]), :(x[3]), :(x[4])]) #5 - @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[1])]) #6 - @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[3]), :(x[4]), :(x[6])]) #7 - @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[2])]) #8 - @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[3]), :(x[4]), :(x[8])]) #9 - @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[3])]) #10 - @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[4])]) #11 - @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2]), :(x[10]), :(x[11])]) #12 - @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[4]), :(x[8]), :(x[10])]) #13 - @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[3]), :(x[6]), :(x[11])]) #14 - @test haskey(alpine.nonconvex_terms, [:(x[6]), :(x[8]), :(x[10]), :(x[11])]) #15 - - @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:id] == 1 #5 - @test alpine.nonconvex_terms[[:(x[1]), :(x[1])]][:id] == 2 #6 - @test alpine.nonconvex_terms[[:(x[2]), :(x[3]), :(x[4]), :(x[6])]][:id] == 3 #7 - @test alpine.nonconvex_terms[[:(x[2]), :(x[2])]][:id] == 4 #8 - @test alpine.nonconvex_terms[[:(x[1]), :(x[3]), :(x[4]), :(x[8])]][:id] == 5 #9 - @test alpine.nonconvex_terms[[:(x[3]), :(x[3])]][:id] == 6 #10 - @test alpine.nonconvex_terms[[:(x[4]), :(x[4])]][:id] == 7 #11 - @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[10]), :(x[11])]][:id] == 8 #12 - @test alpine.nonconvex_terms[[:(x[1]), :(x[4]), :(x[8]), :(x[10])]][:id] == 9 #13 - @test alpine.nonconvex_terms[[:(x[2]), :(x[3]), :(x[6]), :(x[11])]][:id] == 10 #14 - @test alpine.nonconvex_terms[[:(x[6]), :(x[8]), :(x[10]), :(x[11])]][:id] == 11 #15 -end - -@testset "Expression Parsing || part8" begin - m = Model( - optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "log_level" => 100, - ), - ) - @variable(m, x[1:4] >= 0) - - @NLconstraint(m, (x[1] * x[2] * x[3]) * x[4] >= 1) - @NLconstraint(m, (x[1]^2 * x[2] * x[3]) * x[4] >= 1) - @NLconstraint(m, x[1] * (x[2]^2 * x[3]) * x[4] >= 1) - @NLconstraint(m, x[1] * (x[2] * x[3]^2) * x[4] >= 1) - @NLconstraint(m, (x[1] * x[2]^2) * x[3] * x[4] >= 1) - @NLconstraint(m, (x[1] * x[2]) * x[3]^2 * x[4] >= 1) - @NLconstraint(m, (x[1] * x[2]) * x[3] * x[4]^2 >= 1) - @NLconstraint(m, (x[1] * x[2]) * x[3]^2 * x[4]^2 >= 1) - @NLconstraint(m, (x[1]^2 * x[2]^2 * x[3]^2) * x[4]^2 >= 1) - - alpine = _build(m) - - @test alpine.bounding_constr_expr_mip[1] == :(x[6] - 1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[2] == :(x[9] - 1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[3] == :(x[12] - 1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[4] == :(x[15] - 1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[5] == :(x[17] - 1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[6] == :(x[19] - 1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[7] == :(x[21] - 1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[8] == :(x[22] - 1.0 >= 0.0) - @test alpine.bounding_constr_expr_mip[9] == :(x[24] - 1.0 >= 0.0) - - @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2]), :(x[3])]) #5 - @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[5])]) #6 - @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[1])]) #7 - @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[3]), :(x[7])]) #8 - @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[8])]) #9 - @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[2])]) #10 - @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[10])]) #11 - @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[4]), :(x[11])]) #12 - @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[3])]) #13 - @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[13])]) #14 - @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[4]), :(x[14])]) #15 - @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[10])]) #16 - @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[4]), :(x[16])]) #17 - @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2])]) #18 - @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[18]), :(x[13])]) #19 - @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[4])]) #20 - @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[18]), :(x[20])]) #21 - @test haskey(alpine.nonconvex_terms, [:(x[18]), :(x[13]), :(x[20])]) #22 - @test haskey(alpine.nonconvex_terms, [:(x[7]), :(x[10]), :(x[13])]) #23 - @test haskey(alpine.nonconvex_terms, [:(x[23]), :(x[20])]) #24 -end - -@testset "Expression Parsing || Convex" begin - @testset "Convex Parsing :: PART I" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "log_level" => 100, - ) - m = convex_test(solver = test_solver) - - alpine = _build(m) - - @test alpine.num_constr_convex == 21 - - # 0 : OBJ - @test alpine.obj_structure == :convex - @test alpine.nonlinear_constrs[0][:expr_orig] == :objective - @test alpine.nonlinear_constrs[0][:convex_type] == :convexA - @test alpine.nonlinear_constrs[0][:convexified] == false - - @test alpine.bounding_obj_mip[:sense] === nothing - @test alpine.bounding_obj_mip[:coefs] == [1.0, 1.0] - @test alpine.bounding_obj_mip[:vars] == [:(x[1]), :(x[3])] - @test alpine.bounding_obj_mip[:rhs] == 0.0 - @test alpine.bounding_obj_mip[:powers] == [2, 2] - @test alpine.bounding_obj_mip[:cnt] == 2 - - # 1 - @test alpine.constr_structure[1] == :convex - @test alpine.nonlinear_constrs[1][:expr_orig] == :constraints - @test alpine.nonlinear_constrs[1][:convex_type] == :convexA - @test alpine.nonlinear_constrs[1][:convexified] == false - @test alpine.bounding_constr_mip[1][:sense] == :(<=) - @test alpine.bounding_constr_mip[1][:coefs] == [3.0, 4.0] - @test alpine.bounding_constr_mip[1][:vars] == [:(x[1]), :(x[2])] - @test alpine.bounding_constr_mip[1][:rhs] == 25.0 - @test alpine.bounding_constr_mip[1][:powers] == [2, 2] - @test alpine.bounding_constr_mip[1][:cnt] == 2 - - # 2 - @test alpine.constr_structure[2] == :convex - @test alpine.nonlinear_constrs[2][:expr_orig] == :constraints - @test alpine.nonlinear_constrs[2][:convex_type] == :convexA - @test alpine.nonlinear_constrs[2][:convexified] == false - @test alpine.bounding_constr_mip[2][:sense] == :(<=) - @test alpine.bounding_constr_mip[2][:coefs] == [3.0, 4.0] - @test alpine.bounding_constr_mip[2][:vars] == [:(x[1]), :(x[2])] - @test alpine.bounding_constr_mip[2][:rhs] == 25.0 - @test alpine.bounding_constr_mip[2][:powers] == [2, 2] - @test alpine.bounding_constr_mip[2][:cnt] == 2 - - # 4 - @test alpine.constr_structure[4] == :convex - @test alpine.nonlinear_constrs[4][:expr_orig] == :constraints - @test alpine.nonlinear_constrs[4][:convex_type] == :convexA - @test alpine.nonlinear_constrs[4][:convexified] == false - @test alpine.bounding_constr_mip[4][:sense] == :(<=) - @test alpine.bounding_constr_mip[4][:coefs] == [3.0, 4.0] - @test alpine.bounding_constr_mip[4][:vars] == [:(x[1]), :(x[2])] - @test alpine.bounding_constr_mip[4][:rhs] == 10.0 - @test alpine.bounding_constr_mip[4][:powers] == [2, 2] - @test alpine.bounding_constr_mip[4][:cnt] == 2 - - # 5 - @test alpine.constr_structure[5] == :convex - @test alpine.nonlinear_constrs[5][:expr_orig] == :constraints - @test alpine.nonlinear_constrs[5][:convex_type] == :convexA - @test alpine.nonlinear_constrs[5][:convexified] == :false - @test alpine.bounding_constr_mip[5][:sense] == :(<=) - @test alpine.bounding_constr_mip[5][:coefs] == [3.0, 4.0, 6.0] - @test alpine.bounding_constr_mip[5][:vars] == [:(x[1]), :(x[2]), :(x[3])] - @test alpine.bounding_constr_mip[5][:rhs] == 10.0 - @test alpine.bounding_constr_mip[5][:powers] == [2, 2, 2] - @test alpine.bounding_constr_mip[5][:cnt] == 3 - - # 6 - @test alpine.constr_structure[6] == :convex - @test alpine.nonlinear_constrs[6][:expr_orig] == :constraints - @test alpine.nonlinear_constrs[6][:convex_type] == :convexC - @test alpine.nonlinear_constrs[6][:convexified] == :false - @test alpine.bounding_constr_mip[6][:sense] == :(<=) - @test alpine.bounding_constr_mip[6][:coefs] == [3.0, 4.0, 5.0] - @test alpine.bounding_constr_mip[6][:vars] == [:(x[1]), :(x[2]), :(x[5])] - @test alpine.bounding_constr_mip[6][:rhs] == 100.0 - @test alpine.bounding_constr_mip[6][:powers] == [0.5, 0.5, 0.5] - @test alpine.bounding_constr_mip[6][:cnt] == 3 - - # 7 - @test alpine.constr_structure[7] == :convex - @test alpine.nonlinear_constrs[7][:expr_orig] == :constraints - @test alpine.nonlinear_constrs[7][:convex_type] == :convexC - @test alpine.nonlinear_constrs[7][:convexified] == :false - @test alpine.bounding_constr_mip[7][:sense] == :(>=) - @test alpine.bounding_constr_mip[7][:coefs] == [-3.0, -4.0] - @test alpine.bounding_constr_mip[7][:vars] == [:(x[1]), :(x[2])] - @test alpine.bounding_constr_mip[7][:rhs] == -100.0 - @test alpine.bounding_constr_mip[7][:powers] == [0.5, 0.5] - @test alpine.bounding_constr_mip[7][:cnt] == 2 - - # 8 - @test alpine.constr_structure[8] == :convex - @test alpine.nonlinear_constrs[8][:expr_orig] == :constraints - @test alpine.nonlinear_constrs[8][:convex_type] == :convexB - @test alpine.nonlinear_constrs[8][:convexified] == :false - @test alpine.bounding_constr_mip[8][:sense] == :(<=) - @test alpine.bounding_constr_mip[8][:coefs] == [3.0, 1.0, 5.0] - @test alpine.bounding_constr_mip[8][:vars] == [:(x[1]), :(x[2]), :(x[3])] - @test alpine.bounding_constr_mip[8][:rhs] == 200.0 - @test alpine.bounding_constr_mip[8][:powers] == [3.0, 3.0, 3.0] - @test alpine.bounding_constr_mip[8][:cnt] == 3 - - # 9 - @test alpine.constr_structure[9] == :convex - @test alpine.nonlinear_constrs[9][:expr_orig] == :constraints - @test alpine.nonlinear_constrs[9][:convex_type] == :convexB - @test alpine.nonlinear_constrs[9][:convexified] == :false - @test alpine.bounding_constr_mip[9][:sense] == :(<=) - @test alpine.bounding_constr_mip[9][:coefs] == [1.0, 1.0, 1.0, 100.0] - @test alpine.bounding_constr_mip[9][:vars] == [:(x[1]), :(x[2]), :(x[3]), :(x[4])] - @test alpine.bounding_constr_mip[9][:rhs] == 200.0 - @test alpine.bounding_constr_mip[9][:powers] == [3, 3, 3, 3] - @test alpine.bounding_constr_mip[9][:cnt] == 4 - - # 11 - @test alpine.constr_structure[11] == :convex - @test alpine.nonlinear_constrs[11][:expr_orig] == :constraints - @test alpine.nonlinear_constrs[11][:convex_type] == :convexA - @test alpine.nonlinear_constrs[11][:convexified] == :false - @test alpine.bounding_constr_mip[11][:sense] == :(<=) - @test alpine.bounding_constr_mip[11][:coefs] == [3.0, 4.0] - @test alpine.bounding_constr_mip[11][:vars] == [:(x[1]), :(x[2])] - @test alpine.bounding_constr_mip[11][:rhs] == 25.0 - @test alpine.bounding_constr_mip[11][:powers] == [2, 2] - @test alpine.bounding_constr_mip[11][:cnt] == 2 - - # 14 - @test alpine.constr_structure[14] == :convex - @test alpine.nonlinear_constrs[14][:expr_orig] == :constraints - @test alpine.nonlinear_constrs[14][:convex_type] == :convexA - @test alpine.nonlinear_constrs[14][:convexified] == :false - @test alpine.bounding_constr_mip[14][:sense] == :(<=) - @test alpine.bounding_constr_mip[14][:coefs] == [3.0, 5.0] - @test alpine.bounding_constr_mip[14][:vars] == [:(x[1]), :(x[2])] - @test alpine.bounding_constr_mip[14][:rhs] == 25.0 - @test alpine.bounding_constr_mip[14][:powers] == [2, 2] - @test alpine.bounding_constr_mip[14][:cnt] == 2 - - # 15 - @test alpine.constr_structure[15] == :convex - @test alpine.nonlinear_constrs[15][:expr_orig] == :constraints - @test alpine.nonlinear_constrs[15][:convex_type] == :convexA - @test alpine.nonlinear_constrs[15][:convexified] == :false - @test alpine.bounding_constr_mip[15][:sense] == :(<=) - @test alpine.bounding_constr_mip[15][:coefs] == [3.0, 5.0, 1.0] - @test alpine.bounding_constr_mip[15][:vars] == [:(x[1]), :(x[2]), :(x[4])] - @test alpine.bounding_constr_mip[15][:rhs] == 25.0 - @test alpine.bounding_constr_mip[15][:powers] == [2, 2, 2] - @test alpine.bounding_constr_mip[15][:cnt] == 3 - - # 19 - @test alpine.constr_structure[19] == :convex - @test alpine.nonlinear_constrs[19][:expr_orig] == :constraints - @test alpine.nonlinear_constrs[19][:convex_type] == :convexA - @test alpine.nonlinear_constrs[19][:convexified] == :false - @test alpine.bounding_constr_mip[19][:sense] == :(<=) - @test alpine.bounding_constr_mip[19][:coefs] == [3.0, 16.0] - @test alpine.bounding_constr_mip[19][:vars] == [:(x[1]), :(x[2])] - @test alpine.bounding_constr_mip[19][:rhs] == 40.0 - @test alpine.bounding_constr_mip[19][:powers] == [2, 2] - @test alpine.bounding_constr_mip[19][:cnt] == 2 - - # 22 - @test alpine.constr_structure[22] == :convex - @test alpine.nonlinear_constrs[22][:expr_orig] == :constraints - @test alpine.nonlinear_constrs[22][:convex_type] == :convexA - @test alpine.nonlinear_constrs[22][:convexified] == :false - @test alpine.bounding_constr_mip[22][:sense] == :(<=) - @test alpine.bounding_constr_mip[22][:coefs] == [3.0, 4.0, 5.0, 6.0] - @test alpine.bounding_constr_mip[22][:vars] == - [:(x[1]), :(x[2]), :(x[3]), :(x[4])] - @test alpine.bounding_constr_mip[22][:rhs] == 15.0 - @test alpine.bounding_constr_mip[22][:powers] == [2, 2, 2, 2] - @test alpine.bounding_constr_mip[22][:cnt] == 4 - - # 25 - @test alpine.constr_structure[25] == :convex - @test alpine.nonlinear_constrs[25][:expr_orig] == :constraints - @test alpine.nonlinear_constrs[25][:convex_type] == :convexA - @test alpine.nonlinear_constrs[25][:convexified] == :false - @test alpine.bounding_constr_mip[25][:sense] == :(<=) - @test alpine.bounding_constr_mip[25][:coefs] == [1.0, 1.0, 1.0, 1.0, 1.0] - @test alpine.bounding_constr_mip[25][:vars] == - [:(x[1]), :(x[2]), :(x[3]), :(x[4]), :(x[5])] - @test alpine.bounding_constr_mip[25][:rhs] == 99999.0 - @test alpine.bounding_constr_mip[25][:powers] == [2, 2, 2, 2, 2] - @test alpine.bounding_constr_mip[25][:cnt] == 5 - - # 26 - @test alpine.constr_structure[26] == :convex - @test alpine.nonlinear_constrs[26][:expr_orig] == :constraints - @test alpine.nonlinear_constrs[26][:convex_type] == :convexA - @test alpine.nonlinear_constrs[26][:convexified] == :false - @test alpine.bounding_constr_mip[26][:sense] == :(<=) - @test alpine.bounding_constr_mip[26][:coefs] == [3.0, 4.0] - @test alpine.bounding_constr_mip[26][:vars] == [:(x[1]), :(x[2])] - @test alpine.bounding_constr_mip[26][:rhs] == 200.0 - @test alpine.bounding_constr_mip[26][:powers] == [4, 4] - @test alpine.bounding_constr_mip[26][:cnt] == 2 - end -end - -@testset "Expression Prasing || Linear Lifting" begin - @testset "Expression Parsing || Linear Lifting || nlp2" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "disc_ratio" => 8, - "log_level" => 100, - ) - - m = nlp2(solver = test_solver) - - alpine = _build(m) - - @test length(alpine.linear_terms) == 2 - @test length(alpine.nonconvex_terms) == 4 - - lk = Vector{Any}(undef, 2) - lk[1] = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, -1.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3)])), - ) - lk[2] = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, -2.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6)])), - ) - - @test length(keys(alpine.linear_terms)) == 2 - yids = [4, 7] - for i in 1:length(keys(alpine.linear_terms)) - for j in keys(alpine.linear_terms) - if alpine.linear_terms[j][:id] == i - @test j == lk[i] - @test j[:sign] == :+ - @test j[:scalar] == lk[i][:scalar] - @test j[:coef_var] == lk[i][:coef_var] - @test alpine.linear_terms[j][:y_idx] == yids[i] - end - end - end - - @test haskey(alpine.linear_terms, lk[1]) - @test haskey(alpine.linear_terms, lk[2]) - - @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[2])]) - @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[4])]) - @test haskey(alpine.nonconvex_terms, [:(x[7]), :(x[7])]) - @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[1])]) - @test alpine.nonconvex_terms[[:(x[1]), :(x[1])]][:id] == 1 - @test alpine.nonconvex_terms[[:(x[2]), :(x[2])]][:id] == 3 - @test alpine.nonconvex_terms[[:(x[4]), :(x[4])]][:id] == 2 - @test alpine.nonconvex_terms[[:(x[7]), :(x[7])]][:id] == 4 - @test alpine.nonconvex_terms[[:(x[1]), :(x[1])]][:lifted_var_ref].args[2] == 3 - @test alpine.nonconvex_terms[[:(x[2]), :(x[2])]][:lifted_var_ref].args[2] == 6 - @test alpine.nonconvex_terms[[:(x[4]), :(x[4])]][:lifted_var_ref].args[2] == 5 - @test alpine.nonconvex_terms[[:(x[7]), :(x[7])]][:lifted_var_ref].args[2] == 8 - end - - @testset "Expression Parsing || Linear Lifting || general" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "log_level" => 100, - ) - - m = basic_linear_lift(solver = test_solver) - - alpine = _build(m) # Setup internal model - - lk = Vector{Any}(undef, 5) - lk[1] = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1), (-1.0, 2)])), - ) - lk[2] = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(3.0, 2), (-1.0, 3)])), - ) - lk[3] = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1), (1.0, 3)])), - ) - lk[4] = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 2), (1.0, 1)])), - ) - lk[5] = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 3.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 2), (1.0, 1), (1.0, 3)])), - ) - - @test length(keys(alpine.linear_terms)) == 5 - yids = [8, 9, 12, 14, 16] - for i in 1:length(keys(alpine.linear_terms)) - for j in keys(alpine.linear_terms) - if alpine.linear_terms[j][:id] == i - @test j == lk[i] - @test j[:sign] == :+ - @test j[:scalar] == lk[i][:scalar] - @test j[:coef_var] == lk[i][:coef_var] - @test alpine.linear_terms[j][:y_idx] == yids[i] - end - end - end - - nlk1 = [:(x[8]), :(x[9]), :(x[12])] - nlk2 = [:(x[2]), :(x[2])] - nlk3 = [:(x[2]), :(x[3])] - nlk4 = [:(x[8]), :(x[8])] - nlk5 = [:(x[1]), :(x[3])] - nlk6 = [:(x[8]), :(x[9])] - nlk7 = [:(x[1]), :(x[2])] - nlk8 = [:(x[16]), :(x[15])] - nlk9 = [:(x[14]), :(x[14])] - - @test alpine.nonconvex_terms[nlk1][:id] == 7 - @test alpine.nonconvex_terms[nlk2][:id] == 3 - @test alpine.nonconvex_terms[nlk3][:id] == 4 - @test alpine.nonconvex_terms[nlk4][:id] == 6 - @test alpine.nonconvex_terms[nlk5][:id] == 2 - @test alpine.nonconvex_terms[nlk6][:id] == 5 - @test alpine.nonconvex_terms[nlk7][:id] == 1 - @test alpine.nonconvex_terms[nlk8][:id] == 9 - @test alpine.nonconvex_terms[nlk9][:id] == 8 - - @test alpine.nonconvex_terms[nlk1][:lifted_var_ref].args[2] == 13 - @test alpine.nonconvex_terms[nlk2][:lifted_var_ref].args[2] == 6 - @test alpine.nonconvex_terms[nlk3][:lifted_var_ref].args[2] == 7 - @test alpine.nonconvex_terms[nlk4][:lifted_var_ref].args[2] == 11 - @test alpine.nonconvex_terms[nlk5][:lifted_var_ref].args[2] == 5 - @test alpine.nonconvex_terms[nlk6][:lifted_var_ref].args[2] == 10 - @test alpine.nonconvex_terms[nlk7][:lifted_var_ref].args[2] == 4 - @test alpine.nonconvex_terms[nlk8][:lifted_var_ref].args[2] == 17 - @test alpine.nonconvex_terms[nlk9][:lifted_var_ref].args[2] == 15 - - @test alpine.nonconvex_terms[nlk1][:nonlinear_type] == :MULTILINEAR - @test alpine.nonconvex_terms[nlk2][:nonlinear_type] == :MONOMIAL - @test alpine.nonconvex_terms[nlk3][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[nlk4][:nonlinear_type] == :MONOMIAL - @test alpine.nonconvex_terms[nlk5][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[nlk6][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[nlk7][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[nlk8][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[nlk9][:nonlinear_type] == :MONOMIAL - - @test alpine.nonconvex_terms[nlk1][:var_idxs] == [8, 9, 12] - @test alpine.nonconvex_terms[nlk2][:var_idxs] == [2, 2] - @test alpine.nonconvex_terms[nlk3][:var_idxs] == [2, 3] - @test alpine.nonconvex_terms[nlk4][:var_idxs] == [8] - @test alpine.nonconvex_terms[nlk5][:var_idxs] == [1, 3] - @test alpine.nonconvex_terms[nlk6][:var_idxs] == [8, 9] - @test alpine.nonconvex_terms[nlk7][:var_idxs] == [1, 2] - @test alpine.nonconvex_terms[nlk8][:var_idxs] == [16, 15] - @test alpine.nonconvex_terms[nlk9][:var_idxs] == [14] - end - - @testset "Expression Parsing || Linear Lifting || brainpc3" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "disc_ratio" => 8, - "log_level" => 100, - ) - - m = brainpc3(solver = test_solver) - - alpine = _build(m) - - @test alpine.nonconvex_terms[Expr[:(x[6912]), :(x[6912])]][:y_idx] == 6913 - @test alpine.nonconvex_terms[Expr[:(x[6912]), :(x[6912])]][:id] == 2 - @test alpine.nonconvex_terms[Expr[:(x[6912]), :(x[6912])]][:lifted_constr_ref] == - :(x[6913] == (*)(x[6912])) - @test alpine.nonconvex_terms[Expr[:(x[6912]), :(x[6912])]][:nonlinear_type] == - :MONOMIAL - @test alpine.nonconvex_terms[Expr[:(x[6912]), :(x[6912])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6912]), :(x[6912])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6969])]][:y_idx] == 6970 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6969])]][:id] == 25 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6969])]][:lifted_constr_ref] == - :(x[6970] == x[6903] * x[6969]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6969])]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6969])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6969])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6914])]][:y_idx] == 6915 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6914])]][:id] == 3 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6914])]][:lifted_constr_ref] == - :(x[6915] == x[6903] * x[6914]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6914])]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6914])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6914])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6919])]][:y_idx] == 6920 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6919])]][:id] == 5 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6919])]][:lifted_constr_ref] == - :(x[6920] == x[6903] * x[6919]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6919])]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6919])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6919])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6927]), :(x[6927])]][:y_idx] == 6928 - @test alpine.nonconvex_terms[Expr[:(x[6927]), :(x[6927])]][:id] == 8 - @test alpine.nonconvex_terms[Expr[:(x[6927]), :(x[6927])]][:lifted_constr_ref] == - :(x[6928] == (*)(x[6927])) - @test alpine.nonconvex_terms[Expr[:(x[6927]), :(x[6927])]][:nonlinear_type] == - :MONOMIAL - @test alpine.nonconvex_terms[Expr[:(x[6927]), :(x[6927])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6927]), :(x[6927])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6952]), :(x[6952])]][:y_idx] == 6953 - @test alpine.nonconvex_terms[Expr[:(x[6952]), :(x[6952])]][:id] == 18 - @test alpine.nonconvex_terms[Expr[:(x[6952]), :(x[6952])]][:lifted_constr_ref] == - :(x[6953] == (*)(x[6952])) - @test alpine.nonconvex_terms[Expr[:(x[6952]), :(x[6952])]][:nonlinear_type] == - :MONOMIAL - @test alpine.nonconvex_terms[Expr[:(x[6952]), :(x[6952])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6952]), :(x[6952])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6962]), :(x[6962])]][:y_idx] == 6963 - @test alpine.nonconvex_terms[Expr[:(x[6962]), :(x[6962])]][:id] == 22 - @test alpine.nonconvex_terms[Expr[:(x[6962]), :(x[6962])]][:lifted_constr_ref] == - :(x[6963] == (*)(x[6962])) - @test alpine.nonconvex_terms[Expr[:(x[6962]), :(x[6962])]][:nonlinear_type] == - :MONOMIAL - @test alpine.nonconvex_terms[Expr[:(x[6962]), :(x[6962])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6962]), :(x[6962])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6974])]][:y_idx] == 6975 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6974])]][:id] == 27 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6974])]][:lifted_constr_ref] == - :(x[6975] == x[6903] * x[6974]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6974])]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6974])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6974])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6934])]][:y_idx] == 6935 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6934])]][:id] == 11 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6934])]][:lifted_constr_ref] == - :(x[6935] == x[6903] * x[6934]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6934])]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6934])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6934])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6959])]][:y_idx] == 6960 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6959])]][:id] == 21 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6959])]][:lifted_constr_ref] == - :(x[6960] == x[6903] * x[6959]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6959])]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6959])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6959])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7014])]][:y_idx] == 7015 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7014])]][:id] == 43 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7014])]][:lifted_constr_ref] == - :(x[7015] == x[6903] * x[7014]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7014])]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7014])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7014])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6939])]][:y_idx] == 6940 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6939])]][:id] == 13 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6939])]][:lifted_constr_ref] == - :(x[6940] == x[6903] * x[6939]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6939])]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6939])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6939])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[7017]), :(x[7017])]][:y_idx] == 7018 - @test alpine.nonconvex_terms[Expr[:(x[7017]), :(x[7017])]][:id] == 44 - @test alpine.nonconvex_terms[Expr[:(x[7017]), :(x[7017])]][:lifted_constr_ref] == - :(x[7018] == (*)(x[7017])) - @test alpine.nonconvex_terms[Expr[:(x[7017]), :(x[7017])]][:nonlinear_type] == - :MONOMIAL - @test alpine.nonconvex_terms[Expr[:(x[7017]), :(x[7017])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[7017]), :(x[7017])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6929])]][:y_idx] == 6930 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6929])]][:id] == 9 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6929])]][:lifted_constr_ref] == - :(x[6930] == x[6903] * x[6929]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6929])]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6929])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6929])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[7012]), :(x[7012])]][:y_idx] == 7013 - @test alpine.nonconvex_terms[Expr[:(x[7012]), :(x[7012])]][:id] == 42 - @test alpine.nonconvex_terms[Expr[:(x[7012]), :(x[7012])]][:lifted_constr_ref] == - :(x[7013] == (*)(x[7012])) - @test alpine.nonconvex_terms[Expr[:(x[7012]), :(x[7012])]][:nonlinear_type] == - :MONOMIAL - @test alpine.nonconvex_terms[Expr[:(x[7012]), :(x[7012])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[7012]), :(x[7012])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6947]), :(x[6947])]][:y_idx] == 6948 - @test alpine.nonconvex_terms[Expr[:(x[6947]), :(x[6947])]][:id] == 16 - @test alpine.nonconvex_terms[Expr[:(x[6947]), :(x[6947])]][:lifted_constr_ref] == - :(x[6948] == (*)(x[6947])) - @test alpine.nonconvex_terms[Expr[:(x[6947]), :(x[6947])]][:nonlinear_type] == - :MONOMIAL - @test alpine.nonconvex_terms[Expr[:(x[6947]), :(x[6947])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6947]), :(x[6947])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[7032]), :(x[7032])]][:y_idx] == 7033 - @test alpine.nonconvex_terms[Expr[:(x[7032]), :(x[7032])]][:id] == 50 - @test alpine.nonconvex_terms[Expr[:(x[7032]), :(x[7032])]][:lifted_constr_ref] == - :(x[7033] == (*)(x[7032])) - @test alpine.nonconvex_terms[Expr[:(x[7032]), :(x[7032])]][:nonlinear_type] == - :MONOMIAL - @test alpine.nonconvex_terms[Expr[:(x[7032]), :(x[7032])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[7032]), :(x[7032])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6997]), :(x[6997])]][:y_idx] == 6998 - @test alpine.nonconvex_terms[Expr[:(x[6997]), :(x[6997])]][:id] == 36 - @test alpine.nonconvex_terms[Expr[:(x[6997]), :(x[6997])]][:lifted_constr_ref] == - :(x[6998] == (*)(x[6997])) - @test alpine.nonconvex_terms[Expr[:(x[6997]), :(x[6997])]][:nonlinear_type] == - :MONOMIAL - @test alpine.nonconvex_terms[Expr[:(x[6997]), :(x[6997])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6997]), :(x[6997])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[7027]), :(x[7027])]][:y_idx] == 7028 - @test alpine.nonconvex_terms[Expr[:(x[7027]), :(x[7027])]][:id] == 48 - @test alpine.nonconvex_terms[Expr[:(x[7027]), :(x[7027])]][:lifted_constr_ref] == - :(x[7028] == (*)(x[7027])) - @test alpine.nonconvex_terms[Expr[:(x[7027]), :(x[7027])]][:nonlinear_type] == - :MONOMIAL - @test alpine.nonconvex_terms[Expr[:(x[7027]), :(x[7027])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[7027]), :(x[7027])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[7037]), :(x[7037])]][:y_idx] == 7038 - @test alpine.nonconvex_terms[Expr[:(x[7037]), :(x[7037])]][:id] == 52 - @test alpine.nonconvex_terms[Expr[:(x[7037]), :(x[7037])]][:lifted_constr_ref] == - :(x[7038] == (*)(x[7037])) - @test alpine.nonconvex_terms[Expr[:(x[7037]), :(x[7037])]][:nonlinear_type] == - :MONOMIAL - @test alpine.nonconvex_terms[Expr[:(x[7037]), :(x[7037])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[7037]), :(x[7037])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[7007]), :(x[7007])]][:y_idx] == 7008 - @test alpine.nonconvex_terms[Expr[:(x[7007]), :(x[7007])]][:id] == 40 - @test alpine.nonconvex_terms[Expr[:(x[7007]), :(x[7007])]][:lifted_constr_ref] == - :(x[7008] == (*)(x[7007])) - @test alpine.nonconvex_terms[Expr[:(x[7007]), :(x[7007])]][:nonlinear_type] == - :MONOMIAL - @test alpine.nonconvex_terms[Expr[:(x[7007]), :(x[7007])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[7007]), :(x[7007])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6964])]][:y_idx] == 6965 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6964])]][:id] == 23 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6964])]][:lifted_constr_ref] == - :(x[6965] == x[6903] * x[6964]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6964])]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6964])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6964])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6924])]][:y_idx] == 6925 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6924])]][:id] == 7 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6924])]][:lifted_constr_ref] == - :(x[6925] == x[6903] * x[6924]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6924])]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6924])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6924])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6979])]][:y_idx] == 6980 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6979])]][:id] == 29 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6979])]][:lifted_constr_ref] == - :(x[6980] == x[6903] * x[6979]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6979])]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6979])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6979])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6994])]][:y_idx] == 6995 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6994])]][:id] == 35 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6994])]][:lifted_constr_ref] == - :(x[6995] == x[6903] * x[6994]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6994])]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6994])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6994])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6972]), :(x[6972])]][:y_idx] == 6973 - @test alpine.nonconvex_terms[Expr[:(x[6972]), :(x[6972])]][:id] == 26 - @test alpine.nonconvex_terms[Expr[:(x[6972]), :(x[6972])]][:lifted_constr_ref] == - :(x[6973] == (*)(x[6972])) - @test alpine.nonconvex_terms[Expr[:(x[6972]), :(x[6972])]][:nonlinear_type] == - :MONOMIAL - @test alpine.nonconvex_terms[Expr[:(x[6972]), :(x[6972])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6972]), :(x[6972])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7019])]][:y_idx] == 7020 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7019])]][:id] == 45 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7019])]][:lifted_constr_ref] == - :(x[7020] == x[6903] * x[7019]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7019])]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7019])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7019])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6992]), :(x[6992])]][:y_idx] == 6993 - @test alpine.nonconvex_terms[Expr[:(x[6992]), :(x[6992])]][:id] == 34 - @test alpine.nonconvex_terms[Expr[:(x[6992]), :(x[6992])]][:lifted_constr_ref] == - :(x[6993] == (*)(x[6992])) - @test alpine.nonconvex_terms[Expr[:(x[6992]), :(x[6992])]][:nonlinear_type] == - :MONOMIAL - @test alpine.nonconvex_terms[Expr[:(x[6992]), :(x[6992])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6992]), :(x[6992])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[7002]), :(x[7002])]][:y_idx] == 7003 - @test alpine.nonconvex_terms[Expr[:(x[7002]), :(x[7002])]][:id] == 38 - @test alpine.nonconvex_terms[Expr[:(x[7002]), :(x[7002])]][:lifted_constr_ref] == - :(x[7003] == (*)(x[7002])) - @test alpine.nonconvex_terms[Expr[:(x[7002]), :(x[7002])]][:nonlinear_type] == - :MONOMIAL - @test alpine.nonconvex_terms[Expr[:(x[7002]), :(x[7002])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[7002]), :(x[7002])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[7022]), :(x[7022])]][:y_idx] == 7023 - @test alpine.nonconvex_terms[Expr[:(x[7022]), :(x[7022])]][:id] == 46 - @test alpine.nonconvex_terms[Expr[:(x[7022]), :(x[7022])]][:lifted_constr_ref] == - :(x[7023] == (*)(x[7022])) - @test alpine.nonconvex_terms[Expr[:(x[7022]), :(x[7022])]][:nonlinear_type] == - :MONOMIAL - @test alpine.nonconvex_terms[Expr[:(x[7022]), :(x[7022])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[7022]), :(x[7022])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6908])]][:y_idx] == 6909 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6908])]][:id] == 1 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6908])]][:lifted_constr_ref] == - :(x[6909] == x[6903] * x[6908]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6908])]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6908])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6908])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6949])]][:y_idx] == 6950 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6949])]][:id] == 17 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6949])]][:lifted_constr_ref] == - :(x[6950] == x[6903] * x[6949]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6949])]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6949])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6949])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7004])]][:y_idx] == 7005 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7004])]][:id] == 39 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7004])]][:lifted_constr_ref] == - :(x[7005] == x[6903] * x[7004]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7004])]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7004])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7004])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6917]), :(x[6917])]][:y_idx] == 6918 - @test alpine.nonconvex_terms[Expr[:(x[6917]), :(x[6917])]][:id] == 4 - @test alpine.nonconvex_terms[Expr[:(x[6917]), :(x[6917])]][:lifted_constr_ref] == - :(x[6918] == (*)(x[6917])) - @test alpine.nonconvex_terms[Expr[:(x[6917]), :(x[6917])]][:nonlinear_type] == - :MONOMIAL - @test alpine.nonconvex_terms[Expr[:(x[6917]), :(x[6917])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6917]), :(x[6917])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6937]), :(x[6937])]][:y_idx] == 6938 - @test alpine.nonconvex_terms[Expr[:(x[6937]), :(x[6937])]][:id] == 12 - @test alpine.nonconvex_terms[Expr[:(x[6937]), :(x[6937])]][:lifted_constr_ref] == - :(x[6938] == (*)(x[6937])) - @test alpine.nonconvex_terms[Expr[:(x[6937]), :(x[6937])]][:nonlinear_type] == - :MONOMIAL - @test alpine.nonconvex_terms[Expr[:(x[6937]), :(x[6937])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6937]), :(x[6937])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6932]), :(x[6932])]][:y_idx] == 6933 - @test alpine.nonconvex_terms[Expr[:(x[6932]), :(x[6932])]][:id] == 10 - @test alpine.nonconvex_terms[Expr[:(x[6932]), :(x[6932])]][:lifted_constr_ref] == - :(x[6933] == (*)(x[6932])) - @test alpine.nonconvex_terms[Expr[:(x[6932]), :(x[6932])]][:nonlinear_type] == - :MONOMIAL - @test alpine.nonconvex_terms[Expr[:(x[6932]), :(x[6932])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6932]), :(x[6932])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6989])]][:y_idx] == 6990 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6989])]][:id] == 33 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6989])]][:lifted_constr_ref] == - :(x[6990] == x[6903] * x[6989]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6989])]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6989])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6989])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6977]), :(x[6977])]][:y_idx] == 6978 - @test alpine.nonconvex_terms[Expr[:(x[6977]), :(x[6977])]][:id] == 28 - @test alpine.nonconvex_terms[Expr[:(x[6977]), :(x[6977])]][:lifted_constr_ref] == - :(x[6978] == (*)(x[6977])) - @test alpine.nonconvex_terms[Expr[:(x[6977]), :(x[6977])]][:nonlinear_type] == - :MONOMIAL - @test alpine.nonconvex_terms[Expr[:(x[6977]), :(x[6977])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6977]), :(x[6977])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6987]), :(x[6987])]][:y_idx] == 6988 - @test alpine.nonconvex_terms[Expr[:(x[6987]), :(x[6987])]][:id] == 32 - @test alpine.nonconvex_terms[Expr[:(x[6987]), :(x[6987])]][:lifted_constr_ref] == - :(x[6988] == (*)(x[6987])) - @test alpine.nonconvex_terms[Expr[:(x[6987]), :(x[6987])]][:nonlinear_type] == - :MONOMIAL - @test alpine.nonconvex_terms[Expr[:(x[6987]), :(x[6987])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6987]), :(x[6987])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7034])]][:y_idx] == 7035 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7034])]][:id] == 51 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7034])]][:lifted_constr_ref] == - :(x[7035] == x[6903] * x[7034]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7034])]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7034])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7034])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6967]), :(x[6967])]][:y_idx] == 6968 - @test alpine.nonconvex_terms[Expr[:(x[6967]), :(x[6967])]][:id] == 24 - @test alpine.nonconvex_terms[Expr[:(x[6967]), :(x[6967])]][:lifted_constr_ref] == - :(x[6968] == (*)(x[6967])) - @test alpine.nonconvex_terms[Expr[:(x[6967]), :(x[6967])]][:nonlinear_type] == - :MONOMIAL - @test alpine.nonconvex_terms[Expr[:(x[6967]), :(x[6967])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6967]), :(x[6967])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6957]), :(x[6957])]][:y_idx] == 6958 - @test alpine.nonconvex_terms[Expr[:(x[6957]), :(x[6957])]][:id] == 20 - @test alpine.nonconvex_terms[Expr[:(x[6957]), :(x[6957])]][:lifted_constr_ref] == - :(x[6958] == (*)(x[6957])) - @test alpine.nonconvex_terms[Expr[:(x[6957]), :(x[6957])]][:nonlinear_type] == - :MONOMIAL - @test alpine.nonconvex_terms[Expr[:(x[6957]), :(x[6957])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6957]), :(x[6957])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7009])]][:y_idx] == 7010 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7009])]][:id] == 41 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7009])]][:lifted_constr_ref] == - :(x[7010] == x[6903] * x[7009]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7009])]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7009])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7009])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6942]), :(x[6942])]][:y_idx] == 6943 - @test alpine.nonconvex_terms[Expr[:(x[6942]), :(x[6942])]][:id] == 14 - @test alpine.nonconvex_terms[Expr[:(x[6942]), :(x[6942])]][:lifted_constr_ref] == - :(x[6943] == (*)(x[6942])) - @test alpine.nonconvex_terms[Expr[:(x[6942]), :(x[6942])]][:nonlinear_type] == - :MONOMIAL - @test alpine.nonconvex_terms[Expr[:(x[6942]), :(x[6942])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6942]), :(x[6942])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6982]), :(x[6982])]][:y_idx] == 6983 - @test alpine.nonconvex_terms[Expr[:(x[6982]), :(x[6982])]][:id] == 30 - @test alpine.nonconvex_terms[Expr[:(x[6982]), :(x[6982])]][:lifted_constr_ref] == - :(x[6983] == (*)(x[6982])) - @test alpine.nonconvex_terms[Expr[:(x[6982]), :(x[6982])]][:nonlinear_type] == - :MONOMIAL - @test alpine.nonconvex_terms[Expr[:(x[6982]), :(x[6982])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6982]), :(x[6982])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6999])]][:y_idx] == 7000 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6999])]][:id] == 37 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6999])]][:lifted_constr_ref] == - :(x[7000] == x[6903] * x[6999]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6999])]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6999])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6999])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6944])]][:y_idx] == 6945 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6944])]][:id] == 15 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6944])]][:lifted_constr_ref] == - :(x[6945] == x[6903] * x[6944]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6944])]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6944])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6944])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7024])]][:y_idx] == 7025 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7024])]][:id] == 47 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7024])]][:lifted_constr_ref] == - :(x[7025] == x[6903] * x[7024]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7024])]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7024])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7024])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6954])]][:y_idx] == 6955 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6954])]][:id] == 19 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6954])]][:lifted_constr_ref] == - :(x[6955] == x[6903] * x[6954]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6954])]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6954])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6954])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6922]), :(x[6922])]][:y_idx] == 6923 - @test alpine.nonconvex_terms[Expr[:(x[6922]), :(x[6922])]][:id] == 6 - @test alpine.nonconvex_terms[Expr[:(x[6922]), :(x[6922])]][:lifted_constr_ref] == - :(x[6923] == (*)(x[6922])) - @test alpine.nonconvex_terms[Expr[:(x[6922]), :(x[6922])]][:nonlinear_type] == - :MONOMIAL - @test alpine.nonconvex_terms[Expr[:(x[6922]), :(x[6922])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6922]), :(x[6922])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6984])]][:y_idx] == 6985 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6984])]][:id] == 31 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6984])]][:lifted_constr_ref] == - :(x[6985] == x[6903] * x[6984]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6984])]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6984])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6984])]][:constr_id] == - Set(Any[0]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7029])]][:y_idx] == 7030 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7029])]][:id] == 49 - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7029])]][:lifted_constr_ref] == - :(x[7030] == x[6903] * x[7029]) - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7029])]][:nonlinear_type] == - :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7029])]][:y_type] == :Cont - @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7029])]][:constr_id] == - Set(Any[0]) - lk1 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6910), (-1.0, 6909)])), - ) - @test alpine.linear_terms[lk1][:y_idx] == 6911 - @test alpine.linear_terms[lk1][:id] == 3 - @test alpine.linear_terms[lk1][:y_type] == :(Cont) - lk2 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3467), (1.0, 16)])), - ) - @test alpine.linear_terms[lk2][:y_idx] == 6908 - @test alpine.linear_terms[lk2][:id] == 1 - @test alpine.linear_terms[lk2][:y_type] == :(Cont) - lk3 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}( - :coef_var, - Set(Any[(0.001548, 6903), (1.0, 7016), (1.0, 5702)]), - ), - ) - @test alpine.linear_terms[lk3][:y_idx] == 7017 - @test alpine.linear_terms[lk3][:id] == 67 - @test alpine.linear_terms[lk3][:y_type] == :(Cont) - lk4 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 5162), (1.0, 1711)])), - ) - @test alpine.linear_terms[lk4][:y_idx] == 7004 - @test alpine.linear_terms[lk4][:id] == 59 - @test alpine.linear_terms[lk4][:y_type] == :(Cont) - lk5 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}( - :coef_var, - Set(Any[(1.0, 7021), (0.001435, 6903), (1.0, 6002)]), - ), - ) - @test alpine.linear_terms[lk5][:y_idx] == 7022 - @test alpine.linear_terms[lk5][:id] == 70 - @test alpine.linear_terms[lk5][:y_type] == :(Cont) - lk6 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6935), (1.0, 166)])), - ) - @test alpine.linear_terms[lk6][:y_idx] == 6936 - @test alpine.linear_terms[lk6][:id] == 18 - @test alpine.linear_terms[lk6][:y_type] == :(Cont) - lk7 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}( - :coef_var, - Set(Any[(1.0, 4262), (0.00247, 6903), (1.0, 6981)]), - ), - ) - @test alpine.linear_terms[lk7][:y_idx] == 6982 - @test alpine.linear_terms[lk7][:id] == 46 - @test alpine.linear_terms[lk7][:y_type] == :(Cont) - lk8 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 7005), (1.0, 1711)])), - ) - @test alpine.linear_terms[lk8][:y_idx] == 7006 - @test alpine.linear_terms[lk8][:id] == 60 - @test alpine.linear_terms[lk8][:y_type] == :(Cont) - lk9 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1951), (1.0, 5402)])), - ) - @test alpine.linear_terms[lk9][:y_idx] == 7009 - @test alpine.linear_terms[lk9][:id] == 62 - @test alpine.linear_terms[lk9][:y_type] == :(Cont) - lk10 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 226), (-1.0, 6945)])), - ) - @test alpine.linear_terms[lk10][:y_idx] == 6946 - @test alpine.linear_terms[lk10][:id] == 24 - @test alpine.linear_terms[lk10][:y_type] == :(Cont) - lk11 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 7030), (1.0, 3151)])), - ) - @test alpine.linear_terms[lk11][:y_idx] == 7031 - @test alpine.linear_terms[lk11][:id] == 75 - @test alpine.linear_terms[lk11][:y_type] == :(Cont) - lk12 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}( - :coef_var, - Set(Any[(1.0, 6991), (1.0, 4622), (0.002066, 6903)]), - ), - ) - @test alpine.linear_terms[lk12][:y_idx] == 6992 - @test alpine.linear_terms[lk12][:id] == 52 - @test alpine.linear_terms[lk12][:y_type] == :(Cont) - lk13 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}( - :coef_var, - Set(Any[(1.0, 7026), (1.0, 6302), (0.001323, 6903)]), - ), - ) - @test alpine.linear_terms[lk13][:y_idx] == 7027 - @test alpine.linear_terms[lk13][:id] == 73 - @test alpine.linear_terms[lk13][:y_type] == :(Cont) - lk14 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 46), (1.0, 3497)])), - ) - @test alpine.linear_terms[lk14][:y_idx] == 6914 - @test alpine.linear_terms[lk14][:id] == 5 - @test alpine.linear_terms[lk14][:y_type] == :(Cont) - lk15 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6960), (1.0, 391)])), - ) - @test alpine.linear_terms[lk15][:y_idx] == 6961 - @test alpine.linear_terms[lk15][:id] == 33 - @test alpine.linear_terms[lk15][:y_type] == :(Cont) - lk16 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 631), (-1.0, 6975)])), - ) - @test alpine.linear_terms[lk16][:y_idx] == 6976 - @test alpine.linear_terms[lk16][:id] == 42 - @test alpine.linear_terms[lk16][:y_type] == :(Cont) - lk17 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1351), (-1.0, 6995)])), - ) - @test alpine.linear_terms[lk17][:y_idx] == 6996 - @test alpine.linear_terms[lk17][:id] == 54 - @test alpine.linear_terms[lk17][:y_type] == :(Cont) - lk18 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3557), (1.0, 106)])), - ) - @test alpine.linear_terms[lk18][:y_idx] == 6924 - @test alpine.linear_terms[lk18][:id] == 11 - @test alpine.linear_terms[lk18][:y_type] == :(Cont) - lk19 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}( - :coef_var, - Set(Any[(1.0, 3647), (1.0, 6941), (0.004795, 6903)]), - ), - ) - @test alpine.linear_terms[lk19][:y_idx] == 6942 - @test alpine.linear_terms[lk19][:id] == 22 - @test alpine.linear_terms[lk19][:y_type] == :(Cont) - lk20 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3722), (1.0, 271)])), - ) - @test alpine.linear_terms[lk20][:y_idx] == 6949 - @test alpine.linear_terms[lk20][:id] == 26 - @test alpine.linear_terms[lk20][:y_type] == :(Cont) - lk21 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3647), (1.0, 196)])), - ) - @test alpine.linear_terms[lk21][:y_idx] == 6939 - @test alpine.linear_terms[lk21][:id] == 20 - @test alpine.linear_terms[lk21][:y_type] == :(Cont) - lk22 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}( - :coef_var, - Set(Any[(1.0, 3467), (1.0, 6911), (6.34e-6, 6903)]), - ), - ) - @test alpine.linear_terms[lk22][:y_idx] == 6912 - @test alpine.linear_terms[lk22][:id] == 4 - @test alpine.linear_terms[lk22][:y_type] == :(Cont) - lk23 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1531), (1.0, 4982)])), - ) - @test alpine.linear_terms[lk23][:y_idx] == 6999 - @test alpine.linear_terms[lk23][:id] == 56 - @test alpine.linear_terms[lk23][:y_type] == :(Cont) - lk24 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 106), (-1.0, 6925)])), - ) - @test alpine.linear_terms[lk24][:y_idx] == 6926 - @test alpine.linear_terms[lk24][:id] == 12 - @test alpine.linear_terms[lk24][:y_type] == :(Cont) - lk25 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 2251), (-1.0, 7015)])), - ) - @test alpine.linear_terms[lk25][:y_idx] == 7016 - @test alpine.linear_terms[lk25][:id] == 66 - @test alpine.linear_terms[lk25][:y_type] == :(Cont) - lk26 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}( - :coef_var, - Set(Any[(1.0, 6936), (0.004985, 6903), (1.0, 3617)]), - ), - ) - @test alpine.linear_terms[lk26][:y_idx] == 6937 - @test alpine.linear_terms[lk26][:id] == 19 - @test alpine.linear_terms[lk26][:y_type] == :(Cont) - lk27 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6915), (1.0, 46)])), - ) - @test alpine.linear_terms[lk27][:y_idx] == 6916 - @test alpine.linear_terms[lk27][:id] == 6 - @test alpine.linear_terms[lk27][:y_type] == :(Cont) - lk28 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}( - :coef_var, - Set(Any[(1.0, 3557), (0.005968, 6903), (1.0, 6926)]), - ), - ) - @test alpine.linear_terms[lk28][:y_idx] == 6927 - @test alpine.linear_terms[lk28][:id] == 13 - @test alpine.linear_terms[lk28][:y_type] == :(Cont) - lk29 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 271), (-1.0, 6950)])), - ) - @test alpine.linear_terms[lk29][:y_idx] == 6951 - @test alpine.linear_terms[lk29][:id] == 27 - @test alpine.linear_terms[lk29][:y_type] == :(Cont) - lk30 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}( - :coef_var, - Set(Any[(0.002971, 6903), (1.0, 6971), (1.0, 3962)]), - ), - ) - @test alpine.linear_terms[lk30][:y_idx] == 6972 - @test alpine.linear_terms[lk30][:id] == 40 - @test alpine.linear_terms[lk30][:y_type] == :(Cont) - lk31 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 511), (-1.0, 6970)])), - ) - @test alpine.linear_terms[lk31][:y_idx] == 6971 - @test alpine.linear_terms[lk31][:id] == 39 - @test alpine.linear_terms[lk31][:y_type] == :(Cont) - lk32 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}( - :coef_var, - Set(Any[(1.0, 7031), (1.0, 6602), (0.00121, 6903)]), - ), - ) - @test alpine.linear_terms[lk32][:y_idx] == 7032 - @test alpine.linear_terms[lk32][:id] == 76 - @test alpine.linear_terms[lk32][:y_type] == :(Cont) - lk33 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}( - :coef_var, - Set(Any[(0.00166, 6903), (1.0, 7011), (1.0, 5402)]), - ), - ) - @test alpine.linear_terms[lk33][:y_idx] == 7012 - @test alpine.linear_terms[lk33][:id] == 64 - @test alpine.linear_terms[lk33][:y_type] == :(Cont) - lk34 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, -0.003214), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 16)])), - ) - @test alpine.linear_terms[lk34][:y_idx] == 6910 - @test alpine.linear_terms[lk34][:id] == 2 - @test alpine.linear_terms[lk34][:y_type] == :(Cont) - lk35 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 7035), (1.0, 3451)])), - ) - @test alpine.linear_terms[lk35][:y_idx] == 7036 - @test alpine.linear_terms[lk35][:id] == 78 - @test alpine.linear_terms[lk35][:y_type] == :(Cont) - lk36 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 2551), (1.0, 6002)])), - ) - @test alpine.linear_terms[lk36][:y_idx] == 7019 - @test alpine.linear_terms[lk36][:id] == 68 - @test alpine.linear_terms[lk36][:y_type] == :(Cont) - lk37 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3842), (1.0, 391)])), - ) - @test alpine.linear_terms[lk37][:y_idx] == 6959 - @test alpine.linear_terms[lk37][:id] == 32 - @test alpine.linear_terms[lk37][:y_type] == :(Cont) - lk38 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}( - :coef_var, - Set(Any[(1.0, 6966), (0.00307, 6903), (1.0, 3902)]), - ), - ) - @test alpine.linear_terms[lk38][:y_idx] == 6967 - @test alpine.linear_terms[lk38][:id] == 37 - @test alpine.linear_terms[lk38][:y_type] == :(Cont) - lk39 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}( - :coef_var, - Set(Any[(1.0, 3722), (0.003829, 6903), (1.0, 6951)]), - ), - ) - @test alpine.linear_terms[lk39][:y_idx] == 6952 - @test alpine.linear_terms[lk39][:id] == 28 - @test alpine.linear_terms[lk39][:y_type] == :(Cont) - lk40 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 451), (1.0, 3902)])), - ) - @test alpine.linear_terms[lk40][:y_idx] == 6964 - @test alpine.linear_terms[lk40][:id] == 35 - @test alpine.linear_terms[lk40][:y_type] == :(Cont) - lk41 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}( - :coef_var, - Set(Any[(1.0, 7006), (1.0, 5162), (0.001713, 6903)]), - ), - ) - @test alpine.linear_terms[lk41][:y_idx] == 7007 - @test alpine.linear_terms[lk41][:id] == 61 - @test alpine.linear_terms[lk41][:y_type] == :(Cont) - lk42 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 811), (-1.0, 6980)])), - ) - @test alpine.linear_terms[lk42][:y_idx] == 6981 - @test alpine.linear_terms[lk42][:id] == 45 - @test alpine.linear_terms[lk42][:y_type] == :(Cont) - lk43 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}( - :coef_var, - Set(Any[(1.0, 7001), (1.0, 4982), (0.00173, 6903)]), - ), - ) - @test alpine.linear_terms[lk43][:y_idx] == 7002 - @test alpine.linear_terms[lk43][:id] == 58 - @test alpine.linear_terms[lk43][:y_type] == :(Cont) - lk44 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6920), (1.0, 76)])), - ) - @test alpine.linear_terms[lk44][:y_idx] == 6921 - @test alpine.linear_terms[lk44][:id] == 9 - @test alpine.linear_terms[lk44][:y_type] == :(Cont) - lk45 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 4622), (1.0, 1171)])), - ) - @test alpine.linear_terms[lk45][:y_idx] == 6989 - @test alpine.linear_terms[lk45][:id] == 50 - @test alpine.linear_terms[lk45][:y_type] == :(Cont) - lk46 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 991), (1.0, 4442)])), - ) - @test alpine.linear_terms[lk46][:y_idx] == 6984 - @test alpine.linear_terms[lk46][:id] == 47 - @test alpine.linear_terms[lk46][:y_type] == :(Cont) - lk47 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6930), (1.0, 136)])), - ) - @test alpine.linear_terms[lk47][:y_idx] == 6931 - @test alpine.linear_terms[lk47][:id] == 15 - @test alpine.linear_terms[lk47][:y_type] == :(Cont) - lk48 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}( - :coef_var, - Set(Any[(1.0, 4802), (0.001891, 6903), (1.0, 6996)]), - ), - ) - @test alpine.linear_terms[lk48][:y_idx] == 6997 - @test alpine.linear_terms[lk48][:id] == 55 - @test alpine.linear_terms[lk48][:y_type] == :(Cont) - lk49 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 511), (1.0, 3962)])), - ) - @test alpine.linear_terms[lk49][:y_idx] == 6969 - @test alpine.linear_terms[lk49][:id] == 38 - @test alpine.linear_terms[lk49][:y_type] == :(Cont) - lk50 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 811), (1.0, 4262)])), - ) - @test alpine.linear_terms[lk50][:y_idx] == 6979 - @test alpine.linear_terms[lk50][:id] == 44 - @test alpine.linear_terms[lk50][:y_type] == :(Cont) - lk51 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}( - :coef_var, - Set(Any[(0.01551, 6903), (1.0, 6916), (1.0, 3497)]), - ), - ) - @test alpine.linear_terms[lk51][:y_idx] == 6917 - @test alpine.linear_terms[lk51][:id] == 7 - @test alpine.linear_terms[lk51][:y_type] == :(Cont) - lk52 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 451), (-1.0, 6965)])), - ) - @test alpine.linear_terms[lk52][:y_idx] == 6966 - @test alpine.linear_terms[lk52][:id] == 36 - @test alpine.linear_terms[lk52][:y_type] == :(Cont) - lk53 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}( - :coef_var, - Set(Any[(0.005773, 6903), (1.0, 3587), (1.0, 6931)]), - ), - ) - @test alpine.linear_terms[lk53][:y_idx] == 6932 - @test alpine.linear_terms[lk53][:id] == 16 - @test alpine.linear_terms[lk53][:y_type] == :(Cont) - lk54 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 631), (1.0, 4082)])), - ) - @test alpine.linear_terms[lk54][:y_idx] == 6974 - @test alpine.linear_terms[lk54][:id] == 41 - @test alpine.linear_terms[lk54][:y_type] == :(Cont) - lk55 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 991), (-1.0, 6985)])), - ) - @test alpine.linear_terms[lk55][:y_idx] == 6986 - @test alpine.linear_terms[lk55][:id] == 48 - @test alpine.linear_terms[lk55][:y_type] == :(Cont) - lk56 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 4802), (1.0, 1351)])), - ) - @test alpine.linear_terms[lk56][:y_idx] == 6994 - @test alpine.linear_terms[lk56][:id] == 53 - @test alpine.linear_terms[lk56][:y_type] == :(Cont) - lk57 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}( - :coef_var, - Set(Any[(1.0, 6946), (0.004409, 6903), (1.0, 3677)]), - ), - ) - @test alpine.linear_terms[lk57][:y_idx] == 6947 - @test alpine.linear_terms[lk57][:id] == 25 - @test alpine.linear_terms[lk57][:y_type] == :(Cont) - lk58 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 2251), (1.0, 5702)])), - ) - @test alpine.linear_terms[lk58][:y_idx] == 7014 - @test alpine.linear_terms[lk58][:id] == 65 - @test alpine.linear_terms[lk58][:y_type] == :(Cont) - lk59 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 7020), (1.0, 2551)])), - ) - @test alpine.linear_terms[lk59][:y_idx] == 7021 - @test alpine.linear_terms[lk59][:id] == 69 - @test alpine.linear_terms[lk59][:y_type] == :(Cont) - lk60 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6940), (1.0, 196)])), - ) - @test alpine.linear_terms[lk60][:y_idx] == 6941 - @test alpine.linear_terms[lk60][:id] == 21 - @test alpine.linear_terms[lk60][:y_type] == :(Cont) - lk61 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}( - :coef_var, - Set(Any[(1.0, 3527), (1.0, 6921), (0.008919, 6903)]), - ), - ) - @test alpine.linear_terms[lk61][:y_idx] == 6922 - @test alpine.linear_terms[lk61][:id] == 10 - @test alpine.linear_terms[lk61][:y_type] == :(Cont) - lk62 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 7025), (1.0, 2851)])), - ) - @test alpine.linear_terms[lk62][:y_idx] == 7026 - @test alpine.linear_terms[lk62][:id] == 72 - @test alpine.linear_terms[lk62][:y_type] == :(Cont) - lk63 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}( - :coef_var, - Set(Any[(1.0, 6986), (1.0, 4442), (0.002252, 6903)]), - ), - ) - @test alpine.linear_terms[lk63][:y_idx] == 6987 - @test alpine.linear_terms[lk63][:id] == 49 - @test alpine.linear_terms[lk63][:y_type] == :(Cont) - lk64 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}( - :coef_var, - Set(Any[(0.002765, 6903), (1.0, 6976), (1.0, 4082)]), - ), - ) - @test alpine.linear_terms[lk64][:y_idx] == 6977 - @test alpine.linear_terms[lk64][:id] == 43 - @test alpine.linear_terms[lk64][:y_type] == :(Cont) - lk65 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}( - :coef_var, - Set(Any[(1.0, 6956), (0.003269, 6903), (1.0, 3782)]), - ), - ) - @test alpine.linear_terms[lk65][:y_idx] == 6957 - @test alpine.linear_terms[lk65][:id] == 31 - @test alpine.linear_terms[lk65][:y_type] == :(Cont) - lk66 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3587), (1.0, 136)])), - ) - @test alpine.linear_terms[lk66][:y_idx] == 6929 - @test alpine.linear_terms[lk66][:id] == 14 - @test alpine.linear_terms[lk66][:y_type] == :(Cont) - lk67 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 166), (1.0, 3617)])), - ) - @test alpine.linear_terms[lk67][:y_idx] == 6934 - @test alpine.linear_terms[lk67][:id] == 17 - @test alpine.linear_terms[lk67][:y_type] == :(Cont) - lk68 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 7010), (1.0, 1951)])), - ) - @test alpine.linear_terms[lk68][:y_idx] == 7011 - @test alpine.linear_terms[lk68][:id] == 63 - @test alpine.linear_terms[lk68][:y_type] == :(Cont) - lk69 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}( - :coef_var, - Set(Any[(1.0, 7036), (0.001098, 6903), (1.0, 6902)]), - ), - ) - @test alpine.linear_terms[lk69][:y_idx] == 7037 - @test alpine.linear_terms[lk69][:id] == 79 - @test alpine.linear_terms[lk69][:y_type] == :(Cont) - lk70 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3527), (1.0, 76)])), - ) - @test alpine.linear_terms[lk70][:y_idx] == 6919 - @test alpine.linear_terms[lk70][:id] == 8 - @test alpine.linear_terms[lk70][:y_type] == :(Cont) - lk71 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}( - :coef_var, - Set(Any[(1.0, 6961), (1.0, 3842), (0.00317, 6903)]), - ), - ) - @test alpine.linear_terms[lk71][:y_idx] == 6962 - @test alpine.linear_terms[lk71][:id] == 34 - @test alpine.linear_terms[lk71][:y_type] == :(Cont) - lk72 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6990), (1.0, 1171)])), - ) - @test alpine.linear_terms[lk72][:y_idx] == 6991 - @test alpine.linear_terms[lk72][:id] == 51 - @test alpine.linear_terms[lk72][:y_type] == :(Cont) - lk73 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3451), (1.0, 6902)])), - ) - @test alpine.linear_terms[lk73][:y_idx] == 7034 - @test alpine.linear_terms[lk73][:id] == 77 - @test alpine.linear_terms[lk73][:y_type] == :(Cont) - lk74 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6302), (1.0, 2851)])), - ) - @test alpine.linear_terms[lk74][:y_idx] == 7024 - @test alpine.linear_terms[lk74][:id] == 71 - @test alpine.linear_terms[lk74][:y_type] == :(Cont) - lk75 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1531), (-1.0, 7000)])), - ) - @test alpine.linear_terms[lk75][:y_idx] == 7001 - @test alpine.linear_terms[lk75][:id] == 57 - @test alpine.linear_terms[lk75][:y_type] == :(Cont) - lk76 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3151), (1.0, 6602)])), - ) - @test alpine.linear_terms[lk76][:y_idx] == 7029 - @test alpine.linear_terms[lk76][:id] == 74 - @test alpine.linear_terms[lk76][:y_type] == :(Cont) - lk77 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3782), (1.0, 331)])), - ) - @test alpine.linear_terms[lk77][:y_idx] == 6954 - @test alpine.linear_terms[lk77][:id] == 29 - @test alpine.linear_terms[lk77][:y_type] == :(Cont) - lk78 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6955), (1.0, 331)])), - ) - @test alpine.linear_terms[lk78][:y_idx] == 6956 - @test alpine.linear_terms[lk78][:id] == 30 - @test alpine.linear_terms[lk78][:y_type] == :(Cont) - lk79 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 226), (1.0, 3677)])), - ) - @test alpine.linear_terms[lk79][:y_idx] == 6944 - @test alpine.linear_terms[lk79][:id] == 23 - @test alpine.linear_terms[lk79][:y_type] == :(Cont) - end -end - -@testset "Expression Parsing || Basic Multiplication Operators (Machine Generated for diffs)" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "minlp_solver" => JUNIPER, - "mip_solver" => HIGHS, - "log_level" => 100, - ) - - m = operator_basic(solver = test_solver) - JuMP.set_optimize_hook(m, MOI.Utilities.attach_optimizer) - JuMP.optimize!(m) - JuMP.set_optimize_hook(m, nothing) - alpine = JuMP.backend(m).optimizer.model - Alpine.load!(alpine) - - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4])]][:y_idx] == 31 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4])]][:id] == 27 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4])]][:lifted_constr_ref] == - :(x[31] == x[3] * x[4]) - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[76])]][:y_idx] == 83 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[76])]][:id] == 79 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[76])]][:lifted_constr_ref] == - :(x[83] == x[4] * x[5] * x[76]) - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[76])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[2])]][:y_idx] == 9 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[2])]][:id] == 5 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[2])]][:lifted_constr_ref] == - :(x[9] == (*)(x[2])) - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[2])]][:nonlinear_type] == :MONOMIAL - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7])]][:y_idx] == 19 - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7])]][:id] == 15 - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7])]][:lifted_constr_ref] == - :(x[19] == x[5] * x[7]) - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[31])]][:y_idx] == 32 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[31])]][:id] == 28 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[31])]][:lifted_constr_ref] == - :(x[32] == x[2] * x[31]) - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[31])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10])]][:y_idx] == 49 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10])]][:id] == 45 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10])]][:lifted_constr_ref] == - :(x[49] == x[1] * x[2] * x[10]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5]), :(x[9])]][:y_idx] == 50 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5]), :(x[9])]][:id] == 46 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5]), :(x[9])]][:lifted_constr_ref] == - :(x[50] == x[3] * x[5] * x[9]) - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5]), :(x[9])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[47])]][:y_idx] == 69 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[47])]][:id] == 65 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[47])]][:lifted_constr_ref] == - :(x[69] == x[4] * x[47]) - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[47])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[4])]][:y_idx] == 28 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[4])]][:id] == 24 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[4])]][:lifted_constr_ref] == - :(x[28] == (*)(x[4])) - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[4])]][:nonlinear_type] == :MONOMIAL - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[10])]][:y_idx] == 37 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[10])]][:id] == 33 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[10])]][:lifted_constr_ref] == - :(x[37] == x[4] * x[10]) - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[10])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[1])]][:y_idx] == 5 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[1])]][:id] == 1 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[1])]][:lifted_constr_ref] == - :(x[5] == (*)(x[1])) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[1])]][:nonlinear_type] == :MONOMIAL - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[95])]][:y_idx] == 96 - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[95])]][:id] == 92 - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[95])]][:lifted_constr_ref] == - :(x[96] == x[5] * x[95]) - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[95])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[40])]][:y_idx] == 41 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[40])]][:id] == 37 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[40])]][:lifted_constr_ref] == - :(x[41] == x[2] * x[40]) - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[40])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10])]][:y_idx] == 26 - @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10])]][:id] == 22 - @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10])]][:lifted_constr_ref] == - :(x[26] == x[6] * x[10]) - @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[78]), :(x[28])]][:y_idx] == 84 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[78]), :(x[28])]][:id] == 80 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[78]), :(x[28])]][:lifted_constr_ref] == - :(x[84] == x[1] * x[78] * x[28]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[78]), :(x[28])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[43])]][:y_idx] == 58 - @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[43])]][:id] == 54 - @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[43])]][:lifted_constr_ref] == - :(x[58] == x[6] * x[43]) - @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[43])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[6]), :(x[10])]][:y_idx] == 106 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[6]), :(x[10])]][:id] == 102 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[6]), :(x[10])]][:lifted_constr_ref] == - :(x[106] == x[4] * x[6] * x[10]) - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[6]), :(x[10])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4]), :(x[10])]][:y_idx] == 90 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4]), :(x[10])]][:id] == 86 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4]), :(x[10])]][:lifted_constr_ref] == - :(x[90] == x[2] * x[4] * x[10]) - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4]), :(x[10])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[41])]][:y_idx] == 42 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[41])]][:id] == 38 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[41])]][:lifted_constr_ref] == - :(x[42] == x[1] * x[41]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[41])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[37])]][:y_idx] == 38 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[37])]][:id] == 34 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[37])]][:lifted_constr_ref] == - :(x[38] == x[2] * x[37]) - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[37])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[85])]][:y_idx] == 87 - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[85])]][:id] == 83 - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[85])]][:lifted_constr_ref] == - :(x[87] == x[5] * x[85]) - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[85])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5]), :(x[28])]][:y_idx] == 66 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5]), :(x[28])]][:id] == 62 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5]), :(x[28])]][:lifted_constr_ref] == - :(x[66] == x[2] * x[3] * x[5] * x[28]) - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5]), :(x[28])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10])]][:y_idx] == 53 - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10])]][:id] == 49 - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10])]][:lifted_constr_ref] == - :(x[53] == x[5] * x[9] * x[10]) - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6]), :(x[28])]][:y_idx] == 107 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6]), :(x[28])]][:id] == 103 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6]), :(x[28])]][:lifted_constr_ref] == - :(x[107] == x[3] * x[6] * x[28]) - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6]), :(x[28])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5])]][:y_idx] == 17 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5])]][:id] == 13 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5])]][:lifted_constr_ref] == - :(x[17] == x[2] * x[5]) - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[37])]][:y_idx] == 57 - @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[37])]][:id] == 53 - @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[37])]][:lifted_constr_ref] == - :(x[57] == x[6] * x[37]) - @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[37])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7]), :(x[28])]][:y_idx] == 81 - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7]), :(x[28])]][:id] == 77 - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7]), :(x[28])]][:lifted_constr_ref] == - :(x[81] == x[5] * x[7] * x[28]) - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7]), :(x[28])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[38])]][:y_idx] == 39 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[38])]][:id] == 35 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[38])]][:lifted_constr_ref] == - :(x[39] == x[1] * x[38]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[38])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[9])]][:y_idx] == 48 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[9])]][:id] == 44 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[9])]][:lifted_constr_ref] == - :(x[48] == x[1] * x[3] * x[9]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[9])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[23])]][:y_idx] == 24 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[23])]][:id] == 20 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[23])]][:lifted_constr_ref] == - :(x[24] == x[4] * x[23]) - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[23])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[17])]][:y_idx] == 23 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[17])]][:id] == 19 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[17])]][:lifted_constr_ref] == - :(x[23] == x[3] * x[17]) - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[17])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[10])]][:y_idx] == 51 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[10])]][:id] == 47 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[10])]][:lifted_constr_ref] == - :(x[51] == x[1] * x[9] * x[10]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[10])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[7])]][:y_idx] == 75 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[7])]][:id] == 71 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[7])]][:lifted_constr_ref] == - :(x[75] == x[4] * x[5] * x[7]) - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[7])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[28])]][:y_idx] == 95 - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[28])]][:id] == 91 - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[28])]][:lifted_constr_ref] == - :(x[95] == x[9] * x[10] * x[28]) - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[28])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10])]][:y_idx] == 11 - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10])]][:id] == 7 - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10])]][:lifted_constr_ref] == - :(x[11] == x[9] * x[10]) - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[37])]][:y_idx] == 100 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[37])]][:id] == 96 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[37])]][:lifted_constr_ref] == - :(x[100] == x[1] * x[2] * x[37]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[37])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4]), :(x[5])]][:y_idx] == 62 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4]), :(x[5])]][:id] == 58 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4]), :(x[5])]][:lifted_constr_ref] == - :(x[62] == x[2] * x[3] * x[4] * x[5]) - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4]), :(x[5])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[9]), :(x[10])]][:y_idx] == 65 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[9]), :(x[10])]][:id] == 61 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[9]), :(x[10])]][:lifted_constr_ref] == - :(x[65] == x[1] * x[4] * x[9] * x[10]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[9]), :(x[10])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7]), :(x[28])]][:y_idx] == 80 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7]), :(x[28])]][:id] == 76 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7]), :(x[28])]][:lifted_constr_ref] == - :(x[80] == x[1] * x[7] * x[28]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7]), :(x[28])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3])]][:y_idx] == 46 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3])]][:id] == 42 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3])]][:lifted_constr_ref] == - :(x[46] == x[1] * x[2] * x[3]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[40])]][:y_idx] == 59 - @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[40])]][:id] == 55 - @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[40])]][:lifted_constr_ref] == - :(x[59] == x[17] * x[40]) - @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[40])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[85])]][:y_idx] == 86 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[85])]][:id] == 82 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[85])]][:lifted_constr_ref] == - :(x[86] == x[1] * x[85]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[85])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[31])]][:y_idx] == 97 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[31])]][:id] == 93 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[31])]][:lifted_constr_ref] == - :(x[97] == x[1] * x[2] * x[31]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[31])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[28])]][:y_idx] == 29 - @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[28])]][:id] == 25 - @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[28])]][:lifted_constr_ref] == - :(x[29] == x[13] * x[28]) - @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[28])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[28])]][:y_idx] == 92 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[28])]][:id] == 88 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[28])]][:lifted_constr_ref] == - :(x[92] == x[2] * x[3] * x[28]) - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[28])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9])]][:y_idx] == 20 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9])]][:id] == 16 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9])]][:lifted_constr_ref] == - :(x[20] == x[1] * x[9]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10]), :(x[28])]][:y_idx] == 109 - @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10]), :(x[28])]][:id] == 105 - @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10]), :(x[28])]][:lifted_constr_ref] == - :(x[109] == x[14] * x[10] * x[28]) - @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10]), :(x[28])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[92])]][:y_idx] == 93 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[92])]][:id] == 89 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[92])]][:lifted_constr_ref] == - :(x[93] == x[1] * x[92]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[92])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4])]][:y_idx] == 85 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4])]][:id] == 81 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4])]][:lifted_constr_ref] == - :(x[85] == x[2] * x[3] * x[4]) - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[11])]][:y_idx] == 16 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[11])]][:id] == 12 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[11])]][:lifted_constr_ref] == - :(x[16] == x[1] * x[11]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[11])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[21])]][:y_idx] == 25 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[21])]][:id] == 21 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[21])]][:lifted_constr_ref] == - :(x[25] == x[4] * x[21]) - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[21])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[53]), :(x[28])]][:y_idx] == 73 - @test alpine.nonconvex_terms[Expr[:(x[53]), :(x[28])]][:id] == 69 - @test alpine.nonconvex_terms[Expr[:(x[53]), :(x[28])]][:lifted_constr_ref] == - :(x[73] == x[53] * x[28]) - @test alpine.nonconvex_terms[Expr[:(x[53]), :(x[28])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[32])]][:y_idx] == 34 - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[32])]][:id] == 30 - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[32])]][:lifted_constr_ref] == - :(x[34] == x[5] * x[32]) - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[32])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[28])]][:y_idx] == 40 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[28])]][:id] == 36 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[28])]][:lifted_constr_ref] == - :(x[40] == x[3] * x[28]) - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[28])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10]), :(x[28])]][:y_idx] == 67 - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10]), :(x[28])]][:id] == 63 - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10]), :(x[28])]][:lifted_constr_ref] == - :(x[67] == x[5] * x[9] * x[10] * x[28]) - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10]), :(x[28])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[43])]][:y_idx] == 102 - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[43])]][:id] == 98 - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[43])]][:lifted_constr_ref] == - :(x[102] == x[5] * x[9] * x[43]) - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[43])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[26])]][:y_idx] == 27 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[26])]][:id] == 23 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[26])]][:lifted_constr_ref] == - :(x[27] == x[4] * x[26]) - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[26])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[20]), :(x[31])]][:y_idx] == 56 - @test alpine.nonconvex_terms[Expr[:(x[20]), :(x[31])]][:id] == 52 - @test alpine.nonconvex_terms[Expr[:(x[20]), :(x[31])]][:lifted_constr_ref] == - :(x[56] == x[20] * x[31]) - @test alpine.nonconvex_terms[Expr[:(x[20]), :(x[31])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[4]), :(x[9])]][:y_idx] == 63 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[4]), :(x[9])]][:id] == 59 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[4]), :(x[9])]][:lifted_constr_ref] == - :(x[63] == x[1] * x[3] * x[4] * x[9]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[4]), :(x[9])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10])]][:y_idx] == 15 - @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10])]][:id] == 11 - @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10])]][:lifted_constr_ref] == - :(x[15] == x[14] * x[10]) - @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[76])]][:y_idx] == 77 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[76])]][:id] == 73 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[76])]][:lifted_constr_ref] == - :(x[77] == x[1] * x[4] * x[76]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[76])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[88])]][:y_idx] == 89 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[88])]][:id] == 85 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[88])]][:lifted_constr_ref] == - :(x[89] == x[1] * x[88]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[88])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[90])]][:y_idx] == 94 - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[90])]][:id] == 90 - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[90])]][:lifted_constr_ref] == - :(x[94] == x[5] * x[90]) - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[90])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10]), :(x[28])]][:y_idx] == 108 - @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10]), :(x[28])]][:id] == 104 - @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10]), :(x[28])]][:lifted_constr_ref] == - :(x[108] == x[6] * x[10] * x[28]) - @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10]), :(x[28])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[48])]][:y_idx] == 70 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[48])]][:id] == 66 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[48])]][:lifted_constr_ref] == - :(x[70] == x[4] * x[48]) - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[48])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[31])]][:y_idx] == 54 - @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[31])]][:id] == 50 - @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[31])]][:lifted_constr_ref] == - :(x[54] == x[6] * x[31]) - @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[31])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[31])]][:y_idx] == 99 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[31])]][:id] == 95 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[31])]][:lifted_constr_ref] == - :(x[99] == x[1] * x[9] * x[31]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[31])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[35])]][:y_idx] == 36 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[35])]][:id] == 32 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[35])]][:lifted_constr_ref] == - :(x[36] == x[1] * x[35]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[35])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9])]][:y_idx] == 14 - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9])]][:id] == 10 - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9])]][:lifted_constr_ref] == - :(x[14] == x[5] * x[9]) - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[13])]][:y_idx] == 22 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[13])]][:id] == 18 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[13])]][:lifted_constr_ref] == - :(x[22] == x[4] * x[13]) - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[13])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10]), :(x[28])]][:y_idx] == 64 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10]), :(x[28])]][:id] == 60 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10]), :(x[28])]][:lifted_constr_ref] == - :(x[64] == x[1] * x[2] * x[10] * x[28]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10]), :(x[28])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[46]), :(x[28])]][:y_idx] == 72 - @test alpine.nonconvex_terms[Expr[:(x[46]), :(x[28])]][:id] == 68 - @test alpine.nonconvex_terms[Expr[:(x[46]), :(x[28])]][:lifted_constr_ref] == - :(x[72] == x[46] * x[28]) - @test alpine.nonconvex_terms[Expr[:(x[46]), :(x[28])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[31])]][:y_idx] == 55 - @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[31])]][:id] == 51 - @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[31])]][:lifted_constr_ref] == - :(x[55] == x[17] * x[31]) - @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[31])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[31])]][:y_idx] == 98 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[31])]][:id] == 94 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[31])]][:lifted_constr_ref] == - :(x[98] == x[2] * x[5] * x[31]) - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[31])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[28])]][:y_idx] == 43 - @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[28])]][:id] == 39 - @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[28])]][:lifted_constr_ref] == - :(x[43] == x[10] * x[28]) - @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[28])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[10])]][:y_idx] == 78 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[10])]][:id] == 74 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[10])]][:lifted_constr_ref] == - :(x[78] == x[2] * x[10]) - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[10])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[10])]][:y_idx] == 52 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[10])]][:id] == 48 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[10])]][:lifted_constr_ref] == - :(x[52] == x[2] * x[5] * x[10]) - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[10])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[90])]][:y_idx] == 91 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[90])]][:id] == 87 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[90])]][:lifted_constr_ref] == - :(x[91] == x[1] * x[90]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[90])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[17])]][:y_idx] == 104 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[17])]][:id] == 100 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[17])]][:lifted_constr_ref] == - :(x[104] == x[3] * x[4] * x[17]) - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[17])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[9])]][:y_idx] == 76 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[9])]][:id] == 72 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[9])]][:lifted_constr_ref] == - :(x[76] == x[3] * x[9]) - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[9])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[78])]][:y_idx] == 79 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[78])]][:id] == 75 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[78])]][:lifted_constr_ref] == - :(x[79] == x[1] * x[4] * x[78]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[78])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[3])]][:y_idx] == 10 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[3])]][:id] == 6 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[3])]][:lifted_constr_ref] == - :(x[10] == (*)(x[3])) - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[3])]][:nonlinear_type] == :MONOMIAL - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[49])]][:y_idx] == 71 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[49])]][:id] == 67 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[49])]][:lifted_constr_ref] == - :(x[71] == x[4] * x[49]) - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[49])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[9])]][:y_idx] == 88 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[9])]][:id] == 84 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[9])]][:lifted_constr_ref] == - :(x[88] == x[3] * x[4] * x[9]) - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[9])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[15]), :(x[28])]][:y_idx] == 30 - @test alpine.nonconvex_terms[Expr[:(x[15]), :(x[28])]][:id] == 26 - @test alpine.nonconvex_terms[Expr[:(x[15]), :(x[28])]][:lifted_constr_ref] == - :(x[30] == x[15] * x[28]) - @test alpine.nonconvex_terms[Expr[:(x[15]), :(x[28])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[46])]][:y_idx] == 68 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[46])]][:id] == 64 - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[46])]][:lifted_constr_ref] == - :(x[68] == x[4] * x[46]) - @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[46])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[11])]][:y_idx] == 12 - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[11])]][:id] == 8 - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[11])]][:lifted_constr_ref] == - :(x[12] == x[5] * x[11]) - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[11])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[7])]][:y_idx] == 74 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[7])]][:id] == 70 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[7])]][:lifted_constr_ref] == - :(x[74] == x[1] * x[4] * x[7]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[7])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[20])]][:y_idx] == 105 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[20])]][:id] == 101 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[20])]][:lifted_constr_ref] == - :(x[105] == x[3] * x[4] * x[20]) - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[20])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[11])]][:y_idx] == 82 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[11])]][:id] == 78 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[11])]][:lifted_constr_ref] == - :(x[82] == x[1] * x[4] * x[11]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[11])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[43])]][:y_idx] == 44 - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[43])]][:id] == 40 - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[43])]][:lifted_constr_ref] == - :(x[44] == x[9] * x[43]) - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[43])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:y_idx] == 61 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:id] == 57 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:lifted_constr_ref] == - :(x[61] == x[1] * x[2] * x[3] * x[4]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[10])]][:y_idx] == 18 - @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[10])]][:id] == 14 - @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[10])]][:lifted_constr_ref] == - :(x[18] == x[17] * x[10]) - @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[10])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7])]][:y_idx] == 8 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7])]][:id] == 4 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7])]][:lifted_constr_ref] == - :(x[8] == x[1] * x[7]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2])]][:y_idx] == 6 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2])]][:id] == 2 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2])]][:lifted_constr_ref] == - :(x[6] == x[1] * x[2]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[40])]][:y_idx] == 101 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[40])]][:id] == 97 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[40])]][:lifted_constr_ref] == - :(x[101] == x[1] * x[2] * x[40]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[40])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[37])]][:y_idx] == 60 - @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[37])]][:id] == 56 - @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[37])]][:lifted_constr_ref] == - :(x[60] == x[17] * x[37]) - @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[37])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[6])]][:y_idx] == 103 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[6])]][:id] == 99 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[6])]][:lifted_constr_ref] == - :(x[103] == x[3] * x[4] * x[6]) - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[6])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3])]][:y_idx] == 7 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3])]][:id] == 3 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3])]][:lifted_constr_ref] == - :(x[7] == x[2] * x[3]) - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5])]][:y_idx] == 47 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5])]][:id] == 43 - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5])]][:lifted_constr_ref] == - :(x[47] == x[2] * x[3] * x[5]) - @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6])]][:y_idx] == 13 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6])]][:id] == 9 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6])]][:lifted_constr_ref] == - :(x[13] == x[3] * x[6]) - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[31])]][:y_idx] == 35 - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[31])]][:id] == 31 - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[31])]][:lifted_constr_ref] == - :(x[35] == x[9] * x[31]) - @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[31])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[32])]][:y_idx] == 33 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[32])]][:id] == 29 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[32])]][:lifted_constr_ref] == - :(x[33] == x[1] * x[32]) - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[32])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[20])]][:y_idx] == 21 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[20])]][:id] == 17 - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[20])]][:lifted_constr_ref] == - :(x[21] == x[3] * x[20]) - @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[20])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[44])]][:y_idx] == 45 - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[44])]][:id] == 41 - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[44])]][:lifted_constr_ref] == - :(x[45] == x[5] * x[44]) - @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[44])]][:nonlinear_type] == :BILINEAR - - @test alpine.bounding_constr_mip[1][:rhs] == 1.0 - @test alpine.bounding_constr_mip[1][:vars] == Any[:(x[5])] - @test alpine.bounding_constr_mip[1][:coefs] == Any[1.0] - @test alpine.bounding_constr_mip[1][:sense] == :(>=) - @test alpine.bounding_constr_mip[1][:cnt] == 1 - @test alpine.bounding_constr_mip[2][:rhs] == 1.0 - @test alpine.bounding_constr_mip[2][:vars] == Any[:(x[6])] - @test alpine.bounding_constr_mip[2][:coefs] == Any[1.0] - @test alpine.bounding_constr_mip[2][:sense] == :(<=) - @test alpine.bounding_constr_mip[2][:cnt] == 1 - @test alpine.bounding_constr_mip[3][:rhs] == 1.0 - @test alpine.bounding_constr_mip[3][:vars] == Any[:(x[5]), :(x[7])] - @test alpine.bounding_constr_mip[3][:coefs] == Any[1.0, 1.0] - @test alpine.bounding_constr_mip[3][:sense] == :(<=) - @test alpine.bounding_constr_mip[3][:cnt] == 2 - @test alpine.bounding_constr_mip[4][:rhs] == 1.0 - @test alpine.bounding_constr_mip[4][:vars] == Any[:(x[8])] - @test alpine.bounding_constr_mip[4][:coefs] == Any[1.0] - @test alpine.bounding_constr_mip[4][:sense] == :(>=) - @test alpine.bounding_constr_mip[4][:cnt] == 1 - @test alpine.bounding_constr_mip[5][:rhs] == 1.0 - @test alpine.bounding_constr_mip[5][:vars] == Any[:(x[12])] - @test alpine.bounding_constr_mip[5][:coefs] == Any[1.0] - @test alpine.bounding_constr_mip[5][:sense] == :(<=) - @test alpine.bounding_constr_mip[5][:cnt] == 1 - @test alpine.bounding_constr_mip[6][:rhs] == 1.0 - @test alpine.bounding_constr_mip[6][:vars] == Any[:(x[13])] - @test alpine.bounding_constr_mip[6][:coefs] == Any[1.0] - @test alpine.bounding_constr_mip[6][:sense] == :(>=) - @test alpine.bounding_constr_mip[6][:cnt] == 1 - @test alpine.bounding_constr_mip[7][:rhs] == 1.0 - @test alpine.bounding_constr_mip[7][:vars] == Any[:(x[15])] - @test alpine.bounding_constr_mip[7][:coefs] == Any[1.0] - @test alpine.bounding_constr_mip[7][:sense] == :(<=) - @test alpine.bounding_constr_mip[7][:cnt] == 1 - @test alpine.bounding_constr_mip[8][:rhs] == 1.0 - @test alpine.bounding_constr_mip[8][:vars] == Any[:(x[16])] - @test alpine.bounding_constr_mip[8][:coefs] == Any[1.0] - @test alpine.bounding_constr_mip[8][:sense] == :(>=) - @test alpine.bounding_constr_mip[8][:cnt] == 1 - @test alpine.bounding_constr_mip[9][:rhs] == 1.0 - @test alpine.bounding_constr_mip[9][:vars] == Any[:(x[18])] - @test alpine.bounding_constr_mip[9][:coefs] == Any[1.0] - @test alpine.bounding_constr_mip[9][:sense] == :(<=) - @test alpine.bounding_constr_mip[9][:cnt] == 1 - @test alpine.bounding_constr_mip[10][:rhs] == 1.0 - @test alpine.bounding_constr_mip[10][:vars] == Any[:(x[19])] - @test alpine.bounding_constr_mip[10][:coefs] == Any[1.0] - @test alpine.bounding_constr_mip[10][:sense] == :(>=) - @test alpine.bounding_constr_mip[10][:cnt] == 1 - @test alpine.bounding_constr_mip[11][:rhs] == 1.0 - @test alpine.bounding_constr_mip[11][:vars] == Any[:(x[21])] - @test alpine.bounding_constr_mip[11][:coefs] == Any[1.0] - @test alpine.bounding_constr_mip[11][:sense] == :(<=) - @test alpine.bounding_constr_mip[11][:cnt] == 1 - @test alpine.bounding_constr_mip[12][:rhs] == 1.0 - @test alpine.bounding_constr_mip[12][:vars] == Any[:(x[22])] - @test alpine.bounding_constr_mip[12][:coefs] == Any[1.0] - @test alpine.bounding_constr_mip[12][:sense] == :(>=) - @test alpine.bounding_constr_mip[12][:cnt] == 1 - @test alpine.bounding_constr_mip[13][:rhs] == 1.0 - @test alpine.bounding_constr_mip[13][:vars] == Any[:(x[24])] - @test alpine.bounding_constr_mip[13][:coefs] == Any[1.0] - @test alpine.bounding_constr_mip[13][:sense] == :(<=) - @test alpine.bounding_constr_mip[13][:cnt] == 1 - @test alpine.bounding_constr_mip[14][:rhs] == 1.0 - @test alpine.bounding_constr_mip[14][:vars] == Any[:(x[25])] - @test alpine.bounding_constr_mip[14][:coefs] == Any[1.0] - @test alpine.bounding_constr_mip[14][:sense] == :(>=) - @test alpine.bounding_constr_mip[14][:cnt] == 1 - @test alpine.bounding_constr_mip[15][:rhs] == 1.0 - @test alpine.bounding_constr_mip[15][:vars] == Any[:(x[27])] - @test alpine.bounding_constr_mip[15][:coefs] == Any[1.0] - @test alpine.bounding_constr_mip[15][:sense] == :(<=) - @test alpine.bounding_constr_mip[15][:cnt] == 1 -end - -@testset "Expression Parsing || corner cases" begin - @testset "Corner Cases - 1 : sign convertor special case" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "minlp_solver" => JUNIPER, - "log_level" => 100, - ) - - m = Model(test_solver) - @variable(m, 0 <= x[1:5] <= 1, Bin) - @NLconstraint(m, x[1] + -x[2] >= 2) - @objective(m, Min, x[1] + x[2]) - alpine = _build(m) - - @test alpine.bounding_constr_mip[1][:rhs] == 2.0 - @test alpine.bounding_constr_mip[1][:vars] == Any[:(x[1]), :(x[2])] - @test alpine.bounding_constr_mip[1][:coefs] == Any[1.0, -1.0] - @test alpine.bounding_constr_mip[1][:sense] == :(>=) - @test alpine.bounding_constr_mip[1][:cnt] == 2 - end - - @testset "Corner Cases - 2 : full sub-expression" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "log_level" => 100, - ) - - m = Model(test_solver) - @variable(m, x[1:5] >= 0) - @NLconstraint(m, (x[1] + 10 + 4 * x[2] + 200) * 5 >= 2 * 5) - @constraint(m, x[1] + x[2] + 200 >= 2) - @objective(m, Min, x[1] + x[2]) - alpine = _build(m) - - @test alpine.bounding_constr_mip[1][:rhs] == -198.0 - @test alpine.bounding_constr_mip[1][:vars] == Any[:(x[1]), :(x[2])] - @test alpine.bounding_constr_mip[1][:coefs] == Any[1.0, 1.0] - @test alpine.bounding_constr_mip[1][:sense] == :(>=) - @test alpine.bounding_constr_mip[1][:cnt] == 2 - @test alpine.bounding_constr_mip[2][:rhs] == -1040.0 - @test alpine.bounding_constr_mip[2][:vars] == Any[:(x[1]), :(x[2])] - @test alpine.bounding_constr_mip[2][:coefs] == Any[5.0, 20.0] - @test alpine.bounding_constr_mip[2][:sense] == :(>=) - @test alpine.bounding_constr_mip[2][:cnt] == 2 - end - - @testset "Corner Cases - 2 : full sub-expression" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "log_level" => 100, - ) - - m = Model(test_solver) - @variable(m, x[1:5] >= 0) - @NLconstraint(m, (x[1] + 10 + 4 * x[2] + 200) * 5 >= 2 * 5) - @constraint(m, x[1] + x[2] + 200 >= 2) - @objective(m, Min, x[1] + x[2]) - alpine = _build(m) - - @test alpine.bounding_constr_mip[1][:rhs] == -198.0 - @test alpine.bounding_constr_mip[1][:vars] == Any[:(x[1]), :(x[2])] - @test alpine.bounding_constr_mip[1][:coefs] == Any[1.0, 1.0] - @test alpine.bounding_constr_mip[1][:sense] == :(>=) - @test alpine.bounding_constr_mip[1][:cnt] == 2 - @test alpine.bounding_constr_mip[2][:rhs] == -1040.0 - @test alpine.bounding_constr_mip[2][:vars] == Any[:(x[1]), :(x[2])] - @test alpine.bounding_constr_mip[2][:coefs] == Any[5.0, 20.0] - @test alpine.bounding_constr_mip[2][:sense] == :(>=) - @test alpine.bounding_constr_mip[2][:cnt] == 2 - end -end - -@testset "Expression Parsing || Discrete Multilinear" begin - @testset "Expression Parsing || bmpl && binlin && binprod" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "minlp_solver" => JUNIPER, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "log_level" => 100, - ) - - m = bpml(solver = test_solver) - - alpine = _build(m) # Setup internal model - - @test length(keys(alpine.nonconvex_terms)) == 12 - - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[6])]][:y_idx] == 11 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2])]][:y_idx] == 12 - @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[6])]][:y_idx] == 13 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3])]][:y_idx] == 14 - @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[6])]][:y_idx] == 15 - @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[7])]][:y_idx] == 16 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[16])]][:y_idx] == 17 - @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[7]), :(x[8])]][:y_idx] == 18 - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[18])]][:y_idx] == 19 - @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[18])]][:y_idx] == 20 - @test alpine.nonconvex_terms[Expr[ - :(x[1]), - :(x[2]), - :(x[3]), - :(x[4]), - :(x[5]), - ]][:y_idx] == 21 - @test alpine.nonconvex_terms[Expr[ - :(x[6]), - :(x[7]), - :(x[9]), - :(x[10]), - :(x[6]), - ]][:y_idx] == 22 - - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[6])]][:nonlinear_type] == :BINLIN - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2])]][:nonlinear_type] == :BINPROD - @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[6])]][:nonlinear_type] == :BINLIN - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3])]][:nonlinear_type] == - :BINPROD - @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[6])]][:nonlinear_type] == :BINLIN - @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[7])]][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[16])]][:nonlinear_type] == :BINLIN - @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[7]), :(x[8])]][:nonlinear_type] == - :MULTILINEAR - @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[18])]][:nonlinear_type] == :BINLIN - @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[18])]][:nonlinear_type] == :BINLIN - @test alpine.nonconvex_terms[Expr[ - :(x[1]), - :(x[2]), - :(x[3]), - :(x[4]), - :(x[5]), - ]][:nonlinear_type] == :BINPROD - @test alpine.nonconvex_terms[Expr[ - :(x[6]), - :(x[7]), - :(x[9]), - :(x[10]), - :(x[6]), - ]][:nonlinear_type] == :MULTILINEAR - - @test length(alpine.var_type) == 22 - @test alpine.var_type[11] == :Cont - @test alpine.var_type[12] == :Bin - @test alpine.var_type[13] == :Cont - @test alpine.var_type[14] == :Bin - @test alpine.var_type[15] == :Cont - @test alpine.var_type[16] == :Cont - @test alpine.var_type[17] == :Cont - @test alpine.var_type[18] == :Cont - @test alpine.var_type[19] == :Cont - @test alpine.var_type[20] == :Cont - @test alpine.var_type[21] == :Bin - @test alpine.var_type[22] == :Cont - end - - @testset "Expression Parsing || bmpl && binlin && binprod with linear lifting and coefficients" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "minlp_solver" => JUNIPER, - "nlp_solver" => IPOPT, - "mip_solver" => HIGHS, - "log_level" => 100, - ) - - m = bmpl_linearlifting(solver = test_solver) - - alpine = _build(m) - - lk1 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1), (1.0, 17)])), - ) - lk2 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 11), (1.0, 12)])), - ) - lk3 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 7), (2.0, 6)])), - ) - lk4 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6), (1.0, 19)])), - ) - lk5 = Dict{Symbol,Any}( - Pair{Symbol,Any}(:sign, :+), - Pair{Symbol,Any}(:scalar, 0.0), - Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6), (1.0, 25)])), - ) - - @test haskey(alpine.linear_terms, lk1) - @test haskey(alpine.linear_terms, lk2) - @test haskey(alpine.linear_terms, lk3) - @test haskey(alpine.linear_terms, lk4) - @test haskey(alpine.linear_terms, lk5) - - @test alpine.linear_terms[lk1][:lifted_constr_ref] == :(x[20] == x[1] + x[17]) - @test alpine.linear_terms[lk2][:lifted_constr_ref] == :(x[13] == x[11] + x[12]) - @test alpine.linear_terms[lk3][:lifted_constr_ref] == :(x[15] == 2 * x[6] + x[7]) - @test alpine.linear_terms[lk4][:lifted_constr_ref] == :(x[21] == x[6] + x[19]) - @test alpine.linear_terms[lk5][:lifted_constr_ref] == :(x[26] == x[6] + x[25]) - - @test alpine.linear_terms[lk1][:y_idx] == 20 - @test alpine.linear_terms[lk2][:y_idx] == 13 - @test alpine.linear_terms[lk3][:y_idx] == 15 - @test alpine.linear_terms[lk4][:y_idx] == 21 - @test alpine.linear_terms[lk5][:y_idx] == 26 - - @test alpine.linear_terms[lk1][:y_type] == :Cont - @test alpine.linear_terms[lk2][:y_type] == :Cont - @test alpine.linear_terms[lk3][:y_type] == :Cont - @test alpine.linear_terms[lk4][:y_type] == :Cont - @test alpine.linear_terms[lk5][:y_type] == :Cont - - nlk1 = Expr[:(x[18]), :(x[7])] - nlk2 = Expr[:(x[6]), :(x[7]), :(x[8])] - nlk3 = Expr[:(x[7]), :(x[10])] - nlk4 = Expr[:(x[2]), :(x[26])] - nlk5 = Expr[:(x[1]), :(x[13])] - nlk6 = Expr[:(x[1]), :(x[15])] - nlk7 = Expr[:(x[2]), :(x[6])] - nlk8 = Expr[:(x[24]), :(x[23])] - nlk9 = Expr[:(x[1]), :(x[2])] - nlk10 = Expr[:(x[2]), :(x[3])] - nlk11 = Expr[:(x[20]), :(x[21])] - nlk12 = Expr[:(x[3]), :(x[4])] - - @test haskey(alpine.nonconvex_terms, nlk1) - @test haskey(alpine.nonconvex_terms, nlk2) - @test haskey(alpine.nonconvex_terms, nlk3) - @test haskey(alpine.nonconvex_terms, nlk4) - @test haskey(alpine.nonconvex_terms, nlk5) - @test haskey(alpine.nonconvex_terms, nlk6) - @test haskey(alpine.nonconvex_terms, nlk7) - @test haskey(alpine.nonconvex_terms, nlk8) - @test haskey(alpine.nonconvex_terms, nlk9) - @test haskey(alpine.nonconvex_terms, nlk10) - @test haskey(alpine.nonconvex_terms, nlk11) - @test haskey(alpine.nonconvex_terms, nlk12) - - @test alpine.nonconvex_terms[nlk1][:id] == 7 - @test alpine.nonconvex_terms[nlk2][:id] == 1 - @test alpine.nonconvex_terms[nlk3][:id] == 9 - @test alpine.nonconvex_terms[nlk4][:id] == 12 - @test alpine.nonconvex_terms[nlk5][:id] == 3 - @test alpine.nonconvex_terms[nlk6][:id] == 4 - @test alpine.nonconvex_terms[nlk7][:id] == 5 - @test alpine.nonconvex_terms[nlk8][:id] == 11 - @test alpine.nonconvex_terms[nlk9][:id] == 6 - @test alpine.nonconvex_terms[nlk10][:id] == 2 - @test alpine.nonconvex_terms[nlk11][:id] == 8 - @test alpine.nonconvex_terms[nlk12][:id] == 10 - - @test alpine.nonconvex_terms[nlk1][:y_type] == :Cont - @test alpine.nonconvex_terms[nlk2][:y_type] == :Cont - @test alpine.nonconvex_terms[nlk3][:y_type] == :Cont - @test alpine.nonconvex_terms[nlk4][:y_type] == :Cont - @test alpine.nonconvex_terms[nlk5][:y_type] == :Cont - @test alpine.nonconvex_terms[nlk6][:y_type] == :Cont - @test alpine.nonconvex_terms[nlk7][:y_type] == :Cont - @test alpine.nonconvex_terms[nlk8][:y_type] == :Cont - @test alpine.nonconvex_terms[nlk9][:y_type] == :Bin - @test alpine.nonconvex_terms[nlk10][:y_type] == :Bin - @test alpine.nonconvex_terms[nlk11][:y_type] == :Cont - @test alpine.nonconvex_terms[nlk12][:y_type] == :Bin - - @test alpine.nonconvex_terms[nlk1][:y_idx] == 19 - @test alpine.nonconvex_terms[nlk2][:y_idx] == 11 - @test alpine.nonconvex_terms[nlk3][:y_idx] == 23 - @test alpine.nonconvex_terms[nlk4][:y_idx] == 27 - @test alpine.nonconvex_terms[nlk5][:y_idx] == 14 - @test alpine.nonconvex_terms[nlk6][:y_idx] == 16 - @test alpine.nonconvex_terms[nlk7][:y_idx] == 17 - @test alpine.nonconvex_terms[nlk8][:y_idx] == 25 - @test alpine.nonconvex_terms[nlk9][:y_idx] == 18 - @test alpine.nonconvex_terms[nlk10][:y_idx] == 12 - @test alpine.nonconvex_terms[nlk11][:y_idx] == 22 - @test alpine.nonconvex_terms[nlk12][:y_idx] == 24 - - @test alpine.nonconvex_terms[nlk1][:nonlinear_type] == :BINLIN - @test alpine.nonconvex_terms[nlk2][:nonlinear_type] == :MULTILINEAR - @test alpine.nonconvex_terms[nlk3][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[nlk4][:nonlinear_type] == :BINLIN - @test alpine.nonconvex_terms[nlk5][:nonlinear_type] == :BINLIN - @test alpine.nonconvex_terms[nlk6][:nonlinear_type] == :BINLIN - @test alpine.nonconvex_terms[nlk7][:nonlinear_type] == :BINLIN - @test alpine.nonconvex_terms[nlk8][:nonlinear_type] == :BINLIN - @test alpine.nonconvex_terms[nlk9][:nonlinear_type] == :BINPROD - @test alpine.nonconvex_terms[nlk10][:nonlinear_type] == :BINPROD - @test alpine.nonconvex_terms[nlk11][:nonlinear_type] == :BILINEAR - @test alpine.nonconvex_terms[nlk12][:nonlinear_type] == :BINPROD - end -end +# @testset "Expression Parsing || bilinear || Affine || exprs.jl" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "log_level" => 100, +# ) + +# m = exprstest(solver = test_solver) + +# alpine = _build(m) + +# ex = alpine.bounding_constr_expr_mip[1] +# affdict = Alpine.expr_linear_to_affine(ex) +# @test affdict[:coefs] == [-1.0] +# @test affdict[:coefs] == alpine.bounding_constr_mip[1][:coefs] +# @test affdict[:vars] == [:(x[1])] +# @test affdict[:vars] == alpine.bounding_constr_mip[1][:vars] +# @test isapprox(affdict[:rhs], 109.0; atol = 1e-3) +# @test affdict[:rhs] == alpine.bounding_constr_mip[1][:rhs] +# @test affdict[:sense] == :(<=) +# @test affdict[:sense] == alpine.bounding_constr_mip[1][:sense] + +# ex = alpine.bounding_constr_expr_mip[2] +# affdict = Alpine.expr_linear_to_affine(ex) +# @test affdict[:coefs] == [3.0, 3.0, 3.0, 3.0] +# @test affdict[:coefs] == alpine.bounding_constr_mip[2][:coefs] +# @test affdict[:vars] == [:(x[8]), :(x[9]), :(x[10]), :(x[11])] +# @test affdict[:vars] == alpine.bounding_constr_mip[2][:vars] +# @test isapprox(affdict[:rhs], 111.0; atol = 1e-3) +# @test affdict[:rhs] == alpine.bounding_constr_mip[2][:rhs] +# @test affdict[:sense] == :(>=) +# @test affdict[:sense] == alpine.bounding_constr_mip[2][:sense] + +# ex = alpine.bounding_constr_expr_mip[3] +# affdict = Alpine.expr_linear_to_affine(ex) +# @test affdict[:coefs] == [-1.0, 20.0] +# @test affdict[:coefs] == alpine.bounding_constr_mip[3][:coefs] +# @test affdict[:vars] == [:(x[12]), :(x[13])] +# @test affdict[:vars] == alpine.bounding_constr_mip[3][:vars] +# @test isapprox(affdict[:rhs], 222.0; atol = 1e-3) +# @test affdict[:rhs] == alpine.bounding_constr_mip[3][:rhs] +# @test affdict[:sense] == :(>=) +# @test affdict[:sense] == alpine.bounding_constr_mip[3][:sense] + +# # 1.0 * x[12] - 115.0 >= 0.0 +# ex = alpine.bounding_constr_expr_mip[4] +# affdict = Alpine.expr_linear_to_affine(ex) +# @test affdict[:coefs] == [-1.0] +# @test affdict[:coefs] == alpine.bounding_constr_mip[4][:coefs] +# @test affdict[:vars] == [:(x[12])] +# @test affdict[:vars] == alpine.bounding_constr_mip[4][:vars] +# @test isapprox(affdict[:rhs], 115.0; atol = 1e-3) +# @test affdict[:rhs] == alpine.bounding_constr_mip[4][:rhs] +# @test affdict[:sense] == :(<=) +# @test affdict[:sense] == alpine.bounding_constr_mip[4][:sense] + +# # 1.0 * x[12] - 115.0 <= 0.0 +# ex = alpine.bounding_constr_expr_mip[5] +# affdict = Alpine.expr_linear_to_affine(ex) +# @test affdict[:coefs] == [1.0] +# @test affdict[:coefs] == alpine.bounding_constr_mip[5][:coefs] +# @test affdict[:vars] == [:(x[12])] +# @test affdict[:vars] == alpine.bounding_constr_mip[5][:vars] +# @test isapprox(affdict[:rhs], 115.0; atol = 1e-3) +# @test affdict[:rhs] == alpine.bounding_constr_mip[5][:rhs] +# @test affdict[:sense] == :(>=) +# @test affdict[:sense] == alpine.bounding_constr_mip[5][:sense] + +# # -1.0 * x[12] - 115.0 >= 0.0 +# ex = alpine.bounding_constr_expr_mip[6] +# affdict = Alpine.expr_linear_to_affine(ex) +# @test affdict[:coefs] == [-1.0] +# @test affdict[:coefs] == alpine.bounding_constr_mip[6][:coefs] +# @test affdict[:vars] == [:(x[12])] +# @test affdict[:vars] == alpine.bounding_constr_mip[6][:vars] +# @test isapprox(affdict[:rhs], 115.0; atol = 1e-3) +# @test affdict[:rhs] == alpine.bounding_constr_mip[6][:rhs] +# @test affdict[:sense] == :(<=) +# @test affdict[:sense] == alpine.bounding_constr_mip[6][:sense] + +# # (x[1] + 1.0 * x[14]) - 555.0 >= 0.0 +# ex = alpine.bounding_constr_expr_mip[7] +# affdict = Alpine.expr_linear_to_affine(ex) +# @test affdict[:coefs] == [1.0, 1.0] +# @test affdict[:coefs] == alpine.bounding_constr_mip[7][:coefs] +# @test affdict[:vars] == [:(x[1]), :(x[14])] +# @test affdict[:vars] == alpine.bounding_constr_mip[7][:vars] +# @test isapprox(affdict[:rhs], 555.0; atol = 1e-3) +# @test affdict[:rhs] == alpine.bounding_constr_mip[7][:rhs] +# @test affdict[:sense] == :(>=) +# @test affdict[:sense] == alpine.bounding_constr_mip[7][:sense] + +# # ((x[8] - 7.0 * x[9]) + x[10] + x[4]) - 6666.0 <= 0.0 +# ex = alpine.bounding_constr_expr_mip[8] +# affdict = Alpine.expr_linear_to_affine(ex) +# @test affdict[:coefs] == [1.0, -7.0, 1.0, 1.0] +# @test affdict[:coefs] == alpine.bounding_constr_mip[8][:coefs] +# @test affdict[:vars] == [:(x[8]), :(x[9]), :(x[10]), :(x[4])] +# @test affdict[:vars] == alpine.bounding_constr_mip[8][:vars] +# @test isapprox(affdict[:rhs], 6666.0; atol = 1e-3) +# @test affdict[:rhs] == alpine.bounding_constr_mip[8][:rhs] +# @test affdict[:sense] == :(<=) +# @test affdict[:sense] == alpine.bounding_constr_mip[8][:sense] + +# # ((13.0 * x[1] - x[2]) + 30.0 * x[3] + x[4]) - 77.0 >= 0.0 +# ex = alpine.bounding_constr_expr_mip[9] +# affdict = Alpine.expr_linear_to_affine(ex) +# @test affdict[:coefs] == [13.0, -1.0, 30.0, 1.0] +# @test affdict[:coefs] == alpine.bounding_constr_mip[9][:coefs] +# @test affdict[:vars] == [:(x[1]), :(x[2]), :(x[3]), :(x[4])] +# @test affdict[:vars] == alpine.bounding_constr_mip[9][:vars] +# @test isapprox(affdict[:rhs], 77.0; atol = 1e-3) +# @test affdict[:rhs] == alpine.bounding_constr_mip[9][:rhs] +# @test affdict[:sense] == :(>=) +# @test affdict[:sense] == alpine.bounding_constr_mip[9][:sense] +# end + +# @testset "Expression Parsing || bilinear || Affine || nlp1.jl" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "log_level" => 100, +# ) +# m = nlp1(solver = test_solver) + +# alpine = _build(m) + +# ex = alpine.bounding_constr_expr_mip[1] +# affdict = Alpine.expr_linear_to_affine(ex) +# @test affdict[:coefs] == [1.0] +# @test affdict[:coefs] == alpine.bounding_constr_mip[1][:coefs] +# @test affdict[:vars] == [:(x[5])] +# @test affdict[:vars] == alpine.bounding_constr_mip[1][:vars] +# @test isapprox(affdict[:rhs], 8.0; atol = 1e-3) +# @test affdict[:rhs] == alpine.bounding_constr_mip[1][:rhs] +# @test affdict[:sense] == :(>=) +# @test affdict[:sense] == alpine.bounding_constr_mip[1][:sense] +# end + +# @testset "Expression Parsing || bilinear || Affine || nlp3.jl" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "log_level" => 100, +# ) + +# m = nlp3(solver = test_solver) + +# alpine = _build(m) + +# ex = alpine.bounding_constr_expr_mip[1] +# affdict = Alpine.expr_linear_to_affine(ex) +# @test affdict[:coefs] == [0.0025, 0.0025] +# @test affdict[:coefs] == alpine.bounding_constr_mip[1][:coefs] +# @test affdict[:vars] == [:(x[4]), :(x[6])] +# @test affdict[:vars] == alpine.bounding_constr_mip[1][:vars] +# @test isapprox(affdict[:rhs], 1.0; atol = 1e-3) +# @test affdict[:rhs] == alpine.bounding_constr_mip[1][:rhs] +# @test affdict[:sense] == :(<=) +# @test affdict[:sense] == alpine.bounding_constr_mip[1][:sense] + +# ex = alpine.bounding_constr_expr_mip[2] +# affdict = Alpine.expr_linear_to_affine(ex) +# @test affdict[:coefs] == [-0.0025, 0.0025, 0.0025] +# @test affdict[:coefs] == alpine.bounding_constr_mip[2][:coefs] +# @test affdict[:vars] == [:(x[4]), :(x[5]), :(x[7])] +# @test affdict[:vars] == alpine.bounding_constr_mip[2][:vars] +# @test isapprox(affdict[:rhs], 1.0; atol = 1e-3) +# @test affdict[:rhs] == alpine.bounding_constr_mip[2][:rhs] +# @test affdict[:sense] == :(<=) +# @test affdict[:sense] == alpine.bounding_constr_mip[2][:sense] + +# ex = alpine.bounding_constr_expr_mip[3] +# affdict = Alpine.expr_linear_to_affine(ex) +# @test affdict[:coefs] == [-0.01, 0.01] +# @test affdict[:coefs] == alpine.bounding_constr_mip[3][:coefs] +# @test affdict[:vars] == [:(x[5]), :(x[8])] +# @test affdict[:vars] == alpine.bounding_constr_mip[3][:vars] +# @test isapprox(affdict[:rhs], 1.0; atol = 1e-3) +# @test affdict[:rhs] == alpine.bounding_constr_mip[3][:rhs] +# @test affdict[:sense] == :(<=) +# @test affdict[:sense] == alpine.bounding_constr_mip[3][:sense] + +# ex = alpine.bounding_constr_expr_mip[4] +# affdict = Alpine.expr_linear_to_affine(ex) +# @test (affdict[:coefs] .== [100.0, -1.0, 833.33252]) == [true, true, true] +# @test affdict[:coefs] == alpine.bounding_constr_mip[4][:coefs] +# @test affdict[:vars] == [:(x[1]), :(x[9]), :(x[4])] +# @test affdict[:vars] == alpine.bounding_constr_mip[4][:vars] +# @test isapprox(affdict[:rhs], 83333.333; atol = 1e-3) +# @test affdict[:rhs] == alpine.bounding_constr_mip[4][:rhs] +# @test affdict[:sense] == :(<=) +# @test affdict[:sense] == alpine.bounding_constr_mip[4][:sense] + +# ex = alpine.bounding_constr_expr_mip[5] +# affdict = Alpine.expr_linear_to_affine(ex) +# @test affdict[:coefs] == [1.0, -1.0, -1250.0, 1250.0] +# @test affdict[:coefs] == alpine.bounding_constr_mip[5][:coefs] +# @test affdict[:vars] == [:(x[10]), :(x[11]), :(x[4]), :(x[5])] +# @test affdict[:vars] == alpine.bounding_constr_mip[5][:vars] +# @test isapprox(affdict[:rhs], 0.0; atol = 1e-3) +# @test affdict[:rhs] == alpine.bounding_constr_mip[5][:rhs] +# @test affdict[:sense] == :(<=) +# @test affdict[:sense] == alpine.bounding_constr_mip[5][:sense] + +# ex = alpine.bounding_constr_expr_mip[6] +# affdict = Alpine.expr_linear_to_affine(ex) +# @test affdict[:coefs] == [1.0, -1.0, -2500.0] +# @test affdict[:coefs] == alpine.bounding_constr_mip[6][:coefs] +# @test affdict[:vars] == [:(x[12]), :(x[13]), :(x[5])] +# @test affdict[:vars] == alpine.bounding_constr_mip[6][:vars] +# @test isapprox(affdict[:rhs], -1.25e6; atol = 1e-3) +# @test affdict[:rhs] == alpine.bounding_constr_mip[6][:rhs] +# @test affdict[:sense] == :(<=) +# @test affdict[:sense] == alpine.bounding_constr_mip[6][:sense] +# end + +# @testset "Expression Parsing || bilinear || Simple || bi1.jl " begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "log_level" => 100, +# ) + +# m = operator_c(solver = test_solver) + +# alpine = _build(m) # Setup internal model + +# @test length(keys(alpine.nonconvex_terms)) == 8 +# @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 1), Expr(:ref, :x, 1)]) +# @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 2), Expr(:ref, :x, 2)]) +# @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 3), Expr(:ref, :x, 3)]) +# @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 4), Expr(:ref, :x, 4)]) +# @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 2), Expr(:ref, :x, 3)]) +# @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 3), Expr(:ref, :x, 4)]) + +# # TODO setup detailed check on this problem +# end +# @testset "Expression Parsing || bilinear || Complex || blend029.jl " begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "minlp_solver" => JUNIPER, +# "mip_solver" => HIGHS, +# "log_level" => 100, +# ) + +# m = blend029(solver = test_solver) + +# alpine = _build(m) # Setup internal model + +# @test length(keys(alpine.nonconvex_terms)) == 28 +# @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 37), Expr(:ref, :x, 55)]) +# @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 38), Expr(:ref, :x, 56)]) +# @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 37), Expr(:ref, :x, 26)]) +# @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 43), Expr(:ref, :x, 26)]) +# @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 47), Expr(:ref, :x, 59)]) +# @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 48), Expr(:ref, :x, 60)]) +# @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 47), Expr(:ref, :x, 36)]) + +# @test alpine.bounding_constr_mip[1][:rhs] == 1.0 +# @test alpine.bounding_constr_mip[1][:vars] == +# Any[:(x[1]), :(x[4]), :(x[7]), :(x[10]), :(x[49])] +# @test alpine.bounding_constr_mip[1][:sense] == :(==) +# @test alpine.bounding_constr_mip[1][:coefs] == Any[1.0, 1.0, 1.0, 1.0, 1.0] +# @test alpine.bounding_constr_mip[1][:cnt] == 5 + +# @test alpine.bounding_constr_mip[4][:rhs] == 0.1 +# @test alpine.bounding_constr_mip[4][:vars] == +# Any[:(x[4]), :(x[16]), :(x[25]), :(x[34]), :(x[58])] +# @test alpine.bounding_constr_mip[4][:sense] == :(==) +# @test alpine.bounding_constr_mip[4][:coefs] == Any[-1.0, -1.0, -1.0, 1.0, 1.0] +# @test alpine.bounding_constr_mip[4][:cnt] == 5 + +# @test alpine.bounding_constr_mip[17][:rhs] == -0.14 +# @test alpine.bounding_constr_mip[17][:vars] == +# Any[:(x[11]), :(x[23]), :(x[32]), :(x[64]), :(x[65])] +# @test alpine.bounding_constr_mip[17][:sense] == :(==) +# @test alpine.bounding_constr_mip[17][:coefs] == Any[-1.0, -1.0, -1.0, -1.0, 1.0] +# @test alpine.bounding_constr_mip[17][:cnt] == 5 + +# @test alpine.bounding_constr_mip[31][:rhs] == 0.0 +# @test alpine.bounding_constr_mip[31][:vars] == Any[:(x[13])] +# @test alpine.bounding_constr_mip[31][:sense] == :(>=) +# @test alpine.bounding_constr_mip[31][:coefs] == Any[1.0] +# @test alpine.bounding_constr_mip[31][:cnt] == 1 + +# @test alpine.bounding_constr_mip[145][:rhs] == 1.0 +# @test alpine.bounding_constr_mip[145][:vars] == Any[:(x[73])] +# @test alpine.bounding_constr_mip[145][:sense] == :(<=) +# @test alpine.bounding_constr_mip[145][:coefs] == Any[1.0] +# @test alpine.bounding_constr_mip[145][:cnt] == 1 + +# @test alpine.bounding_constr_mip[67][:rhs] == -1.0 +# @test alpine.bounding_constr_mip[67][:vars] == Any[:(x[73])] +# @test alpine.bounding_constr_mip[67][:sense] == :(>=) +# @test alpine.bounding_constr_mip[67][:coefs] == Any[-1.0] +# @test alpine.bounding_constr_mip[67][:cnt] == 1 + +# @test alpine.bounding_constr_mip[187][:rhs] == 1.0 +# @test alpine.bounding_constr_mip[187][:vars] == Any[:(x[79]), :(x[94])] +# @test alpine.bounding_constr_mip[187][:sense] == :(<=) +# @test alpine.bounding_constr_mip[187][:coefs] == Any[1.0, 1.0] +# @test alpine.bounding_constr_mip[187][:cnt] == 2 + +# @test alpine.bounding_constr_mip[202][:rhs] == 0.04 +# @test alpine.bounding_constr_mip[202][:vars] == +# Any[:(x[103]), :(x[1]), :(x[13]), :(x[25]), :(x[28]), :(x[31])] +# @test alpine.bounding_constr_mip[202][:sense] == :(==) +# @test alpine.bounding_constr_mip[202][:coefs] == Any[1.0, -0.6, -0.2, 0.2, 0.2, 0.2] +# @test alpine.bounding_constr_mip[202][:cnt] == 6 + +# @test alpine.nonconvex_terms[[:(x[37]), :(x[55])]][:id] == 1 +# @test alpine.nonconvex_terms[[:(x[37]), :(x[55])]][:lifted_var_ref] == :(x[103]) +# @test alpine.nonconvex_terms[[:(x[37]), :(x[55])]][:convexified] == false +# @test alpine.nonconvex_terms[[:(x[37]), :(x[55])]][:nonlinear_type] == :BILINEAR + +# @test alpine.bounding_constr_mip[206][:rhs] == 0.0 +# @test alpine.bounding_constr_mip[206][:vars] == +# Any[:(x[107]), :(x[103]), :(x[108]), :(x[109]), :(x[110]), :(x[2]), :(x[14])] +# @test alpine.bounding_constr_mip[206][:sense] == :(==) +# @test alpine.bounding_constr_mip[206][:coefs] == +# Any[1.0, -1.0, 1.0, 1.0, 1.0, -0.6, -0.2] +# @test alpine.bounding_constr_mip[206][:cnt] == 7 + +# @test alpine.nonconvex_terms[[:(x[38]), :(x[56])]][:id] == 5 +# @test alpine.nonconvex_terms[[:(x[38]), :(x[56])]][:lifted_var_ref] == :(x[107]) +# @test alpine.nonconvex_terms[[:(x[38]), :(x[56])]][:convexified] == false +# @test alpine.nonconvex_terms[[:(x[38]), :(x[56])]][:nonlinear_type] == :BILINEAR + +# @test alpine.nonconvex_terms[[:(x[37]), :(x[26])]][:id] == 6 +# @test alpine.nonconvex_terms[[:(x[37]), :(x[26])]][:lifted_var_ref] == :(x[108]) +# @test alpine.nonconvex_terms[[:(x[37]), :(x[26])]][:convexified] == false +# @test alpine.nonconvex_terms[[:(x[37]), :(x[26])]][:nonlinear_type] == :BILINEAR + +# @test alpine.nonconvex_terms[[:(x[37]), :(x[32])]][:id] == 8 +# @test alpine.nonconvex_terms[[:(x[37]), :(x[32])]][:lifted_var_ref] == :(x[110]) +# @test alpine.nonconvex_terms[[:(x[37]), :(x[32])]][:convexified] == false +# @test alpine.nonconvex_terms[[:(x[37]), :(x[32])]][:nonlinear_type] == :BILINEAR + +# @test alpine.bounding_constr_mip[213][:rhs] == 0.0 +# @test alpine.bounding_constr_mip[213][:vars] == +# Any[:(x[129]), :(x[127]), :(x[124]), :(x[130]), :(x[6]), :(x[18])] +# @test alpine.bounding_constr_mip[213][:sense] == :(==) +# @test alpine.bounding_constr_mip[213][:coefs] == Any[1.0, -1.0, -1.0, 1.0, -0.4, -0.4] +# @test alpine.bounding_constr_mip[213][:cnt] == 6 + +# @test alpine.nonconvex_terms[[:(x[48]), :(x[60])]][:id] == 27 +# @test alpine.nonconvex_terms[[:(x[48]), :(x[60])]][:lifted_var_ref] == :(x[129]) +# @test alpine.nonconvex_terms[[:(x[48]), :(x[60])]][:convexified] == false +# @test alpine.nonconvex_terms[[:(x[48]), :(x[60])]][:nonlinear_type] == :BILINEAR + +# @test alpine.nonconvex_terms[[:(x[47]), :(x[59])]][:id] == 25 +# @test alpine.nonconvex_terms[[:(x[47]), :(x[59])]][:lifted_var_ref] == :(x[127]) +# @test alpine.nonconvex_terms[[:(x[47]), :(x[59])]][:convexified] == false +# @test alpine.nonconvex_terms[[:(x[47]), :(x[59])]][:nonlinear_type] == :BILINEAR + +# @test alpine.nonconvex_terms[[:(x[47]), :(x[36])]][:id] == 28 +# @test alpine.nonconvex_terms[[:(x[47]), :(x[36])]][:lifted_var_ref] == :(x[130]) +# @test alpine.nonconvex_terms[[:(x[47]), :(x[36])]][:convexified] == false +# @test alpine.nonconvex_terms[[:(x[47]), :(x[36])]][:nonlinear_type] == :BILINEAR +# end + +# @testset "Expression Parsing || multilinear || Simple || multi.jl " begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "log_level" => 100, +# ) + +# m = multi3(solver = test_solver, exprmode = 1) + +# alpine = _build(m) # Setup internal model + +# @test length(keys(alpine.nonconvex_terms)) == 1 +# @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3])]][:id] == 1 +# @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3])]][:lifted_var_ref] == :(x[4]) +# @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3])]][:nonlinear_type] == +# :MULTILINEAR + +# @test alpine.bounding_obj_mip[:rhs] == 0 +# @test alpine.bounding_obj_mip[:vars] == Expr[:(x[4])] +# @test alpine.bounding_obj_mip[:coefs] == [1.0] +# @test alpine.bounding_obj_mip[:cnt] == 1 +# @test alpine.bounding_obj_mip[:sense] === nothing + +# @test alpine.bounding_constr_mip[1][:rhs] == 3.0 +# @test alpine.bounding_constr_mip[1][:vars] == Any[:(x[1]), :(x[2]), :(x[3])] +# @test alpine.bounding_constr_mip[1][:sense] == :(<=) +# @test alpine.bounding_constr_mip[1][:coefs] == Any[1.0, 1.0, 1.0] +# @test alpine.bounding_constr_mip[1][:cnt] == 3 + +# m = multi3(solver = test_solver, exprmode = 2) + +# alpine = _build(m) + +# @test length(keys(alpine.nonconvex_terms)) == 2 +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:id] == 1 +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:lifted_var_ref] == +# :(x[4]) +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 4), Expr(:ref, :x, 3)]][:id] == 2 +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 4), Expr(:ref, :x, 3)]][:lifted_var_ref] == +# :(x[5]) +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 4), Expr(:ref, :x, 3)]][:nonlinear_type] == +# :BILINEAR + +# @test alpine.bounding_obj_mip[:rhs] == 0 +# @test alpine.bounding_obj_mip[:vars] == Expr[:(x[5])] +# @test alpine.bounding_obj_mip[:coefs] == [1.0] +# @test alpine.bounding_obj_mip[:cnt] == 1 +# @test alpine.bounding_obj_mip[:sense] === nothing + +# m = multi3(solver = test_solver, exprmode = 3) + +# alpine = _build(m) + +# @test length(keys(alpine.nonconvex_terms)) == 2 +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:id] == 1 +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:lifted_var_ref] == +# :(x[4]) +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 4)]][:id] == 2 +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 4)]][:lifted_var_ref] == +# :(x[5]) +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 4)]][:nonlinear_type] == +# :BILINEAR + +# @test alpine.bounding_obj_mip[:rhs] == 0 +# @test alpine.bounding_obj_mip[:vars] == Expr[:(x[5])] +# @test alpine.bounding_obj_mip[:coefs] == [1.0] +# @test alpine.bounding_obj_mip[:cnt] == 1 +# @test alpine.bounding_obj_mip[:sense] === nothing + +# m = multi4(solver = test_solver, exprmode = 1) + +# alpine = _build(m) + +# @test length(keys(alpine.nonconvex_terms)) == 1 + +# @test alpine.bounding_obj_mip[:rhs] == 0 +# @test alpine.bounding_obj_mip[:vars] == Expr[:(x[5])] +# @test alpine.bounding_obj_mip[:coefs] == [1.0] +# @test alpine.bounding_obj_mip[:cnt] == 1 +# @test alpine.bounding_obj_mip[:sense] === nothing + +# @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:id] == 1 +# @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:lifted_var_ref] == +# :(x[5]) +# @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:nonlinear_type] == +# :MULTILINEAR + +# @test alpine.bounding_constr_mip[1][:rhs] == 4.0 +# @test alpine.bounding_constr_mip[1][:vars] == Any[:(x[1]), :(x[2]), :(x[3]), :(x[4])] +# @test alpine.bounding_constr_mip[1][:sense] == :(<=) +# @test alpine.bounding_constr_mip[1][:coefs] == Any[1.0, 1.0, 1.0, 1.0] +# @test alpine.bounding_constr_mip[1][:cnt] == 4 + +# m = multi4(solver = test_solver, exprmode = 2) + +# alpine = _build(m) + +# @test length(keys(alpine.nonconvex_terms)) == 3 + +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:id] == 1 +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:lifted_var_ref] == +# :(x[5]) +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:id] == 2 +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:lifted_var_ref] == +# :(x[6]) +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 5), Expr(:ref, :x, 6)]][:id] == 3 +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 5), Expr(:ref, :x, 6)]][:lifted_var_ref] == +# :(x[7]) +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 5), Expr(:ref, :x, 6)]][:nonlinear_type] == +# :BILINEAR + +# @test alpine.bounding_obj_mip[:rhs] == 0 +# @test alpine.bounding_obj_mip[:vars] == Expr[:(x[7])] +# @test alpine.bounding_obj_mip[:coefs] == [1.0] +# @test alpine.bounding_obj_mip[:cnt] == 1 +# @test alpine.bounding_obj_mip[:sense] === nothing + +# m = multi4(solver = test_solver, exprmode = 3) + +# alpine = _build(m) + +# @test length(keys(alpine.nonconvex_terms)) == 2 + +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:id] == 1 +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:lifted_var_ref] == +# :(x[5]) +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[[:(x[5]), :(x[3]), :(x[4])]][:id] == 2 +# @test alpine.nonconvex_terms[[:(x[5]), :(x[3]), :(x[4])]][:lifted_var_ref] == :(x[6]) +# @test alpine.nonconvex_terms[[:(x[5]), :(x[3]), :(x[4])]][:nonlinear_type] == +# :MULTILINEAR + +# @test alpine.bounding_obj_mip[:rhs] == 0 +# @test alpine.bounding_obj_mip[:vars] == Expr[:(x[6])] +# @test alpine.bounding_obj_mip[:coefs] == [1.0] +# @test alpine.bounding_obj_mip[:cnt] == 1 +# @test alpine.bounding_obj_mip[:sense] === nothing + +# m = multi4(solver = test_solver, exprmode = 4) + +# alpine = _build(m) + +# @test length(keys(alpine.nonconvex_terms)) == 2 + +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:id] == 1 +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:lifted_var_ref] == +# :(x[5]) +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[5])]][:id] == 2 +# @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[5])]][:lifted_var_ref] == :(x[6]) +# @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[5])]][:nonlinear_type] == +# :MULTILINEAR + +# @test alpine.bounding_obj_mip[:rhs] == 0 +# @test alpine.bounding_obj_mip[:vars] == Expr[:(x[6])] +# @test alpine.bounding_obj_mip[:coefs] == [1.0] +# @test alpine.bounding_obj_mip[:cnt] == 1 +# @test alpine.bounding_obj_mip[:sense] === nothing + +# @test alpine.bounding_obj_mip[:rhs] == 0 +# @test alpine.bounding_obj_mip[:vars] == Expr[:(x[6])] +# @test alpine.bounding_obj_mip[:coefs] == [1.0] +# @test alpine.bounding_obj_mip[:cnt] == 1 +# @test alpine.bounding_obj_mip[:sense] === nothing + +# m = multi4(solver = test_solver, exprmode = 5) + +# alpine = _build(m) + +# @test length(keys(alpine.nonconvex_terms)) == 3 + +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:id] == 1 +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:lifted_var_ref] == +# :(x[5]) +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 5)]][:id] == 2 +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 5)]][:lifted_var_ref] == +# :(x[6]) +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 5)]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 6), Expr(:ref, :x, 4)]][:id] == 3 +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 6), Expr(:ref, :x, 4)]][:lifted_var_ref] == +# :(x[7]) +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 6), Expr(:ref, :x, 4)]][:nonlinear_type] == +# :BILINEAR + +# @test alpine.bounding_obj_mip[:rhs] == 0 +# @test alpine.bounding_obj_mip[:vars] == Expr[:(x[7])] +# @test alpine.bounding_obj_mip[:coefs] == [1.0] +# @test alpine.bounding_obj_mip[:cnt] == 1 +# @test alpine.bounding_obj_mip[:sense] === nothing + +# @test alpine.bounding_obj_mip[:rhs] == 0 +# @test alpine.bounding_obj_mip[:vars] == Expr[:(x[7])] +# @test alpine.bounding_obj_mip[:coefs] == [1.0] +# @test alpine.bounding_obj_mip[:cnt] == 1 +# @test alpine.bounding_obj_mip[:sense] === nothing + +# m = multi4(solver = test_solver, exprmode = 6) + +# alpine = _build(m) + +# @test length(keys(alpine.nonconvex_terms)) == 2 + +# @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3])]][:id] == 1 +# @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3])]][:lifted_var_ref] == :(x[5]) +# @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 5), Expr(:ref, :x, 4)]][:id] == 2 +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 5), Expr(:ref, :x, 4)]][:lifted_var_ref] == +# :(x[6]) +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 5), Expr(:ref, :x, 4)]][:nonlinear_type] == +# :BILINEAR + +# @test alpine.bounding_obj_mip[:rhs] == 0 +# @test alpine.bounding_obj_mip[:vars] == Expr[:(x[6])] +# @test alpine.bounding_obj_mip[:coefs] == [1.0] +# @test alpine.bounding_obj_mip[:cnt] == 1 +# @test alpine.bounding_obj_mip[:sense] === nothing + +# m = multi4(solver = test_solver, exprmode = 7) + +# alpine = _build(m) + +# @test length(keys(alpine.nonconvex_terms)) == 3 + +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:id] == 1 +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:lifted_var_ref] == +# :(x[5]) +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 5)]][:id] == 2 +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 5)]][:lifted_var_ref] == +# :(x[6]) +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 5)]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 6)]][:id] == 3 +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 6)]][:lifted_var_ref] == +# :(x[7]) +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 6)]][:nonlinear_type] == +# :BILINEAR + +# @test alpine.bounding_obj_mip[:rhs] == 0 +# @test alpine.bounding_obj_mip[:vars] == Expr[:(x[7])] +# @test alpine.bounding_obj_mip[:coefs] == [1.0] +# @test alpine.bounding_obj_mip[:cnt] == 1 +# @test alpine.bounding_obj_mip[:sense] === nothing + +# m = multi4(solver = test_solver, exprmode = 8) + +# alpine = _build(m) + +# @test length(keys(alpine.nonconvex_terms)) == 2 + +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:id] == 1 +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:lifted_var_ref] == +# :(x[5]) +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[[:(x[1]), :(x[5]), :(x[4])]][:id] == 2 +# @test alpine.nonconvex_terms[[:(x[1]), :(x[5]), :(x[4])]][:lifted_var_ref] == :(x[6]) +# @test alpine.nonconvex_terms[[:(x[1]), :(x[5]), :(x[4])]][:nonlinear_type] == +# :MULTILINEAR + +# @test alpine.bounding_obj_mip[:rhs] == 0 +# @test alpine.bounding_obj_mip[:vars] == Expr[:(x[6])] +# @test alpine.bounding_obj_mip[:coefs] == [1.0] +# @test alpine.bounding_obj_mip[:cnt] == 1 +# @test alpine.bounding_obj_mip[:sense] === nothing + +# m = multi4(solver = test_solver, exprmode = 9) + +# alpine = _build(m) + +# @test length(keys(alpine.nonconvex_terms)) == 2 + +# @test alpine.nonconvex_terms[[:(x[2]), :(x[3]), :(x[4])]][:id] == 1 +# @test alpine.nonconvex_terms[[:(x[2]), :(x[3]), :(x[4])]][:lifted_var_ref] == :(x[5]) +# @test alpine.nonconvex_terms[[:(x[2]), :(x[3]), :(x[4])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 5)]][:id] == 2 +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 5)]][:lifted_var_ref] == +# :(x[6]) +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 5)]][:nonlinear_type] == +# :BILINEAR + +# @test alpine.bounding_obj_mip[:rhs] == 0 +# @test alpine.bounding_obj_mip[:vars] == Expr[:(x[6])] +# @test alpine.bounding_obj_mip[:coefs] == [1.0] +# @test alpine.bounding_obj_mip[:cnt] == 1 +# @test alpine.bounding_obj_mip[:sense] === nothing + +# m = multi4(solver = test_solver, exprmode = 10) + +# alpine = _build(m) +# @test length(keys(alpine.nonconvex_terms)) == 3 + +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:id] == 1 +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:lifted_var_ref] == +# :(x[5]) +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 4), Expr(:ref, :x, 5)]][:id] == 2 +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 4), Expr(:ref, :x, 5)]][:lifted_var_ref] == +# :(x[6]) +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 4), Expr(:ref, :x, 5)]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 6)]][:id] == 3 +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 6)]][:lifted_var_ref] == +# :(x[7]) +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 6)]][:nonlinear_type] == +# :BILINEAR + +# @test alpine.bounding_obj_mip[:rhs] == 0 +# @test alpine.bounding_obj_mip[:vars] == Expr[:(x[7])] +# @test alpine.bounding_obj_mip[:coefs] == [1.0] +# @test alpine.bounding_obj_mip[:cnt] == 1 +# @test alpine.bounding_obj_mip[:sense] === nothing + +# m = multi4(solver = test_solver, exprmode = 11) + +# alpine = _build(m) + +# @test length(keys(alpine.nonconvex_terms)) == 3 + +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:id] == 1 +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:lifted_var_ref] == +# :(x[5]) +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 5)]][:id] == 2 +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 5)]][:lifted_var_ref] == +# :(x[6]) +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 5)]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 6), Expr(:ref, :x, 4)]][:id] == 3 +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 6), Expr(:ref, :x, 4)]][:lifted_var_ref] == +# :(x[7]) +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 6), Expr(:ref, :x, 4)]][:nonlinear_type] == +# :BILINEAR + +# @test alpine.bounding_obj_mip[:rhs] == 0 +# @test alpine.bounding_obj_mip[:vars] == Expr[:(x[7])] +# @test alpine.bounding_obj_mip[:coefs] == [1.0] +# @test alpine.bounding_obj_mip[:cnt] == 1 +# @test alpine.bounding_obj_mip[:sense] === nothing +# end + +# @testset "Expression Parsing || bilinear || Complex-div || div.jl" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "log_level" => 100, +# ) + +# m = div(solver = test_solver) + +# alpine = _build(m) # Setup internal model + +# @test length(keys(alpine.nonconvex_terms)) == 3 +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 1)]][:id] == 1 +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 1)]][:lifted_var_ref] == +# :(x[3]) +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 1)]][:nonlinear_type] == +# :MONOMIAL + +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 2)]][:id] == 2 +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 2)]][:lifted_var_ref] == +# :(x[4]) +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 2)]][:nonlinear_type] == +# :MONOMIAL + +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:id] == 3 +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:lifted_var_ref] == +# :(x[5]) +# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:nonlinear_type] == +# :BILINEAR + +# aff_mip = alpine.bounding_constr_mip + +# @test aff_mip[1][:rhs] == 0.0 +# @test aff_mip[1][:vars] == Any[:(x[1])] +# @test aff_mip[1][:sense] == :(>=) +# @test round(aff_mip[1][:coefs][1]; digits = 1) == -3.0 +# @test aff_mip[1][:cnt] == 1 + +# @test aff_mip[2][:rhs] == 0.0 +# @test aff_mip[2][:vars] == Any[:(x[2])] +# @test aff_mip[2][:sense] == :(>=) +# @test aff_mip[2][:coefs] == Any[0.25] +# @test aff_mip[2][:cnt] == 1 + +# @test aff_mip[3][:rhs] == 0.0 +# @test aff_mip[3][:vars] == Any[:(x[2])] +# @test aff_mip[3][:sense] == :(>=) +# @test aff_mip[3][:coefs] == Any[5.0] +# @test aff_mip[3][:cnt] == 1 + +# @test aff_mip[4][:rhs] == 0.0 +# @test aff_mip[4][:vars] == Any[:(x[2])] +# @test aff_mip[4][:sense] == :(>=) +# @test aff_mip[4][:coefs] == Any[-120.0] +# @test aff_mip[4][:cnt] == 1 + +# @test aff_mip[5][:rhs] == 0.0 +# @test aff_mip[5][:vars] == Any[:(x[2])] +# @test aff_mip[5][:sense] == :(>=) +# @test aff_mip[5][:coefs] == Any[72000.0] +# @test aff_mip[5][:cnt] == 1 + +# @test aff_mip[6][:rhs] == 0.0 +# @test aff_mip[6][:vars] == Any[:(x[1])] +# @test aff_mip[6][:sense] == :(>=) +# @test aff_mip[6][:coefs] == Any[72000.0] +# @test aff_mip[6][:cnt] == 1 + +# @test aff_mip[7][:rhs] == 8.0 +# @test aff_mip[7][:vars] == Any[:(x[5])] +# @test aff_mip[7][:sense] == :(>=) +# @test aff_mip[7][:coefs] == Any[0.6] +# @test aff_mip[7][:cnt] == 1 + +# @test aff_mip[8][:rhs] == 0.0 +# @test aff_mip[8][:vars] == Any[:(x[2]), :(x[5])] +# @test aff_mip[8][:sense] == :(>=) +# @test aff_mip[8][:coefs] == Any[5.6, -72000.0] +# @test aff_mip[8][:cnt] == 2 + +# @test aff_mip[9][:rhs] == 0.0 +# @test aff_mip[9][:vars] == Any[:(x[2]), :(x[5])] +# @test aff_mip[9][:sense] == :(>=) +# @test aff_mip[9][:coefs] == Any[5.6, -36000.0] +# @test aff_mip[9][:cnt] == 2 + +# @test aff_mip[10][:rhs] == 0.0 +# @test aff_mip[10][:vars] == Any[:(x[2]), :(x[5]), :(x[2])] +# @test aff_mip[10][:sense] == :(>=) +# @test aff_mip[10][:coefs] == Any[5.6, -300.0, -1.75] +# @test aff_mip[10][:cnt] == 3 + +# @test aff_mip[11][:rhs] == 0.0 +# @test aff_mip[11][:vars] == Any[:(x[2]), :(x[1]), :(x[5])] +# @test aff_mip[11][:sense] == :(>=) +# @test aff_mip[11][:coefs] == Any[5.6, -0.5, 0.5] +# @test aff_mip[11][:cnt] == 3 +# end + +# @testset "Expression Parsing || part1 " begin +# m = Model( +# optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "log_level" => 100, +# ), +# ) +# @variable(m, x[1:4] >= 0) +# @NLconstraint(m, x[1]^2 >= 1) # Basic monomial x[5]=x[1]^2 +# @NLconstraint(m, x[1] * x[2] <= 1) # x[6] <= 1 : x[6] = x[1]*x[2] +# @NLconstraint(m, x[1]^2 * x[2]^2 <= 1) # x[5] + x[7] <= 1 : x[7] = x[2]^2 +# @NLconstraint(m, x[1] * (x[2] * x[3]) >= 1) # x[9] >= 1 : x[8] = x[2] * x[3] && x[9] = x[1]*x[8] +# @NLconstraint(m, x[1]^2 * (x[2]^2 * x[3]^2) <= 1) # x[12] <= 1 : x[10] = x[3] ^ 2 && x[11] = x[7] * x[10] && x[12] = x[11]*[5] + +# alpine = _build(m) + +# @test alpine.bounding_constr_expr_mip[1] == :(x[5] - 1.0 >= 0.0) +# @test alpine.bounding_constr_expr_mip[2] == :(x[6] - 1.0 <= 0.0) +# @test alpine.bounding_constr_expr_mip[3] == :(x[8] - 1.0 <= 0.0) +# @test alpine.bounding_constr_expr_mip[4] == :(x[10] - 1.0 >= 0.0) +# @test alpine.bounding_constr_expr_mip[5] == :(x[13] - 1.0 <= 0.0) +# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[1])]) +# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2])]) +# @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[2])]) +# @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[3])]) +# @test haskey(alpine.nonconvex_terms, [:(x[5]), :(x[7])]) +# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[9])]) +# @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[3])]) +# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2])]) +# @test haskey(alpine.nonconvex_terms, [:(x[5]), :(x[12])]) + +# @test alpine.nonconvex_terms[[:(x[1]), :(x[1])]][:id] == 1 +# @test alpine.nonconvex_terms[[:(x[1]), :(x[2])]][:id] == 2 +# @test alpine.nonconvex_terms[[:(x[2]), :(x[2])]][:id] == 3 +# @test alpine.nonconvex_terms[[:(x[5]), :(x[7])]][:id] == 4 +# @test alpine.nonconvex_terms[[:(x[2]), :(x[3])]][:id] == 5 +# @test alpine.nonconvex_terms[[:(x[1]), :(x[9])]][:id] == 6 +# @test alpine.nonconvex_terms[[:(x[3]), :(x[3])]][:id] == 7 +# @test alpine.nonconvex_terms[[:(x[7]), :(x[11])]][:id] == 8 +# @test alpine.nonconvex_terms[[:(x[5]), :(x[12])]][:id] == 9 +# end + +# @testset "Expression Parsing || part2" begin +# m = Model( +# optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "log_level" => 100, +# ), +# ) + +# @variable(m, x[1:4] >= 0) +# @NLconstraint(m, (x[1] * x[2]) * x[3] >= 1) +# @NLconstraint(m, (x[1]^2 * x[2]^2) * x[3]^2 <= 1) + +# @NLconstraint(m, x[1] * (x[2]^2 * x[3]^2) >= 1) +# @NLconstraint(m, (x[1]^2 * x[2]) * x[3]^2 <= 1) +# @NLconstraint(m, x[1]^2 * (x[2] * x[3]) >= 1) +# @NLconstraint(m, (x[1] * x[2]^2) * x[3] <= 1) + +# alpine = _build(m) + +# @test alpine.bounding_constr_expr_mip[1] == :(x[6] - 1.0 >= 0.0) +# @test alpine.bounding_constr_expr_mip[2] == :(x[11] - 1.0 <= 0.0) +# @test alpine.bounding_constr_expr_mip[3] == :(x[13] - 1.0 >= 0.0) +# @test alpine.bounding_constr_expr_mip[4] == :(x[15] - 1.0 <= 0.0) +# @test alpine.bounding_constr_expr_mip[5] == :(x[17] - 1.0 >= 0.0) +# @test alpine.bounding_constr_expr_mip[6] == :(x[19] - 1.0 <= 0.0) + +# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2])]) #5 +# @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[5])]) #6 +# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[1])]) #7 +# @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[2])]) #8 +# @test haskey(alpine.nonconvex_terms, [:(x[7]), :(x[8])]) #9 +# @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[3])]) #10 +# @test haskey(alpine.nonconvex_terms, [:(x[9]), :(x[10])]) #11 +# @test haskey(alpine.nonconvex_terms, [:(x[8]), :(x[10])]) #12 +# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[12])]) #13 +# @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[7])]) #14 +# @test haskey(alpine.nonconvex_terms, [:(x[14]), :(x[10])]) #15 +# @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[3])]) #16 +# @test haskey(alpine.nonconvex_terms, [:(x[7]), :(x[16])]) #17 +# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[8])]) #18 +# @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[18])]) #19 + +# @test alpine.nonconvex_terms[[:(x[1]), :(x[2])]][:id] == 1 +# @test alpine.nonconvex_terms[[:(x[3]), :(x[5])]][:id] == 2 +# @test alpine.nonconvex_terms[[:(x[1]), :(x[1])]][:id] == 3 +# @test alpine.nonconvex_terms[[:(x[2]), :(x[2])]][:id] == 4 +# @test alpine.nonconvex_terms[[:(x[7]), :(x[8])]][:id] == 5 +# @test alpine.nonconvex_terms[[:(x[3]), :(x[3])]][:id] == 6 +# @test alpine.nonconvex_terms[[:(x[9]), :(x[10])]][:id] == 7 +# @test alpine.nonconvex_terms[[:(x[8]), :(x[10])]][:id] == 8 +# @test alpine.nonconvex_terms[[:(x[1]), :(x[12])]][:id] == 9 +# @test alpine.nonconvex_terms[[:(x[2]), :(x[7])]][:id] == 10 +# @test alpine.nonconvex_terms[[:(x[14]), :(x[10])]][:id] == 11 +# @test alpine.nonconvex_terms[[:(x[2]), :(x[3])]][:id] == 12 +# @test alpine.nonconvex_terms[[:(x[7]), :(x[16])]][:id] == 13 +# @test alpine.nonconvex_terms[[:(x[1]), :(x[8])]][:id] == 14 +# @test alpine.nonconvex_terms[[:(x[3]), :(x[18])]][:id] == 15 +# end + +# @testset "Expression Parsing || part3" begin +# m = Model( +# optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "log_level" => 100, +# ), +# ) + +# @variable(m, x[1:4] >= 0) +# @NLconstraint(m, ((x[1] * x[2]) * x[3]) * x[4] >= 1) +# @NLconstraint(m, ((x[1]^2 * x[2]) * x[3]) * x[4] <= 1) +# @NLconstraint(m, ((x[1] * x[2]^2) * x[3]) * x[4] >= 1) +# @NLconstraint(m, ((x[1] * x[2]) * x[3]^2) * x[4] <= 1) +# @NLconstraint(m, ((x[1] * x[2]) * x[3]) * x[4]^2 >= 1) +# @NLconstraint(m, ((x[1]^2 * x[2]^2) * x[3]^2) * x[4]^2 <= 1) + +# alpine = _build(m) + +# @test alpine.bounding_constr_expr_mip[1] == :(x[7] - 1.0 >= 0.0) +# @test alpine.bounding_constr_expr_mip[2] == :(x[11] - 1.0 <= 0.0) +# @test alpine.bounding_constr_expr_mip[3] == :(x[15] - 1.0 >= 0.0) +# @test alpine.bounding_constr_expr_mip[4] == :(x[18] - 1.0 <= 0.0) +# @test alpine.bounding_constr_expr_mip[5] == :(x[20] - 1.0 >= 0.0) +# @test alpine.bounding_constr_expr_mip[6] == :(x[23] - 1.0 <= 0.0) + +# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2])]) #5 +# @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[5])]) #6 +# @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[6])]) #7 +# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[1])]) #8 +# @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[8])]) #9 +# @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[9])]) #10 +# @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[10])]) #11 +# @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[2])]) #12 +# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[12])]) #13 +# @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[13])]) #14 +# @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[14])]) #15 +# @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[3])]) #16 +# @test haskey(alpine.nonconvex_terms, [:(x[5]), :(x[16])]) #17 +# @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[17])]) #18 +# @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[4])]) #19 +# @test haskey(alpine.nonconvex_terms, [:(x[6]), :(x[19])]) #20 +# @test haskey(alpine.nonconvex_terms, [:(x[8]), :(x[12])]) #21 +# @test haskey(alpine.nonconvex_terms, [:(x[21]), :(x[16])]) #22 +# @test haskey(alpine.nonconvex_terms, [:(x[22]), :(x[19])]) #23 + +# @test alpine.nonconvex_terms[[:(x[1]), :(x[2])]][:id] == 1 +# @test alpine.nonconvex_terms[[:(x[3]), :(x[5])]][:id] == 2 +# @test alpine.nonconvex_terms[[:(x[4]), :(x[6])]][:id] == 3 +# @test alpine.nonconvex_terms[[:(x[1]), :(x[1])]][:id] == 4 +# @test alpine.nonconvex_terms[[:(x[2]), :(x[8])]][:id] == 5 +# @test alpine.nonconvex_terms[[:(x[3]), :(x[9])]][:id] == 6 +# @test alpine.nonconvex_terms[[:(x[4]), :(x[10])]][:id] == 7 +# @test alpine.nonconvex_terms[[:(x[2]), :(x[2])]][:id] == 8 +# @test alpine.nonconvex_terms[[:(x[1]), :(x[12])]][:id] == 9 +# @test alpine.nonconvex_terms[[:(x[3]), :(x[13])]][:id] == 10 +# @test alpine.nonconvex_terms[[:(x[4]), :(x[14])]][:id] == 11 +# @test alpine.nonconvex_terms[[:(x[3]), :(x[3])]][:id] == 12 +# @test alpine.nonconvex_terms[[:(x[5]), :(x[16])]][:id] == 13 +# @test alpine.nonconvex_terms[[:(x[4]), :(x[17])]][:id] == 14 +# @test alpine.nonconvex_terms[[:(x[4]), :(x[4])]][:id] == 15 +# @test alpine.nonconvex_terms[[:(x[6]), :(x[19])]][:id] == 16 +# @test alpine.nonconvex_terms[[:(x[8]), :(x[12])]][:id] == 17 +# @test alpine.nonconvex_terms[[:(x[21]), :(x[16])]][:id] == 18 +# @test alpine.nonconvex_terms[[:(x[22]), :(x[19])]][:id] == 19 +# end + +# @testset "Expression Parsing || part7" begin +# m = Model( +# optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "log_level" => 100, +# ), +# ) +# @variable(m, x[1:4] >= 0) + +# @NLconstraint(m, x[1] * x[2] * x[3] * x[4] >= 1) +# @NLconstraint(m, x[1]^2 * x[2] * x[3] * x[4] >= 1) +# @NLconstraint(m, x[1] * x[2]^2 * x[3] * x[4] >= 1) +# @NLconstraint(m, x[1] * x[2] * x[3]^2 * x[4]^2 >= 1) +# @NLconstraint(m, x[1] * x[2]^2 * x[3]^2 * x[4] >= 1) +# @NLconstraint(m, x[1]^2 * x[2] * x[3] * x[4]^2 >= 1) +# @NLconstraint(m, x[1]^2 * x[2]^2 * x[3]^2 * x[4]^2 >= 1) + +# alpine = _build(m) + +# @test alpine.bounding_constr_expr_mip[1] == :(x[5] - 1.0 >= 0.0) +# @test alpine.bounding_constr_expr_mip[2] == :(x[7] - 1.0 >= 0.0) +# @test alpine.bounding_constr_expr_mip[3] == :(x[9] - 1.0 >= 0.0) +# @test alpine.bounding_constr_expr_mip[4] == :(x[12] - 1.0 >= 0.0) +# @test alpine.bounding_constr_expr_mip[5] == :(x[13] - 1.0 >= 0.0) +# @test alpine.bounding_constr_expr_mip[6] == :(x[14] - 1.0 >= 0.0) +# @test alpine.bounding_constr_expr_mip[7] == :(x[15] - 1.0 >= 0.0) + +# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2]), :(x[3]), :(x[4])]) #5 +# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[1])]) #6 +# @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[3]), :(x[4]), :(x[6])]) #7 +# @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[2])]) #8 +# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[3]), :(x[4]), :(x[8])]) #9 +# @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[3])]) #10 +# @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[4])]) #11 +# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2]), :(x[10]), :(x[11])]) #12 +# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[4]), :(x[8]), :(x[10])]) #13 +# @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[3]), :(x[6]), :(x[11])]) #14 +# @test haskey(alpine.nonconvex_terms, [:(x[6]), :(x[8]), :(x[10]), :(x[11])]) #15 + +# @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:id] == 1 #5 +# @test alpine.nonconvex_terms[[:(x[1]), :(x[1])]][:id] == 2 #6 +# @test alpine.nonconvex_terms[[:(x[2]), :(x[3]), :(x[4]), :(x[6])]][:id] == 3 #7 +# @test alpine.nonconvex_terms[[:(x[2]), :(x[2])]][:id] == 4 #8 +# @test alpine.nonconvex_terms[[:(x[1]), :(x[3]), :(x[4]), :(x[8])]][:id] == 5 #9 +# @test alpine.nonconvex_terms[[:(x[3]), :(x[3])]][:id] == 6 #10 +# @test alpine.nonconvex_terms[[:(x[4]), :(x[4])]][:id] == 7 #11 +# @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[10]), :(x[11])]][:id] == 8 #12 +# @test alpine.nonconvex_terms[[:(x[1]), :(x[4]), :(x[8]), :(x[10])]][:id] == 9 #13 +# @test alpine.nonconvex_terms[[:(x[2]), :(x[3]), :(x[6]), :(x[11])]][:id] == 10 #14 +# @test alpine.nonconvex_terms[[:(x[6]), :(x[8]), :(x[10]), :(x[11])]][:id] == 11 #15 +# end + +# @testset "Expression Parsing || part8" begin +# m = Model( +# optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "log_level" => 100, +# ), +# ) +# @variable(m, x[1:4] >= 0) + +# @NLconstraint(m, (x[1] * x[2] * x[3]) * x[4] >= 1) +# @NLconstraint(m, (x[1]^2 * x[2] * x[3]) * x[4] >= 1) +# @NLconstraint(m, x[1] * (x[2]^2 * x[3]) * x[4] >= 1) +# @NLconstraint(m, x[1] * (x[2] * x[3]^2) * x[4] >= 1) +# @NLconstraint(m, (x[1] * x[2]^2) * x[3] * x[4] >= 1) +# @NLconstraint(m, (x[1] * x[2]) * x[3]^2 * x[4] >= 1) +# @NLconstraint(m, (x[1] * x[2]) * x[3] * x[4]^2 >= 1) +# @NLconstraint(m, (x[1] * x[2]) * x[3]^2 * x[4]^2 >= 1) +# @NLconstraint(m, (x[1]^2 * x[2]^2 * x[3]^2) * x[4]^2 >= 1) + +# alpine = _build(m) + +# @test alpine.bounding_constr_expr_mip[1] == :(x[6] - 1.0 >= 0.0) +# @test alpine.bounding_constr_expr_mip[2] == :(x[9] - 1.0 >= 0.0) +# @test alpine.bounding_constr_expr_mip[3] == :(x[12] - 1.0 >= 0.0) +# @test alpine.bounding_constr_expr_mip[4] == :(x[15] - 1.0 >= 0.0) +# @test alpine.bounding_constr_expr_mip[5] == :(x[17] - 1.0 >= 0.0) +# @test alpine.bounding_constr_expr_mip[6] == :(x[19] - 1.0 >= 0.0) +# @test alpine.bounding_constr_expr_mip[7] == :(x[21] - 1.0 >= 0.0) +# @test alpine.bounding_constr_expr_mip[8] == :(x[22] - 1.0 >= 0.0) +# @test alpine.bounding_constr_expr_mip[9] == :(x[24] - 1.0 >= 0.0) + +# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2]), :(x[3])]) #5 +# @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[5])]) #6 +# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[1])]) #7 +# @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[3]), :(x[7])]) #8 +# @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[8])]) #9 +# @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[2])]) #10 +# @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[10])]) #11 +# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[4]), :(x[11])]) #12 +# @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[3])]) #13 +# @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[13])]) #14 +# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[4]), :(x[14])]) #15 +# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[10])]) #16 +# @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[4]), :(x[16])]) #17 +# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2])]) #18 +# @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[18]), :(x[13])]) #19 +# @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[4])]) #20 +# @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[18]), :(x[20])]) #21 +# @test haskey(alpine.nonconvex_terms, [:(x[18]), :(x[13]), :(x[20])]) #22 +# @test haskey(alpine.nonconvex_terms, [:(x[7]), :(x[10]), :(x[13])]) #23 +# @test haskey(alpine.nonconvex_terms, [:(x[23]), :(x[20])]) #24 +# end + +# @testset "Expression Parsing || Convex" begin +# @testset "Convex Parsing :: PART I" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "log_level" => 100, +# ) +# m = convex_test(solver = test_solver) + +# alpine = _build(m) + +# @test alpine.num_constr_convex == 21 + +# # 0 : OBJ +# @test alpine.obj_structure == :convex +# @test alpine.nonlinear_constrs[0][:expr_orig] == :objective +# @test alpine.nonlinear_constrs[0][:convex_type] == :convexA +# @test alpine.nonlinear_constrs[0][:convexified] == false + +# @test alpine.bounding_obj_mip[:sense] === nothing +# @test alpine.bounding_obj_mip[:coefs] == [1.0, 1.0] +# @test alpine.bounding_obj_mip[:vars] == [:(x[1]), :(x[3])] +# @test alpine.bounding_obj_mip[:rhs] == 0.0 +# @test alpine.bounding_obj_mip[:powers] == [2, 2] +# @test alpine.bounding_obj_mip[:cnt] == 2 + +# # 1 +# @test alpine.constr_structure[1] == :convex +# @test alpine.nonlinear_constrs[1][:expr_orig] == :constraints +# @test alpine.nonlinear_constrs[1][:convex_type] == :convexA +# @test alpine.nonlinear_constrs[1][:convexified] == false +# @test alpine.bounding_constr_mip[1][:sense] == :(<=) +# @test alpine.bounding_constr_mip[1][:coefs] == [3.0, 4.0] +# @test alpine.bounding_constr_mip[1][:vars] == [:(x[1]), :(x[2])] +# @test alpine.bounding_constr_mip[1][:rhs] == 25.0 +# @test alpine.bounding_constr_mip[1][:powers] == [2, 2] +# @test alpine.bounding_constr_mip[1][:cnt] == 2 + +# # 2 +# @test alpine.constr_structure[2] == :convex +# @test alpine.nonlinear_constrs[2][:expr_orig] == :constraints +# @test alpine.nonlinear_constrs[2][:convex_type] == :convexA +# @test alpine.nonlinear_constrs[2][:convexified] == false +# @test alpine.bounding_constr_mip[2][:sense] == :(<=) +# @test alpine.bounding_constr_mip[2][:coefs] == [3.0, 4.0] +# @test alpine.bounding_constr_mip[2][:vars] == [:(x[1]), :(x[2])] +# @test alpine.bounding_constr_mip[2][:rhs] == 25.0 +# @test alpine.bounding_constr_mip[2][:powers] == [2, 2] +# @test alpine.bounding_constr_mip[2][:cnt] == 2 + +# # 4 +# @test alpine.constr_structure[4] == :convex +# @test alpine.nonlinear_constrs[4][:expr_orig] == :constraints +# @test alpine.nonlinear_constrs[4][:convex_type] == :convexA +# @test alpine.nonlinear_constrs[4][:convexified] == false +# @test alpine.bounding_constr_mip[4][:sense] == :(<=) +# @test alpine.bounding_constr_mip[4][:coefs] == [3.0, 4.0] +# @test alpine.bounding_constr_mip[4][:vars] == [:(x[1]), :(x[2])] +# @test alpine.bounding_constr_mip[4][:rhs] == 10.0 +# @test alpine.bounding_constr_mip[4][:powers] == [2, 2] +# @test alpine.bounding_constr_mip[4][:cnt] == 2 + +# # 5 +# @test alpine.constr_structure[5] == :convex +# @test alpine.nonlinear_constrs[5][:expr_orig] == :constraints +# @test alpine.nonlinear_constrs[5][:convex_type] == :convexA +# @test alpine.nonlinear_constrs[5][:convexified] == :false +# @test alpine.bounding_constr_mip[5][:sense] == :(<=) +# @test alpine.bounding_constr_mip[5][:coefs] == [3.0, 4.0, 6.0] +# @test alpine.bounding_constr_mip[5][:vars] == [:(x[1]), :(x[2]), :(x[3])] +# @test alpine.bounding_constr_mip[5][:rhs] == 10.0 +# @test alpine.bounding_constr_mip[5][:powers] == [2, 2, 2] +# @test alpine.bounding_constr_mip[5][:cnt] == 3 + +# # 6 +# @test alpine.constr_structure[6] == :convex +# @test alpine.nonlinear_constrs[6][:expr_orig] == :constraints +# @test alpine.nonlinear_constrs[6][:convex_type] == :convexC +# @test alpine.nonlinear_constrs[6][:convexified] == :false +# @test alpine.bounding_constr_mip[6][:sense] == :(<=) +# @test alpine.bounding_constr_mip[6][:coefs] == [3.0, 4.0, 5.0] +# @test alpine.bounding_constr_mip[6][:vars] == [:(x[1]), :(x[2]), :(x[5])] +# @test alpine.bounding_constr_mip[6][:rhs] == 100.0 +# @test alpine.bounding_constr_mip[6][:powers] == [0.5, 0.5, 0.5] +# @test alpine.bounding_constr_mip[6][:cnt] == 3 + +# # 7 +# @test alpine.constr_structure[7] == :convex +# @test alpine.nonlinear_constrs[7][:expr_orig] == :constraints +# @test alpine.nonlinear_constrs[7][:convex_type] == :convexC +# @test alpine.nonlinear_constrs[7][:convexified] == :false +# @test alpine.bounding_constr_mip[7][:sense] == :(>=) +# @test alpine.bounding_constr_mip[7][:coefs] == [-3.0, -4.0] +# @test alpine.bounding_constr_mip[7][:vars] == [:(x[1]), :(x[2])] +# @test alpine.bounding_constr_mip[7][:rhs] == -100.0 +# @test alpine.bounding_constr_mip[7][:powers] == [0.5, 0.5] +# @test alpine.bounding_constr_mip[7][:cnt] == 2 + +# # 8 +# @test alpine.constr_structure[8] == :convex +# @test alpine.nonlinear_constrs[8][:expr_orig] == :constraints +# @test alpine.nonlinear_constrs[8][:convex_type] == :convexB +# @test alpine.nonlinear_constrs[8][:convexified] == :false +# @test alpine.bounding_constr_mip[8][:sense] == :(<=) +# @test alpine.bounding_constr_mip[8][:coefs] == [3.0, 1.0, 5.0] +# @test alpine.bounding_constr_mip[8][:vars] == [:(x[1]), :(x[2]), :(x[3])] +# @test alpine.bounding_constr_mip[8][:rhs] == 200.0 +# @test alpine.bounding_constr_mip[8][:powers] == [3.0, 3.0, 3.0] +# @test alpine.bounding_constr_mip[8][:cnt] == 3 + +# # 9 +# @test alpine.constr_structure[9] == :convex +# @test alpine.nonlinear_constrs[9][:expr_orig] == :constraints +# @test alpine.nonlinear_constrs[9][:convex_type] == :convexB +# @test alpine.nonlinear_constrs[9][:convexified] == :false +# @test alpine.bounding_constr_mip[9][:sense] == :(<=) +# @test alpine.bounding_constr_mip[9][:coefs] == [1.0, 1.0, 1.0, 100.0] +# @test alpine.bounding_constr_mip[9][:vars] == [:(x[1]), :(x[2]), :(x[3]), :(x[4])] +# @test alpine.bounding_constr_mip[9][:rhs] == 200.0 +# @test alpine.bounding_constr_mip[9][:powers] == [3, 3, 3, 3] +# @test alpine.bounding_constr_mip[9][:cnt] == 4 + +# # 11 +# @test alpine.constr_structure[11] == :convex +# @test alpine.nonlinear_constrs[11][:expr_orig] == :constraints +# @test alpine.nonlinear_constrs[11][:convex_type] == :convexA +# @test alpine.nonlinear_constrs[11][:convexified] == :false +# @test alpine.bounding_constr_mip[11][:sense] == :(<=) +# @test alpine.bounding_constr_mip[11][:coefs] == [3.0, 4.0] +# @test alpine.bounding_constr_mip[11][:vars] == [:(x[1]), :(x[2])] +# @test alpine.bounding_constr_mip[11][:rhs] == 25.0 +# @test alpine.bounding_constr_mip[11][:powers] == [2, 2] +# @test alpine.bounding_constr_mip[11][:cnt] == 2 + +# # 14 +# @test alpine.constr_structure[14] == :convex +# @test alpine.nonlinear_constrs[14][:expr_orig] == :constraints +# @test alpine.nonlinear_constrs[14][:convex_type] == :convexA +# @test alpine.nonlinear_constrs[14][:convexified] == :false +# @test alpine.bounding_constr_mip[14][:sense] == :(<=) +# @test alpine.bounding_constr_mip[14][:coefs] == [3.0, 5.0] +# @test alpine.bounding_constr_mip[14][:vars] == [:(x[1]), :(x[2])] +# @test alpine.bounding_constr_mip[14][:rhs] == 25.0 +# @test alpine.bounding_constr_mip[14][:powers] == [2, 2] +# @test alpine.bounding_constr_mip[14][:cnt] == 2 + +# # 15 +# @test alpine.constr_structure[15] == :convex +# @test alpine.nonlinear_constrs[15][:expr_orig] == :constraints +# @test alpine.nonlinear_constrs[15][:convex_type] == :convexA +# @test alpine.nonlinear_constrs[15][:convexified] == :false +# @test alpine.bounding_constr_mip[15][:sense] == :(<=) +# @test alpine.bounding_constr_mip[15][:coefs] == [3.0, 5.0, 1.0] +# @test alpine.bounding_constr_mip[15][:vars] == [:(x[1]), :(x[2]), :(x[4])] +# @test alpine.bounding_constr_mip[15][:rhs] == 25.0 +# @test alpine.bounding_constr_mip[15][:powers] == [2, 2, 2] +# @test alpine.bounding_constr_mip[15][:cnt] == 3 + +# # 19 +# @test alpine.constr_structure[19] == :convex +# @test alpine.nonlinear_constrs[19][:expr_orig] == :constraints +# @test alpine.nonlinear_constrs[19][:convex_type] == :convexA +# @test alpine.nonlinear_constrs[19][:convexified] == :false +# @test alpine.bounding_constr_mip[19][:sense] == :(<=) +# @test alpine.bounding_constr_mip[19][:coefs] == [3.0, 16.0] +# @test alpine.bounding_constr_mip[19][:vars] == [:(x[1]), :(x[2])] +# @test alpine.bounding_constr_mip[19][:rhs] == 40.0 +# @test alpine.bounding_constr_mip[19][:powers] == [2, 2] +# @test alpine.bounding_constr_mip[19][:cnt] == 2 + +# # 22 +# @test alpine.constr_structure[22] == :convex +# @test alpine.nonlinear_constrs[22][:expr_orig] == :constraints +# @test alpine.nonlinear_constrs[22][:convex_type] == :convexA +# @test alpine.nonlinear_constrs[22][:convexified] == :false +# @test alpine.bounding_constr_mip[22][:sense] == :(<=) +# @test alpine.bounding_constr_mip[22][:coefs] == [3.0, 4.0, 5.0, 6.0] +# @test alpine.bounding_constr_mip[22][:vars] == +# [:(x[1]), :(x[2]), :(x[3]), :(x[4])] +# @test alpine.bounding_constr_mip[22][:rhs] == 15.0 +# @test alpine.bounding_constr_mip[22][:powers] == [2, 2, 2, 2] +# @test alpine.bounding_constr_mip[22][:cnt] == 4 + +# # 25 +# @test alpine.constr_structure[25] == :convex +# @test alpine.nonlinear_constrs[25][:expr_orig] == :constraints +# @test alpine.nonlinear_constrs[25][:convex_type] == :convexA +# @test alpine.nonlinear_constrs[25][:convexified] == :false +# @test alpine.bounding_constr_mip[25][:sense] == :(<=) +# @test alpine.bounding_constr_mip[25][:coefs] == [1.0, 1.0, 1.0, 1.0, 1.0] +# @test alpine.bounding_constr_mip[25][:vars] == +# [:(x[1]), :(x[2]), :(x[3]), :(x[4]), :(x[5])] +# @test alpine.bounding_constr_mip[25][:rhs] == 99999.0 +# @test alpine.bounding_constr_mip[25][:powers] == [2, 2, 2, 2, 2] +# @test alpine.bounding_constr_mip[25][:cnt] == 5 + +# # 26 +# @test alpine.constr_structure[26] == :convex +# @test alpine.nonlinear_constrs[26][:expr_orig] == :constraints +# @test alpine.nonlinear_constrs[26][:convex_type] == :convexA +# @test alpine.nonlinear_constrs[26][:convexified] == :false +# @test alpine.bounding_constr_mip[26][:sense] == :(<=) +# @test alpine.bounding_constr_mip[26][:coefs] == [3.0, 4.0] +# @test alpine.bounding_constr_mip[26][:vars] == [:(x[1]), :(x[2])] +# @test alpine.bounding_constr_mip[26][:rhs] == 200.0 +# @test alpine.bounding_constr_mip[26][:powers] == [4, 4] +# @test alpine.bounding_constr_mip[26][:cnt] == 2 +# end +# end + +# @testset "Expression Prasing || Linear Lifting" begin +# @testset "Expression Parsing || Linear Lifting || nlp2" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "partition_scaling_factor" => 8, +# "log_level" => 100, +# ) + +# m = nlp2(solver = test_solver) + +# alpine = _build(m) + +# @test length(alpine.linear_terms) == 2 +# @test length(alpine.nonconvex_terms) == 4 + +# lk = Vector{Any}(undef, 2) +# lk[1] = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, -1.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3)])), +# ) +# lk[2] = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, -2.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6)])), +# ) + +# @test length(keys(alpine.linear_terms)) == 2 +# yids = [4, 7] +# for i in 1:length(keys(alpine.linear_terms)) +# for j in keys(alpine.linear_terms) +# if alpine.linear_terms[j][:id] == i +# @test j == lk[i] +# @test j[:sign] == :+ +# @test j[:scalar] == lk[i][:scalar] +# @test j[:coef_var] == lk[i][:coef_var] +# @test alpine.linear_terms[j][:y_idx] == yids[i] +# end +# end +# end + +# @test haskey(alpine.linear_terms, lk[1]) +# @test haskey(alpine.linear_terms, lk[2]) + +# @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[2])]) +# @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[4])]) +# @test haskey(alpine.nonconvex_terms, [:(x[7]), :(x[7])]) +# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[1])]) +# @test alpine.nonconvex_terms[[:(x[1]), :(x[1])]][:id] == 1 +# @test alpine.nonconvex_terms[[:(x[2]), :(x[2])]][:id] == 3 +# @test alpine.nonconvex_terms[[:(x[4]), :(x[4])]][:id] == 2 +# @test alpine.nonconvex_terms[[:(x[7]), :(x[7])]][:id] == 4 +# @test alpine.nonconvex_terms[[:(x[1]), :(x[1])]][:lifted_var_ref].args[2] == 3 +# @test alpine.nonconvex_terms[[:(x[2]), :(x[2])]][:lifted_var_ref].args[2] == 6 +# @test alpine.nonconvex_terms[[:(x[4]), :(x[4])]][:lifted_var_ref].args[2] == 5 +# @test alpine.nonconvex_terms[[:(x[7]), :(x[7])]][:lifted_var_ref].args[2] == 8 +# end + +# @testset "Expression Parsing || Linear Lifting || general" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "log_level" => 100, +# ) + +# m = basic_linear_lift(solver = test_solver) + +# alpine = _build(m) # Setup internal model + +# lk = Vector{Any}(undef, 5) +# lk[1] = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1), (-1.0, 2)])), +# ) +# lk[2] = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(3.0, 2), (-1.0, 3)])), +# ) +# lk[3] = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1), (1.0, 3)])), +# ) +# lk[4] = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 2), (1.0, 1)])), +# ) +# lk[5] = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 3.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 2), (1.0, 1), (1.0, 3)])), +# ) + +# @test length(keys(alpine.linear_terms)) == 5 +# yids = [8, 9, 12, 14, 16] +# for i in 1:length(keys(alpine.linear_terms)) +# for j in keys(alpine.linear_terms) +# if alpine.linear_terms[j][:id] == i +# @test j == lk[i] +# @test j[:sign] == :+ +# @test j[:scalar] == lk[i][:scalar] +# @test j[:coef_var] == lk[i][:coef_var] +# @test alpine.linear_terms[j][:y_idx] == yids[i] +# end +# end +# end + +# nlk1 = [:(x[8]), :(x[9]), :(x[12])] +# nlk2 = [:(x[2]), :(x[2])] +# nlk3 = [:(x[2]), :(x[3])] +# nlk4 = [:(x[8]), :(x[8])] +# nlk5 = [:(x[1]), :(x[3])] +# nlk6 = [:(x[8]), :(x[9])] +# nlk7 = [:(x[1]), :(x[2])] +# nlk8 = [:(x[16]), :(x[15])] +# nlk9 = [:(x[14]), :(x[14])] + +# @test alpine.nonconvex_terms[nlk1][:id] == 7 +# @test alpine.nonconvex_terms[nlk2][:id] == 3 +# @test alpine.nonconvex_terms[nlk3][:id] == 4 +# @test alpine.nonconvex_terms[nlk4][:id] == 6 +# @test alpine.nonconvex_terms[nlk5][:id] == 2 +# @test alpine.nonconvex_terms[nlk6][:id] == 5 +# @test alpine.nonconvex_terms[nlk7][:id] == 1 +# @test alpine.nonconvex_terms[nlk8][:id] == 9 +# @test alpine.nonconvex_terms[nlk9][:id] == 8 + +# @test alpine.nonconvex_terms[nlk1][:lifted_var_ref].args[2] == 13 +# @test alpine.nonconvex_terms[nlk2][:lifted_var_ref].args[2] == 6 +# @test alpine.nonconvex_terms[nlk3][:lifted_var_ref].args[2] == 7 +# @test alpine.nonconvex_terms[nlk4][:lifted_var_ref].args[2] == 11 +# @test alpine.nonconvex_terms[nlk5][:lifted_var_ref].args[2] == 5 +# @test alpine.nonconvex_terms[nlk6][:lifted_var_ref].args[2] == 10 +# @test alpine.nonconvex_terms[nlk7][:lifted_var_ref].args[2] == 4 +# @test alpine.nonconvex_terms[nlk8][:lifted_var_ref].args[2] == 17 +# @test alpine.nonconvex_terms[nlk9][:lifted_var_ref].args[2] == 15 + +# @test alpine.nonconvex_terms[nlk1][:nonlinear_type] == :MULTILINEAR +# @test alpine.nonconvex_terms[nlk2][:nonlinear_type] == :MONOMIAL +# @test alpine.nonconvex_terms[nlk3][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[nlk4][:nonlinear_type] == :MONOMIAL +# @test alpine.nonconvex_terms[nlk5][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[nlk6][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[nlk7][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[nlk8][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[nlk9][:nonlinear_type] == :MONOMIAL + +# @test alpine.nonconvex_terms[nlk1][:var_idxs] == [8, 9, 12] +# @test alpine.nonconvex_terms[nlk2][:var_idxs] == [2, 2] +# @test alpine.nonconvex_terms[nlk3][:var_idxs] == [2, 3] +# @test alpine.nonconvex_terms[nlk4][:var_idxs] == [8] +# @test alpine.nonconvex_terms[nlk5][:var_idxs] == [1, 3] +# @test alpine.nonconvex_terms[nlk6][:var_idxs] == [8, 9] +# @test alpine.nonconvex_terms[nlk7][:var_idxs] == [1, 2] +# @test alpine.nonconvex_terms[nlk8][:var_idxs] == [16, 15] +# @test alpine.nonconvex_terms[nlk9][:var_idxs] == [14] +# end + +# @testset "Expression Parsing || Linear Lifting || brainpc3" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "partition_scaling_factor" => 8, +# "log_level" => 100, +# ) + +# m = brainpc3(solver = test_solver) + +# alpine = _build(m) + +# @test alpine.nonconvex_terms[Expr[:(x[6912]), :(x[6912])]][:y_idx] == 6913 +# @test alpine.nonconvex_terms[Expr[:(x[6912]), :(x[6912])]][:id] == 2 +# @test alpine.nonconvex_terms[Expr[:(x[6912]), :(x[6912])]][:lifted_constr_ref] == +# :(x[6913] == (*)(x[6912])) +# @test alpine.nonconvex_terms[Expr[:(x[6912]), :(x[6912])]][:nonlinear_type] == +# :MONOMIAL +# @test alpine.nonconvex_terms[Expr[:(x[6912]), :(x[6912])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6912]), :(x[6912])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6969])]][:y_idx] == 6970 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6969])]][:id] == 25 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6969])]][:lifted_constr_ref] == +# :(x[6970] == x[6903] * x[6969]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6969])]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6969])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6969])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6914])]][:y_idx] == 6915 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6914])]][:id] == 3 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6914])]][:lifted_constr_ref] == +# :(x[6915] == x[6903] * x[6914]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6914])]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6914])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6914])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6919])]][:y_idx] == 6920 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6919])]][:id] == 5 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6919])]][:lifted_constr_ref] == +# :(x[6920] == x[6903] * x[6919]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6919])]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6919])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6919])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6927]), :(x[6927])]][:y_idx] == 6928 +# @test alpine.nonconvex_terms[Expr[:(x[6927]), :(x[6927])]][:id] == 8 +# @test alpine.nonconvex_terms[Expr[:(x[6927]), :(x[6927])]][:lifted_constr_ref] == +# :(x[6928] == (*)(x[6927])) +# @test alpine.nonconvex_terms[Expr[:(x[6927]), :(x[6927])]][:nonlinear_type] == +# :MONOMIAL +# @test alpine.nonconvex_terms[Expr[:(x[6927]), :(x[6927])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6927]), :(x[6927])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6952]), :(x[6952])]][:y_idx] == 6953 +# @test alpine.nonconvex_terms[Expr[:(x[6952]), :(x[6952])]][:id] == 18 +# @test alpine.nonconvex_terms[Expr[:(x[6952]), :(x[6952])]][:lifted_constr_ref] == +# :(x[6953] == (*)(x[6952])) +# @test alpine.nonconvex_terms[Expr[:(x[6952]), :(x[6952])]][:nonlinear_type] == +# :MONOMIAL +# @test alpine.nonconvex_terms[Expr[:(x[6952]), :(x[6952])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6952]), :(x[6952])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6962]), :(x[6962])]][:y_idx] == 6963 +# @test alpine.nonconvex_terms[Expr[:(x[6962]), :(x[6962])]][:id] == 22 +# @test alpine.nonconvex_terms[Expr[:(x[6962]), :(x[6962])]][:lifted_constr_ref] == +# :(x[6963] == (*)(x[6962])) +# @test alpine.nonconvex_terms[Expr[:(x[6962]), :(x[6962])]][:nonlinear_type] == +# :MONOMIAL +# @test alpine.nonconvex_terms[Expr[:(x[6962]), :(x[6962])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6962]), :(x[6962])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6974])]][:y_idx] == 6975 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6974])]][:id] == 27 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6974])]][:lifted_constr_ref] == +# :(x[6975] == x[6903] * x[6974]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6974])]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6974])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6974])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6934])]][:y_idx] == 6935 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6934])]][:id] == 11 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6934])]][:lifted_constr_ref] == +# :(x[6935] == x[6903] * x[6934]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6934])]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6934])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6934])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6959])]][:y_idx] == 6960 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6959])]][:id] == 21 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6959])]][:lifted_constr_ref] == +# :(x[6960] == x[6903] * x[6959]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6959])]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6959])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6959])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7014])]][:y_idx] == 7015 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7014])]][:id] == 43 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7014])]][:lifted_constr_ref] == +# :(x[7015] == x[6903] * x[7014]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7014])]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7014])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7014])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6939])]][:y_idx] == 6940 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6939])]][:id] == 13 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6939])]][:lifted_constr_ref] == +# :(x[6940] == x[6903] * x[6939]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6939])]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6939])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6939])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[7017]), :(x[7017])]][:y_idx] == 7018 +# @test alpine.nonconvex_terms[Expr[:(x[7017]), :(x[7017])]][:id] == 44 +# @test alpine.nonconvex_terms[Expr[:(x[7017]), :(x[7017])]][:lifted_constr_ref] == +# :(x[7018] == (*)(x[7017])) +# @test alpine.nonconvex_terms[Expr[:(x[7017]), :(x[7017])]][:nonlinear_type] == +# :MONOMIAL +# @test alpine.nonconvex_terms[Expr[:(x[7017]), :(x[7017])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[7017]), :(x[7017])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6929])]][:y_idx] == 6930 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6929])]][:id] == 9 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6929])]][:lifted_constr_ref] == +# :(x[6930] == x[6903] * x[6929]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6929])]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6929])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6929])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[7012]), :(x[7012])]][:y_idx] == 7013 +# @test alpine.nonconvex_terms[Expr[:(x[7012]), :(x[7012])]][:id] == 42 +# @test alpine.nonconvex_terms[Expr[:(x[7012]), :(x[7012])]][:lifted_constr_ref] == +# :(x[7013] == (*)(x[7012])) +# @test alpine.nonconvex_terms[Expr[:(x[7012]), :(x[7012])]][:nonlinear_type] == +# :MONOMIAL +# @test alpine.nonconvex_terms[Expr[:(x[7012]), :(x[7012])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[7012]), :(x[7012])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6947]), :(x[6947])]][:y_idx] == 6948 +# @test alpine.nonconvex_terms[Expr[:(x[6947]), :(x[6947])]][:id] == 16 +# @test alpine.nonconvex_terms[Expr[:(x[6947]), :(x[6947])]][:lifted_constr_ref] == +# :(x[6948] == (*)(x[6947])) +# @test alpine.nonconvex_terms[Expr[:(x[6947]), :(x[6947])]][:nonlinear_type] == +# :MONOMIAL +# @test alpine.nonconvex_terms[Expr[:(x[6947]), :(x[6947])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6947]), :(x[6947])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[7032]), :(x[7032])]][:y_idx] == 7033 +# @test alpine.nonconvex_terms[Expr[:(x[7032]), :(x[7032])]][:id] == 50 +# @test alpine.nonconvex_terms[Expr[:(x[7032]), :(x[7032])]][:lifted_constr_ref] == +# :(x[7033] == (*)(x[7032])) +# @test alpine.nonconvex_terms[Expr[:(x[7032]), :(x[7032])]][:nonlinear_type] == +# :MONOMIAL +# @test alpine.nonconvex_terms[Expr[:(x[7032]), :(x[7032])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[7032]), :(x[7032])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6997]), :(x[6997])]][:y_idx] == 6998 +# @test alpine.nonconvex_terms[Expr[:(x[6997]), :(x[6997])]][:id] == 36 +# @test alpine.nonconvex_terms[Expr[:(x[6997]), :(x[6997])]][:lifted_constr_ref] == +# :(x[6998] == (*)(x[6997])) +# @test alpine.nonconvex_terms[Expr[:(x[6997]), :(x[6997])]][:nonlinear_type] == +# :MONOMIAL +# @test alpine.nonconvex_terms[Expr[:(x[6997]), :(x[6997])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6997]), :(x[6997])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[7027]), :(x[7027])]][:y_idx] == 7028 +# @test alpine.nonconvex_terms[Expr[:(x[7027]), :(x[7027])]][:id] == 48 +# @test alpine.nonconvex_terms[Expr[:(x[7027]), :(x[7027])]][:lifted_constr_ref] == +# :(x[7028] == (*)(x[7027])) +# @test alpine.nonconvex_terms[Expr[:(x[7027]), :(x[7027])]][:nonlinear_type] == +# :MONOMIAL +# @test alpine.nonconvex_terms[Expr[:(x[7027]), :(x[7027])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[7027]), :(x[7027])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[7037]), :(x[7037])]][:y_idx] == 7038 +# @test alpine.nonconvex_terms[Expr[:(x[7037]), :(x[7037])]][:id] == 52 +# @test alpine.nonconvex_terms[Expr[:(x[7037]), :(x[7037])]][:lifted_constr_ref] == +# :(x[7038] == (*)(x[7037])) +# @test alpine.nonconvex_terms[Expr[:(x[7037]), :(x[7037])]][:nonlinear_type] == +# :MONOMIAL +# @test alpine.nonconvex_terms[Expr[:(x[7037]), :(x[7037])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[7037]), :(x[7037])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[7007]), :(x[7007])]][:y_idx] == 7008 +# @test alpine.nonconvex_terms[Expr[:(x[7007]), :(x[7007])]][:id] == 40 +# @test alpine.nonconvex_terms[Expr[:(x[7007]), :(x[7007])]][:lifted_constr_ref] == +# :(x[7008] == (*)(x[7007])) +# @test alpine.nonconvex_terms[Expr[:(x[7007]), :(x[7007])]][:nonlinear_type] == +# :MONOMIAL +# @test alpine.nonconvex_terms[Expr[:(x[7007]), :(x[7007])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[7007]), :(x[7007])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6964])]][:y_idx] == 6965 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6964])]][:id] == 23 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6964])]][:lifted_constr_ref] == +# :(x[6965] == x[6903] * x[6964]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6964])]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6964])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6964])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6924])]][:y_idx] == 6925 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6924])]][:id] == 7 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6924])]][:lifted_constr_ref] == +# :(x[6925] == x[6903] * x[6924]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6924])]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6924])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6924])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6979])]][:y_idx] == 6980 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6979])]][:id] == 29 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6979])]][:lifted_constr_ref] == +# :(x[6980] == x[6903] * x[6979]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6979])]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6979])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6979])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6994])]][:y_idx] == 6995 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6994])]][:id] == 35 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6994])]][:lifted_constr_ref] == +# :(x[6995] == x[6903] * x[6994]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6994])]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6994])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6994])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6972]), :(x[6972])]][:y_idx] == 6973 +# @test alpine.nonconvex_terms[Expr[:(x[6972]), :(x[6972])]][:id] == 26 +# @test alpine.nonconvex_terms[Expr[:(x[6972]), :(x[6972])]][:lifted_constr_ref] == +# :(x[6973] == (*)(x[6972])) +# @test alpine.nonconvex_terms[Expr[:(x[6972]), :(x[6972])]][:nonlinear_type] == +# :MONOMIAL +# @test alpine.nonconvex_terms[Expr[:(x[6972]), :(x[6972])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6972]), :(x[6972])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7019])]][:y_idx] == 7020 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7019])]][:id] == 45 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7019])]][:lifted_constr_ref] == +# :(x[7020] == x[6903] * x[7019]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7019])]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7019])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7019])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6992]), :(x[6992])]][:y_idx] == 6993 +# @test alpine.nonconvex_terms[Expr[:(x[6992]), :(x[6992])]][:id] == 34 +# @test alpine.nonconvex_terms[Expr[:(x[6992]), :(x[6992])]][:lifted_constr_ref] == +# :(x[6993] == (*)(x[6992])) +# @test alpine.nonconvex_terms[Expr[:(x[6992]), :(x[6992])]][:nonlinear_type] == +# :MONOMIAL +# @test alpine.nonconvex_terms[Expr[:(x[6992]), :(x[6992])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6992]), :(x[6992])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[7002]), :(x[7002])]][:y_idx] == 7003 +# @test alpine.nonconvex_terms[Expr[:(x[7002]), :(x[7002])]][:id] == 38 +# @test alpine.nonconvex_terms[Expr[:(x[7002]), :(x[7002])]][:lifted_constr_ref] == +# :(x[7003] == (*)(x[7002])) +# @test alpine.nonconvex_terms[Expr[:(x[7002]), :(x[7002])]][:nonlinear_type] == +# :MONOMIAL +# @test alpine.nonconvex_terms[Expr[:(x[7002]), :(x[7002])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[7002]), :(x[7002])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[7022]), :(x[7022])]][:y_idx] == 7023 +# @test alpine.nonconvex_terms[Expr[:(x[7022]), :(x[7022])]][:id] == 46 +# @test alpine.nonconvex_terms[Expr[:(x[7022]), :(x[7022])]][:lifted_constr_ref] == +# :(x[7023] == (*)(x[7022])) +# @test alpine.nonconvex_terms[Expr[:(x[7022]), :(x[7022])]][:nonlinear_type] == +# :MONOMIAL +# @test alpine.nonconvex_terms[Expr[:(x[7022]), :(x[7022])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[7022]), :(x[7022])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6908])]][:y_idx] == 6909 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6908])]][:id] == 1 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6908])]][:lifted_constr_ref] == +# :(x[6909] == x[6903] * x[6908]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6908])]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6908])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6908])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6949])]][:y_idx] == 6950 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6949])]][:id] == 17 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6949])]][:lifted_constr_ref] == +# :(x[6950] == x[6903] * x[6949]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6949])]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6949])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6949])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7004])]][:y_idx] == 7005 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7004])]][:id] == 39 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7004])]][:lifted_constr_ref] == +# :(x[7005] == x[6903] * x[7004]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7004])]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7004])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7004])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6917]), :(x[6917])]][:y_idx] == 6918 +# @test alpine.nonconvex_terms[Expr[:(x[6917]), :(x[6917])]][:id] == 4 +# @test alpine.nonconvex_terms[Expr[:(x[6917]), :(x[6917])]][:lifted_constr_ref] == +# :(x[6918] == (*)(x[6917])) +# @test alpine.nonconvex_terms[Expr[:(x[6917]), :(x[6917])]][:nonlinear_type] == +# :MONOMIAL +# @test alpine.nonconvex_terms[Expr[:(x[6917]), :(x[6917])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6917]), :(x[6917])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6937]), :(x[6937])]][:y_idx] == 6938 +# @test alpine.nonconvex_terms[Expr[:(x[6937]), :(x[6937])]][:id] == 12 +# @test alpine.nonconvex_terms[Expr[:(x[6937]), :(x[6937])]][:lifted_constr_ref] == +# :(x[6938] == (*)(x[6937])) +# @test alpine.nonconvex_terms[Expr[:(x[6937]), :(x[6937])]][:nonlinear_type] == +# :MONOMIAL +# @test alpine.nonconvex_terms[Expr[:(x[6937]), :(x[6937])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6937]), :(x[6937])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6932]), :(x[6932])]][:y_idx] == 6933 +# @test alpine.nonconvex_terms[Expr[:(x[6932]), :(x[6932])]][:id] == 10 +# @test alpine.nonconvex_terms[Expr[:(x[6932]), :(x[6932])]][:lifted_constr_ref] == +# :(x[6933] == (*)(x[6932])) +# @test alpine.nonconvex_terms[Expr[:(x[6932]), :(x[6932])]][:nonlinear_type] == +# :MONOMIAL +# @test alpine.nonconvex_terms[Expr[:(x[6932]), :(x[6932])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6932]), :(x[6932])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6989])]][:y_idx] == 6990 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6989])]][:id] == 33 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6989])]][:lifted_constr_ref] == +# :(x[6990] == x[6903] * x[6989]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6989])]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6989])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6989])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6977]), :(x[6977])]][:y_idx] == 6978 +# @test alpine.nonconvex_terms[Expr[:(x[6977]), :(x[6977])]][:id] == 28 +# @test alpine.nonconvex_terms[Expr[:(x[6977]), :(x[6977])]][:lifted_constr_ref] == +# :(x[6978] == (*)(x[6977])) +# @test alpine.nonconvex_terms[Expr[:(x[6977]), :(x[6977])]][:nonlinear_type] == +# :MONOMIAL +# @test alpine.nonconvex_terms[Expr[:(x[6977]), :(x[6977])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6977]), :(x[6977])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6987]), :(x[6987])]][:y_idx] == 6988 +# @test alpine.nonconvex_terms[Expr[:(x[6987]), :(x[6987])]][:id] == 32 +# @test alpine.nonconvex_terms[Expr[:(x[6987]), :(x[6987])]][:lifted_constr_ref] == +# :(x[6988] == (*)(x[6987])) +# @test alpine.nonconvex_terms[Expr[:(x[6987]), :(x[6987])]][:nonlinear_type] == +# :MONOMIAL +# @test alpine.nonconvex_terms[Expr[:(x[6987]), :(x[6987])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6987]), :(x[6987])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7034])]][:y_idx] == 7035 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7034])]][:id] == 51 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7034])]][:lifted_constr_ref] == +# :(x[7035] == x[6903] * x[7034]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7034])]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7034])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7034])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6967]), :(x[6967])]][:y_idx] == 6968 +# @test alpine.nonconvex_terms[Expr[:(x[6967]), :(x[6967])]][:id] == 24 +# @test alpine.nonconvex_terms[Expr[:(x[6967]), :(x[6967])]][:lifted_constr_ref] == +# :(x[6968] == (*)(x[6967])) +# @test alpine.nonconvex_terms[Expr[:(x[6967]), :(x[6967])]][:nonlinear_type] == +# :MONOMIAL +# @test alpine.nonconvex_terms[Expr[:(x[6967]), :(x[6967])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6967]), :(x[6967])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6957]), :(x[6957])]][:y_idx] == 6958 +# @test alpine.nonconvex_terms[Expr[:(x[6957]), :(x[6957])]][:id] == 20 +# @test alpine.nonconvex_terms[Expr[:(x[6957]), :(x[6957])]][:lifted_constr_ref] == +# :(x[6958] == (*)(x[6957])) +# @test alpine.nonconvex_terms[Expr[:(x[6957]), :(x[6957])]][:nonlinear_type] == +# :MONOMIAL +# @test alpine.nonconvex_terms[Expr[:(x[6957]), :(x[6957])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6957]), :(x[6957])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7009])]][:y_idx] == 7010 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7009])]][:id] == 41 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7009])]][:lifted_constr_ref] == +# :(x[7010] == x[6903] * x[7009]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7009])]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7009])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7009])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6942]), :(x[6942])]][:y_idx] == 6943 +# @test alpine.nonconvex_terms[Expr[:(x[6942]), :(x[6942])]][:id] == 14 +# @test alpine.nonconvex_terms[Expr[:(x[6942]), :(x[6942])]][:lifted_constr_ref] == +# :(x[6943] == (*)(x[6942])) +# @test alpine.nonconvex_terms[Expr[:(x[6942]), :(x[6942])]][:nonlinear_type] == +# :MONOMIAL +# @test alpine.nonconvex_terms[Expr[:(x[6942]), :(x[6942])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6942]), :(x[6942])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6982]), :(x[6982])]][:y_idx] == 6983 +# @test alpine.nonconvex_terms[Expr[:(x[6982]), :(x[6982])]][:id] == 30 +# @test alpine.nonconvex_terms[Expr[:(x[6982]), :(x[6982])]][:lifted_constr_ref] == +# :(x[6983] == (*)(x[6982])) +# @test alpine.nonconvex_terms[Expr[:(x[6982]), :(x[6982])]][:nonlinear_type] == +# :MONOMIAL +# @test alpine.nonconvex_terms[Expr[:(x[6982]), :(x[6982])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6982]), :(x[6982])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6999])]][:y_idx] == 7000 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6999])]][:id] == 37 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6999])]][:lifted_constr_ref] == +# :(x[7000] == x[6903] * x[6999]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6999])]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6999])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6999])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6944])]][:y_idx] == 6945 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6944])]][:id] == 15 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6944])]][:lifted_constr_ref] == +# :(x[6945] == x[6903] * x[6944]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6944])]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6944])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6944])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7024])]][:y_idx] == 7025 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7024])]][:id] == 47 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7024])]][:lifted_constr_ref] == +# :(x[7025] == x[6903] * x[7024]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7024])]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7024])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7024])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6954])]][:y_idx] == 6955 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6954])]][:id] == 19 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6954])]][:lifted_constr_ref] == +# :(x[6955] == x[6903] * x[6954]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6954])]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6954])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6954])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6922]), :(x[6922])]][:y_idx] == 6923 +# @test alpine.nonconvex_terms[Expr[:(x[6922]), :(x[6922])]][:id] == 6 +# @test alpine.nonconvex_terms[Expr[:(x[6922]), :(x[6922])]][:lifted_constr_ref] == +# :(x[6923] == (*)(x[6922])) +# @test alpine.nonconvex_terms[Expr[:(x[6922]), :(x[6922])]][:nonlinear_type] == +# :MONOMIAL +# @test alpine.nonconvex_terms[Expr[:(x[6922]), :(x[6922])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6922]), :(x[6922])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6984])]][:y_idx] == 6985 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6984])]][:id] == 31 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6984])]][:lifted_constr_ref] == +# :(x[6985] == x[6903] * x[6984]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6984])]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6984])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6984])]][:constr_id] == +# Set(Any[0]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7029])]][:y_idx] == 7030 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7029])]][:id] == 49 +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7029])]][:lifted_constr_ref] == +# :(x[7030] == x[6903] * x[7029]) +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7029])]][:nonlinear_type] == +# :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7029])]][:y_type] == :Cont +# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7029])]][:constr_id] == +# Set(Any[0]) +# lk1 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6910), (-1.0, 6909)])), +# ) +# @test alpine.linear_terms[lk1][:y_idx] == 6911 +# @test alpine.linear_terms[lk1][:id] == 3 +# @test alpine.linear_terms[lk1][:y_type] == :(Cont) +# lk2 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3467), (1.0, 16)])), +# ) +# @test alpine.linear_terms[lk2][:y_idx] == 6908 +# @test alpine.linear_terms[lk2][:id] == 1 +# @test alpine.linear_terms[lk2][:y_type] == :(Cont) +# lk3 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}( +# :coef_var, +# Set(Any[(0.001548, 6903), (1.0, 7016), (1.0, 5702)]), +# ), +# ) +# @test alpine.linear_terms[lk3][:y_idx] == 7017 +# @test alpine.linear_terms[lk3][:id] == 67 +# @test alpine.linear_terms[lk3][:y_type] == :(Cont) +# lk4 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 5162), (1.0, 1711)])), +# ) +# @test alpine.linear_terms[lk4][:y_idx] == 7004 +# @test alpine.linear_terms[lk4][:id] == 59 +# @test alpine.linear_terms[lk4][:y_type] == :(Cont) +# lk5 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}( +# :coef_var, +# Set(Any[(1.0, 7021), (0.001435, 6903), (1.0, 6002)]), +# ), +# ) +# @test alpine.linear_terms[lk5][:y_idx] == 7022 +# @test alpine.linear_terms[lk5][:id] == 70 +# @test alpine.linear_terms[lk5][:y_type] == :(Cont) +# lk6 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6935), (1.0, 166)])), +# ) +# @test alpine.linear_terms[lk6][:y_idx] == 6936 +# @test alpine.linear_terms[lk6][:id] == 18 +# @test alpine.linear_terms[lk6][:y_type] == :(Cont) +# lk7 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}( +# :coef_var, +# Set(Any[(1.0, 4262), (0.00247, 6903), (1.0, 6981)]), +# ), +# ) +# @test alpine.linear_terms[lk7][:y_idx] == 6982 +# @test alpine.linear_terms[lk7][:id] == 46 +# @test alpine.linear_terms[lk7][:y_type] == :(Cont) +# lk8 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 7005), (1.0, 1711)])), +# ) +# @test alpine.linear_terms[lk8][:y_idx] == 7006 +# @test alpine.linear_terms[lk8][:id] == 60 +# @test alpine.linear_terms[lk8][:y_type] == :(Cont) +# lk9 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1951), (1.0, 5402)])), +# ) +# @test alpine.linear_terms[lk9][:y_idx] == 7009 +# @test alpine.linear_terms[lk9][:id] == 62 +# @test alpine.linear_terms[lk9][:y_type] == :(Cont) +# lk10 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 226), (-1.0, 6945)])), +# ) +# @test alpine.linear_terms[lk10][:y_idx] == 6946 +# @test alpine.linear_terms[lk10][:id] == 24 +# @test alpine.linear_terms[lk10][:y_type] == :(Cont) +# lk11 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 7030), (1.0, 3151)])), +# ) +# @test alpine.linear_terms[lk11][:y_idx] == 7031 +# @test alpine.linear_terms[lk11][:id] == 75 +# @test alpine.linear_terms[lk11][:y_type] == :(Cont) +# lk12 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}( +# :coef_var, +# Set(Any[(1.0, 6991), (1.0, 4622), (0.002066, 6903)]), +# ), +# ) +# @test alpine.linear_terms[lk12][:y_idx] == 6992 +# @test alpine.linear_terms[lk12][:id] == 52 +# @test alpine.linear_terms[lk12][:y_type] == :(Cont) +# lk13 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}( +# :coef_var, +# Set(Any[(1.0, 7026), (1.0, 6302), (0.001323, 6903)]), +# ), +# ) +# @test alpine.linear_terms[lk13][:y_idx] == 7027 +# @test alpine.linear_terms[lk13][:id] == 73 +# @test alpine.linear_terms[lk13][:y_type] == :(Cont) +# lk14 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 46), (1.0, 3497)])), +# ) +# @test alpine.linear_terms[lk14][:y_idx] == 6914 +# @test alpine.linear_terms[lk14][:id] == 5 +# @test alpine.linear_terms[lk14][:y_type] == :(Cont) +# lk15 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6960), (1.0, 391)])), +# ) +# @test alpine.linear_terms[lk15][:y_idx] == 6961 +# @test alpine.linear_terms[lk15][:id] == 33 +# @test alpine.linear_terms[lk15][:y_type] == :(Cont) +# lk16 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 631), (-1.0, 6975)])), +# ) +# @test alpine.linear_terms[lk16][:y_idx] == 6976 +# @test alpine.linear_terms[lk16][:id] == 42 +# @test alpine.linear_terms[lk16][:y_type] == :(Cont) +# lk17 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1351), (-1.0, 6995)])), +# ) +# @test alpine.linear_terms[lk17][:y_idx] == 6996 +# @test alpine.linear_terms[lk17][:id] == 54 +# @test alpine.linear_terms[lk17][:y_type] == :(Cont) +# lk18 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3557), (1.0, 106)])), +# ) +# @test alpine.linear_terms[lk18][:y_idx] == 6924 +# @test alpine.linear_terms[lk18][:id] == 11 +# @test alpine.linear_terms[lk18][:y_type] == :(Cont) +# lk19 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}( +# :coef_var, +# Set(Any[(1.0, 3647), (1.0, 6941), (0.004795, 6903)]), +# ), +# ) +# @test alpine.linear_terms[lk19][:y_idx] == 6942 +# @test alpine.linear_terms[lk19][:id] == 22 +# @test alpine.linear_terms[lk19][:y_type] == :(Cont) +# lk20 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3722), (1.0, 271)])), +# ) +# @test alpine.linear_terms[lk20][:y_idx] == 6949 +# @test alpine.linear_terms[lk20][:id] == 26 +# @test alpine.linear_terms[lk20][:y_type] == :(Cont) +# lk21 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3647), (1.0, 196)])), +# ) +# @test alpine.linear_terms[lk21][:y_idx] == 6939 +# @test alpine.linear_terms[lk21][:id] == 20 +# @test alpine.linear_terms[lk21][:y_type] == :(Cont) +# lk22 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}( +# :coef_var, +# Set(Any[(1.0, 3467), (1.0, 6911), (6.34e-6, 6903)]), +# ), +# ) +# @test alpine.linear_terms[lk22][:y_idx] == 6912 +# @test alpine.linear_terms[lk22][:id] == 4 +# @test alpine.linear_terms[lk22][:y_type] == :(Cont) +# lk23 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1531), (1.0, 4982)])), +# ) +# @test alpine.linear_terms[lk23][:y_idx] == 6999 +# @test alpine.linear_terms[lk23][:id] == 56 +# @test alpine.linear_terms[lk23][:y_type] == :(Cont) +# lk24 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 106), (-1.0, 6925)])), +# ) +# @test alpine.linear_terms[lk24][:y_idx] == 6926 +# @test alpine.linear_terms[lk24][:id] == 12 +# @test alpine.linear_terms[lk24][:y_type] == :(Cont) +# lk25 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 2251), (-1.0, 7015)])), +# ) +# @test alpine.linear_terms[lk25][:y_idx] == 7016 +# @test alpine.linear_terms[lk25][:id] == 66 +# @test alpine.linear_terms[lk25][:y_type] == :(Cont) +# lk26 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}( +# :coef_var, +# Set(Any[(1.0, 6936), (0.004985, 6903), (1.0, 3617)]), +# ), +# ) +# @test alpine.linear_terms[lk26][:y_idx] == 6937 +# @test alpine.linear_terms[lk26][:id] == 19 +# @test alpine.linear_terms[lk26][:y_type] == :(Cont) +# lk27 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6915), (1.0, 46)])), +# ) +# @test alpine.linear_terms[lk27][:y_idx] == 6916 +# @test alpine.linear_terms[lk27][:id] == 6 +# @test alpine.linear_terms[lk27][:y_type] == :(Cont) +# lk28 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}( +# :coef_var, +# Set(Any[(1.0, 3557), (0.005968, 6903), (1.0, 6926)]), +# ), +# ) +# @test alpine.linear_terms[lk28][:y_idx] == 6927 +# @test alpine.linear_terms[lk28][:id] == 13 +# @test alpine.linear_terms[lk28][:y_type] == :(Cont) +# lk29 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 271), (-1.0, 6950)])), +# ) +# @test alpine.linear_terms[lk29][:y_idx] == 6951 +# @test alpine.linear_terms[lk29][:id] == 27 +# @test alpine.linear_terms[lk29][:y_type] == :(Cont) +# lk30 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}( +# :coef_var, +# Set(Any[(0.002971, 6903), (1.0, 6971), (1.0, 3962)]), +# ), +# ) +# @test alpine.linear_terms[lk30][:y_idx] == 6972 +# @test alpine.linear_terms[lk30][:id] == 40 +# @test alpine.linear_terms[lk30][:y_type] == :(Cont) +# lk31 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 511), (-1.0, 6970)])), +# ) +# @test alpine.linear_terms[lk31][:y_idx] == 6971 +# @test alpine.linear_terms[lk31][:id] == 39 +# @test alpine.linear_terms[lk31][:y_type] == :(Cont) +# lk32 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}( +# :coef_var, +# Set(Any[(1.0, 7031), (1.0, 6602), (0.00121, 6903)]), +# ), +# ) +# @test alpine.linear_terms[lk32][:y_idx] == 7032 +# @test alpine.linear_terms[lk32][:id] == 76 +# @test alpine.linear_terms[lk32][:y_type] == :(Cont) +# lk33 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}( +# :coef_var, +# Set(Any[(0.00166, 6903), (1.0, 7011), (1.0, 5402)]), +# ), +# ) +# @test alpine.linear_terms[lk33][:y_idx] == 7012 +# @test alpine.linear_terms[lk33][:id] == 64 +# @test alpine.linear_terms[lk33][:y_type] == :(Cont) +# lk34 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, -0.003214), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 16)])), +# ) +# @test alpine.linear_terms[lk34][:y_idx] == 6910 +# @test alpine.linear_terms[lk34][:id] == 2 +# @test alpine.linear_terms[lk34][:y_type] == :(Cont) +# lk35 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 7035), (1.0, 3451)])), +# ) +# @test alpine.linear_terms[lk35][:y_idx] == 7036 +# @test alpine.linear_terms[lk35][:id] == 78 +# @test alpine.linear_terms[lk35][:y_type] == :(Cont) +# lk36 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 2551), (1.0, 6002)])), +# ) +# @test alpine.linear_terms[lk36][:y_idx] == 7019 +# @test alpine.linear_terms[lk36][:id] == 68 +# @test alpine.linear_terms[lk36][:y_type] == :(Cont) +# lk37 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3842), (1.0, 391)])), +# ) +# @test alpine.linear_terms[lk37][:y_idx] == 6959 +# @test alpine.linear_terms[lk37][:id] == 32 +# @test alpine.linear_terms[lk37][:y_type] == :(Cont) +# lk38 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}( +# :coef_var, +# Set(Any[(1.0, 6966), (0.00307, 6903), (1.0, 3902)]), +# ), +# ) +# @test alpine.linear_terms[lk38][:y_idx] == 6967 +# @test alpine.linear_terms[lk38][:id] == 37 +# @test alpine.linear_terms[lk38][:y_type] == :(Cont) +# lk39 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}( +# :coef_var, +# Set(Any[(1.0, 3722), (0.003829, 6903), (1.0, 6951)]), +# ), +# ) +# @test alpine.linear_terms[lk39][:y_idx] == 6952 +# @test alpine.linear_terms[lk39][:id] == 28 +# @test alpine.linear_terms[lk39][:y_type] == :(Cont) +# lk40 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 451), (1.0, 3902)])), +# ) +# @test alpine.linear_terms[lk40][:y_idx] == 6964 +# @test alpine.linear_terms[lk40][:id] == 35 +# @test alpine.linear_terms[lk40][:y_type] == :(Cont) +# lk41 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}( +# :coef_var, +# Set(Any[(1.0, 7006), (1.0, 5162), (0.001713, 6903)]), +# ), +# ) +# @test alpine.linear_terms[lk41][:y_idx] == 7007 +# @test alpine.linear_terms[lk41][:id] == 61 +# @test alpine.linear_terms[lk41][:y_type] == :(Cont) +# lk42 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 811), (-1.0, 6980)])), +# ) +# @test alpine.linear_terms[lk42][:y_idx] == 6981 +# @test alpine.linear_terms[lk42][:id] == 45 +# @test alpine.linear_terms[lk42][:y_type] == :(Cont) +# lk43 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}( +# :coef_var, +# Set(Any[(1.0, 7001), (1.0, 4982), (0.00173, 6903)]), +# ), +# ) +# @test alpine.linear_terms[lk43][:y_idx] == 7002 +# @test alpine.linear_terms[lk43][:id] == 58 +# @test alpine.linear_terms[lk43][:y_type] == :(Cont) +# lk44 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6920), (1.0, 76)])), +# ) +# @test alpine.linear_terms[lk44][:y_idx] == 6921 +# @test alpine.linear_terms[lk44][:id] == 9 +# @test alpine.linear_terms[lk44][:y_type] == :(Cont) +# lk45 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 4622), (1.0, 1171)])), +# ) +# @test alpine.linear_terms[lk45][:y_idx] == 6989 +# @test alpine.linear_terms[lk45][:id] == 50 +# @test alpine.linear_terms[lk45][:y_type] == :(Cont) +# lk46 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 991), (1.0, 4442)])), +# ) +# @test alpine.linear_terms[lk46][:y_idx] == 6984 +# @test alpine.linear_terms[lk46][:id] == 47 +# @test alpine.linear_terms[lk46][:y_type] == :(Cont) +# lk47 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6930), (1.0, 136)])), +# ) +# @test alpine.linear_terms[lk47][:y_idx] == 6931 +# @test alpine.linear_terms[lk47][:id] == 15 +# @test alpine.linear_terms[lk47][:y_type] == :(Cont) +# lk48 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}( +# :coef_var, +# Set(Any[(1.0, 4802), (0.001891, 6903), (1.0, 6996)]), +# ), +# ) +# @test alpine.linear_terms[lk48][:y_idx] == 6997 +# @test alpine.linear_terms[lk48][:id] == 55 +# @test alpine.linear_terms[lk48][:y_type] == :(Cont) +# lk49 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 511), (1.0, 3962)])), +# ) +# @test alpine.linear_terms[lk49][:y_idx] == 6969 +# @test alpine.linear_terms[lk49][:id] == 38 +# @test alpine.linear_terms[lk49][:y_type] == :(Cont) +# lk50 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 811), (1.0, 4262)])), +# ) +# @test alpine.linear_terms[lk50][:y_idx] == 6979 +# @test alpine.linear_terms[lk50][:id] == 44 +# @test alpine.linear_terms[lk50][:y_type] == :(Cont) +# lk51 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}( +# :coef_var, +# Set(Any[(0.01551, 6903), (1.0, 6916), (1.0, 3497)]), +# ), +# ) +# @test alpine.linear_terms[lk51][:y_idx] == 6917 +# @test alpine.linear_terms[lk51][:id] == 7 +# @test alpine.linear_terms[lk51][:y_type] == :(Cont) +# lk52 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 451), (-1.0, 6965)])), +# ) +# @test alpine.linear_terms[lk52][:y_idx] == 6966 +# @test alpine.linear_terms[lk52][:id] == 36 +# @test alpine.linear_terms[lk52][:y_type] == :(Cont) +# lk53 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}( +# :coef_var, +# Set(Any[(0.005773, 6903), (1.0, 3587), (1.0, 6931)]), +# ), +# ) +# @test alpine.linear_terms[lk53][:y_idx] == 6932 +# @test alpine.linear_terms[lk53][:id] == 16 +# @test alpine.linear_terms[lk53][:y_type] == :(Cont) +# lk54 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 631), (1.0, 4082)])), +# ) +# @test alpine.linear_terms[lk54][:y_idx] == 6974 +# @test alpine.linear_terms[lk54][:id] == 41 +# @test alpine.linear_terms[lk54][:y_type] == :(Cont) +# lk55 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 991), (-1.0, 6985)])), +# ) +# @test alpine.linear_terms[lk55][:y_idx] == 6986 +# @test alpine.linear_terms[lk55][:id] == 48 +# @test alpine.linear_terms[lk55][:y_type] == :(Cont) +# lk56 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 4802), (1.0, 1351)])), +# ) +# @test alpine.linear_terms[lk56][:y_idx] == 6994 +# @test alpine.linear_terms[lk56][:id] == 53 +# @test alpine.linear_terms[lk56][:y_type] == :(Cont) +# lk57 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}( +# :coef_var, +# Set(Any[(1.0, 6946), (0.004409, 6903), (1.0, 3677)]), +# ), +# ) +# @test alpine.linear_terms[lk57][:y_idx] == 6947 +# @test alpine.linear_terms[lk57][:id] == 25 +# @test alpine.linear_terms[lk57][:y_type] == :(Cont) +# lk58 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 2251), (1.0, 5702)])), +# ) +# @test alpine.linear_terms[lk58][:y_idx] == 7014 +# @test alpine.linear_terms[lk58][:id] == 65 +# @test alpine.linear_terms[lk58][:y_type] == :(Cont) +# lk59 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 7020), (1.0, 2551)])), +# ) +# @test alpine.linear_terms[lk59][:y_idx] == 7021 +# @test alpine.linear_terms[lk59][:id] == 69 +# @test alpine.linear_terms[lk59][:y_type] == :(Cont) +# lk60 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6940), (1.0, 196)])), +# ) +# @test alpine.linear_terms[lk60][:y_idx] == 6941 +# @test alpine.linear_terms[lk60][:id] == 21 +# @test alpine.linear_terms[lk60][:y_type] == :(Cont) +# lk61 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}( +# :coef_var, +# Set(Any[(1.0, 3527), (1.0, 6921), (0.008919, 6903)]), +# ), +# ) +# @test alpine.linear_terms[lk61][:y_idx] == 6922 +# @test alpine.linear_terms[lk61][:id] == 10 +# @test alpine.linear_terms[lk61][:y_type] == :(Cont) +# lk62 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 7025), (1.0, 2851)])), +# ) +# @test alpine.linear_terms[lk62][:y_idx] == 7026 +# @test alpine.linear_terms[lk62][:id] == 72 +# @test alpine.linear_terms[lk62][:y_type] == :(Cont) +# lk63 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}( +# :coef_var, +# Set(Any[(1.0, 6986), (1.0, 4442), (0.002252, 6903)]), +# ), +# ) +# @test alpine.linear_terms[lk63][:y_idx] == 6987 +# @test alpine.linear_terms[lk63][:id] == 49 +# @test alpine.linear_terms[lk63][:y_type] == :(Cont) +# lk64 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}( +# :coef_var, +# Set(Any[(0.002765, 6903), (1.0, 6976), (1.0, 4082)]), +# ), +# ) +# @test alpine.linear_terms[lk64][:y_idx] == 6977 +# @test alpine.linear_terms[lk64][:id] == 43 +# @test alpine.linear_terms[lk64][:y_type] == :(Cont) +# lk65 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}( +# :coef_var, +# Set(Any[(1.0, 6956), (0.003269, 6903), (1.0, 3782)]), +# ), +# ) +# @test alpine.linear_terms[lk65][:y_idx] == 6957 +# @test alpine.linear_terms[lk65][:id] == 31 +# @test alpine.linear_terms[lk65][:y_type] == :(Cont) +# lk66 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3587), (1.0, 136)])), +# ) +# @test alpine.linear_terms[lk66][:y_idx] == 6929 +# @test alpine.linear_terms[lk66][:id] == 14 +# @test alpine.linear_terms[lk66][:y_type] == :(Cont) +# lk67 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 166), (1.0, 3617)])), +# ) +# @test alpine.linear_terms[lk67][:y_idx] == 6934 +# @test alpine.linear_terms[lk67][:id] == 17 +# @test alpine.linear_terms[lk67][:y_type] == :(Cont) +# lk68 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 7010), (1.0, 1951)])), +# ) +# @test alpine.linear_terms[lk68][:y_idx] == 7011 +# @test alpine.linear_terms[lk68][:id] == 63 +# @test alpine.linear_terms[lk68][:y_type] == :(Cont) +# lk69 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}( +# :coef_var, +# Set(Any[(1.0, 7036), (0.001098, 6903), (1.0, 6902)]), +# ), +# ) +# @test alpine.linear_terms[lk69][:y_idx] == 7037 +# @test alpine.linear_terms[lk69][:id] == 79 +# @test alpine.linear_terms[lk69][:y_type] == :(Cont) +# lk70 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3527), (1.0, 76)])), +# ) +# @test alpine.linear_terms[lk70][:y_idx] == 6919 +# @test alpine.linear_terms[lk70][:id] == 8 +# @test alpine.linear_terms[lk70][:y_type] == :(Cont) +# lk71 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}( +# :coef_var, +# Set(Any[(1.0, 6961), (1.0, 3842), (0.00317, 6903)]), +# ), +# ) +# @test alpine.linear_terms[lk71][:y_idx] == 6962 +# @test alpine.linear_terms[lk71][:id] == 34 +# @test alpine.linear_terms[lk71][:y_type] == :(Cont) +# lk72 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6990), (1.0, 1171)])), +# ) +# @test alpine.linear_terms[lk72][:y_idx] == 6991 +# @test alpine.linear_terms[lk72][:id] == 51 +# @test alpine.linear_terms[lk72][:y_type] == :(Cont) +# lk73 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3451), (1.0, 6902)])), +# ) +# @test alpine.linear_terms[lk73][:y_idx] == 7034 +# @test alpine.linear_terms[lk73][:id] == 77 +# @test alpine.linear_terms[lk73][:y_type] == :(Cont) +# lk74 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6302), (1.0, 2851)])), +# ) +# @test alpine.linear_terms[lk74][:y_idx] == 7024 +# @test alpine.linear_terms[lk74][:id] == 71 +# @test alpine.linear_terms[lk74][:y_type] == :(Cont) +# lk75 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1531), (-1.0, 7000)])), +# ) +# @test alpine.linear_terms[lk75][:y_idx] == 7001 +# @test alpine.linear_terms[lk75][:id] == 57 +# @test alpine.linear_terms[lk75][:y_type] == :(Cont) +# lk76 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3151), (1.0, 6602)])), +# ) +# @test alpine.linear_terms[lk76][:y_idx] == 7029 +# @test alpine.linear_terms[lk76][:id] == 74 +# @test alpine.linear_terms[lk76][:y_type] == :(Cont) +# lk77 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3782), (1.0, 331)])), +# ) +# @test alpine.linear_terms[lk77][:y_idx] == 6954 +# @test alpine.linear_terms[lk77][:id] == 29 +# @test alpine.linear_terms[lk77][:y_type] == :(Cont) +# lk78 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6955), (1.0, 331)])), +# ) +# @test alpine.linear_terms[lk78][:y_idx] == 6956 +# @test alpine.linear_terms[lk78][:id] == 30 +# @test alpine.linear_terms[lk78][:y_type] == :(Cont) +# lk79 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 226), (1.0, 3677)])), +# ) +# @test alpine.linear_terms[lk79][:y_idx] == 6944 +# @test alpine.linear_terms[lk79][:id] == 23 +# @test alpine.linear_terms[lk79][:y_type] == :(Cont) +# end +# end + +# @testset "Expression Parsing || Basic Multiplication Operators (Machine Generated for diffs)" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "minlp_solver" => JUNIPER, +# "mip_solver" => HIGHS, +# "log_level" => 100, +# ) + +# m = operator_basic(solver = test_solver) +# JuMP.set_optimize_hook(m, MOI.Utilities.attach_optimizer) +# JuMP.optimize!(m) +# JuMP.set_optimize_hook(m, nothing) +# alpine = JuMP.backend(m).optimizer.model +# Alpine.load!(alpine) + +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4])]][:y_idx] == 31 +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4])]][:id] == 27 +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4])]][:lifted_constr_ref] == +# :(x[31] == x[3] * x[4]) +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[76])]][:y_idx] == 83 +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[76])]][:id] == 79 +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[76])]][:lifted_constr_ref] == +# :(x[83] == x[4] * x[5] * x[76]) +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[76])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[2])]][:y_idx] == 9 +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[2])]][:id] == 5 +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[2])]][:lifted_constr_ref] == +# :(x[9] == (*)(x[2])) +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[2])]][:nonlinear_type] == :MONOMIAL +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7])]][:y_idx] == 19 +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7])]][:id] == 15 +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7])]][:lifted_constr_ref] == +# :(x[19] == x[5] * x[7]) +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[31])]][:y_idx] == 32 +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[31])]][:id] == 28 +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[31])]][:lifted_constr_ref] == +# :(x[32] == x[2] * x[31]) +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[31])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10])]][:y_idx] == 49 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10])]][:id] == 45 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10])]][:lifted_constr_ref] == +# :(x[49] == x[1] * x[2] * x[10]) +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5]), :(x[9])]][:y_idx] == 50 +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5]), :(x[9])]][:id] == 46 +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5]), :(x[9])]][:lifted_constr_ref] == +# :(x[50] == x[3] * x[5] * x[9]) +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5]), :(x[9])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[47])]][:y_idx] == 69 +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[47])]][:id] == 65 +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[47])]][:lifted_constr_ref] == +# :(x[69] == x[4] * x[47]) +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[47])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[4])]][:y_idx] == 28 +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[4])]][:id] == 24 +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[4])]][:lifted_constr_ref] == +# :(x[28] == (*)(x[4])) +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[4])]][:nonlinear_type] == :MONOMIAL +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[10])]][:y_idx] == 37 +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[10])]][:id] == 33 +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[10])]][:lifted_constr_ref] == +# :(x[37] == x[4] * x[10]) +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[10])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[1])]][:y_idx] == 5 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[1])]][:id] == 1 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[1])]][:lifted_constr_ref] == +# :(x[5] == (*)(x[1])) +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[1])]][:nonlinear_type] == :MONOMIAL +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[95])]][:y_idx] == 96 +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[95])]][:id] == 92 +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[95])]][:lifted_constr_ref] == +# :(x[96] == x[5] * x[95]) +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[95])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[40])]][:y_idx] == 41 +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[40])]][:id] == 37 +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[40])]][:lifted_constr_ref] == +# :(x[41] == x[2] * x[40]) +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[40])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10])]][:y_idx] == 26 +# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10])]][:id] == 22 +# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10])]][:lifted_constr_ref] == +# :(x[26] == x[6] * x[10]) +# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[78]), :(x[28])]][:y_idx] == 84 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[78]), :(x[28])]][:id] == 80 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[78]), :(x[28])]][:lifted_constr_ref] == +# :(x[84] == x[1] * x[78] * x[28]) +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[78]), :(x[28])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[43])]][:y_idx] == 58 +# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[43])]][:id] == 54 +# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[43])]][:lifted_constr_ref] == +# :(x[58] == x[6] * x[43]) +# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[43])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[6]), :(x[10])]][:y_idx] == 106 +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[6]), :(x[10])]][:id] == 102 +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[6]), :(x[10])]][:lifted_constr_ref] == +# :(x[106] == x[4] * x[6] * x[10]) +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[6]), :(x[10])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4]), :(x[10])]][:y_idx] == 90 +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4]), :(x[10])]][:id] == 86 +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4]), :(x[10])]][:lifted_constr_ref] == +# :(x[90] == x[2] * x[4] * x[10]) +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4]), :(x[10])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[41])]][:y_idx] == 42 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[41])]][:id] == 38 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[41])]][:lifted_constr_ref] == +# :(x[42] == x[1] * x[41]) +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[41])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[37])]][:y_idx] == 38 +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[37])]][:id] == 34 +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[37])]][:lifted_constr_ref] == +# :(x[38] == x[2] * x[37]) +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[37])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[85])]][:y_idx] == 87 +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[85])]][:id] == 83 +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[85])]][:lifted_constr_ref] == +# :(x[87] == x[5] * x[85]) +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[85])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5]), :(x[28])]][:y_idx] == 66 +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5]), :(x[28])]][:id] == 62 +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5]), :(x[28])]][:lifted_constr_ref] == +# :(x[66] == x[2] * x[3] * x[5] * x[28]) +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5]), :(x[28])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10])]][:y_idx] == 53 +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10])]][:id] == 49 +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10])]][:lifted_constr_ref] == +# :(x[53] == x[5] * x[9] * x[10]) +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6]), :(x[28])]][:y_idx] == 107 +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6]), :(x[28])]][:id] == 103 +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6]), :(x[28])]][:lifted_constr_ref] == +# :(x[107] == x[3] * x[6] * x[28]) +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6]), :(x[28])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5])]][:y_idx] == 17 +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5])]][:id] == 13 +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5])]][:lifted_constr_ref] == +# :(x[17] == x[2] * x[5]) +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[37])]][:y_idx] == 57 +# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[37])]][:id] == 53 +# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[37])]][:lifted_constr_ref] == +# :(x[57] == x[6] * x[37]) +# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[37])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7]), :(x[28])]][:y_idx] == 81 +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7]), :(x[28])]][:id] == 77 +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7]), :(x[28])]][:lifted_constr_ref] == +# :(x[81] == x[5] * x[7] * x[28]) +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7]), :(x[28])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[38])]][:y_idx] == 39 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[38])]][:id] == 35 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[38])]][:lifted_constr_ref] == +# :(x[39] == x[1] * x[38]) +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[38])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[9])]][:y_idx] == 48 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[9])]][:id] == 44 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[9])]][:lifted_constr_ref] == +# :(x[48] == x[1] * x[3] * x[9]) +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[9])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[23])]][:y_idx] == 24 +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[23])]][:id] == 20 +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[23])]][:lifted_constr_ref] == +# :(x[24] == x[4] * x[23]) +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[23])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[17])]][:y_idx] == 23 +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[17])]][:id] == 19 +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[17])]][:lifted_constr_ref] == +# :(x[23] == x[3] * x[17]) +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[17])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[10])]][:y_idx] == 51 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[10])]][:id] == 47 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[10])]][:lifted_constr_ref] == +# :(x[51] == x[1] * x[9] * x[10]) +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[10])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[7])]][:y_idx] == 75 +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[7])]][:id] == 71 +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[7])]][:lifted_constr_ref] == +# :(x[75] == x[4] * x[5] * x[7]) +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[7])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[28])]][:y_idx] == 95 +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[28])]][:id] == 91 +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[28])]][:lifted_constr_ref] == +# :(x[95] == x[9] * x[10] * x[28]) +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[28])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10])]][:y_idx] == 11 +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10])]][:id] == 7 +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10])]][:lifted_constr_ref] == +# :(x[11] == x[9] * x[10]) +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[37])]][:y_idx] == 100 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[37])]][:id] == 96 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[37])]][:lifted_constr_ref] == +# :(x[100] == x[1] * x[2] * x[37]) +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[37])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4]), :(x[5])]][:y_idx] == 62 +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4]), :(x[5])]][:id] == 58 +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4]), :(x[5])]][:lifted_constr_ref] == +# :(x[62] == x[2] * x[3] * x[4] * x[5]) +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4]), :(x[5])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[9]), :(x[10])]][:y_idx] == 65 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[9]), :(x[10])]][:id] == 61 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[9]), :(x[10])]][:lifted_constr_ref] == +# :(x[65] == x[1] * x[4] * x[9] * x[10]) +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[9]), :(x[10])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7]), :(x[28])]][:y_idx] == 80 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7]), :(x[28])]][:id] == 76 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7]), :(x[28])]][:lifted_constr_ref] == +# :(x[80] == x[1] * x[7] * x[28]) +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7]), :(x[28])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3])]][:y_idx] == 46 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3])]][:id] == 42 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3])]][:lifted_constr_ref] == +# :(x[46] == x[1] * x[2] * x[3]) +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[40])]][:y_idx] == 59 +# @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[40])]][:id] == 55 +# @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[40])]][:lifted_constr_ref] == +# :(x[59] == x[17] * x[40]) +# @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[40])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[85])]][:y_idx] == 86 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[85])]][:id] == 82 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[85])]][:lifted_constr_ref] == +# :(x[86] == x[1] * x[85]) +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[85])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[31])]][:y_idx] == 97 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[31])]][:id] == 93 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[31])]][:lifted_constr_ref] == +# :(x[97] == x[1] * x[2] * x[31]) +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[31])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[28])]][:y_idx] == 29 +# @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[28])]][:id] == 25 +# @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[28])]][:lifted_constr_ref] == +# :(x[29] == x[13] * x[28]) +# @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[28])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[28])]][:y_idx] == 92 +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[28])]][:id] == 88 +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[28])]][:lifted_constr_ref] == +# :(x[92] == x[2] * x[3] * x[28]) +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[28])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9])]][:y_idx] == 20 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9])]][:id] == 16 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9])]][:lifted_constr_ref] == +# :(x[20] == x[1] * x[9]) +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10]), :(x[28])]][:y_idx] == 109 +# @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10]), :(x[28])]][:id] == 105 +# @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10]), :(x[28])]][:lifted_constr_ref] == +# :(x[109] == x[14] * x[10] * x[28]) +# @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10]), :(x[28])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[92])]][:y_idx] == 93 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[92])]][:id] == 89 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[92])]][:lifted_constr_ref] == +# :(x[93] == x[1] * x[92]) +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[92])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4])]][:y_idx] == 85 +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4])]][:id] == 81 +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4])]][:lifted_constr_ref] == +# :(x[85] == x[2] * x[3] * x[4]) +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[11])]][:y_idx] == 16 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[11])]][:id] == 12 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[11])]][:lifted_constr_ref] == +# :(x[16] == x[1] * x[11]) +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[11])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[21])]][:y_idx] == 25 +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[21])]][:id] == 21 +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[21])]][:lifted_constr_ref] == +# :(x[25] == x[4] * x[21]) +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[21])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[53]), :(x[28])]][:y_idx] == 73 +# @test alpine.nonconvex_terms[Expr[:(x[53]), :(x[28])]][:id] == 69 +# @test alpine.nonconvex_terms[Expr[:(x[53]), :(x[28])]][:lifted_constr_ref] == +# :(x[73] == x[53] * x[28]) +# @test alpine.nonconvex_terms[Expr[:(x[53]), :(x[28])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[32])]][:y_idx] == 34 +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[32])]][:id] == 30 +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[32])]][:lifted_constr_ref] == +# :(x[34] == x[5] * x[32]) +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[32])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[28])]][:y_idx] == 40 +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[28])]][:id] == 36 +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[28])]][:lifted_constr_ref] == +# :(x[40] == x[3] * x[28]) +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[28])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10]), :(x[28])]][:y_idx] == 67 +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10]), :(x[28])]][:id] == 63 +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10]), :(x[28])]][:lifted_constr_ref] == +# :(x[67] == x[5] * x[9] * x[10] * x[28]) +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10]), :(x[28])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[43])]][:y_idx] == 102 +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[43])]][:id] == 98 +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[43])]][:lifted_constr_ref] == +# :(x[102] == x[5] * x[9] * x[43]) +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[43])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[26])]][:y_idx] == 27 +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[26])]][:id] == 23 +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[26])]][:lifted_constr_ref] == +# :(x[27] == x[4] * x[26]) +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[26])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[20]), :(x[31])]][:y_idx] == 56 +# @test alpine.nonconvex_terms[Expr[:(x[20]), :(x[31])]][:id] == 52 +# @test alpine.nonconvex_terms[Expr[:(x[20]), :(x[31])]][:lifted_constr_ref] == +# :(x[56] == x[20] * x[31]) +# @test alpine.nonconvex_terms[Expr[:(x[20]), :(x[31])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[4]), :(x[9])]][:y_idx] == 63 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[4]), :(x[9])]][:id] == 59 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[4]), :(x[9])]][:lifted_constr_ref] == +# :(x[63] == x[1] * x[3] * x[4] * x[9]) +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[4]), :(x[9])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10])]][:y_idx] == 15 +# @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10])]][:id] == 11 +# @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10])]][:lifted_constr_ref] == +# :(x[15] == x[14] * x[10]) +# @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[76])]][:y_idx] == 77 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[76])]][:id] == 73 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[76])]][:lifted_constr_ref] == +# :(x[77] == x[1] * x[4] * x[76]) +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[76])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[88])]][:y_idx] == 89 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[88])]][:id] == 85 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[88])]][:lifted_constr_ref] == +# :(x[89] == x[1] * x[88]) +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[88])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[90])]][:y_idx] == 94 +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[90])]][:id] == 90 +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[90])]][:lifted_constr_ref] == +# :(x[94] == x[5] * x[90]) +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[90])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10]), :(x[28])]][:y_idx] == 108 +# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10]), :(x[28])]][:id] == 104 +# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10]), :(x[28])]][:lifted_constr_ref] == +# :(x[108] == x[6] * x[10] * x[28]) +# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10]), :(x[28])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[48])]][:y_idx] == 70 +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[48])]][:id] == 66 +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[48])]][:lifted_constr_ref] == +# :(x[70] == x[4] * x[48]) +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[48])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[31])]][:y_idx] == 54 +# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[31])]][:id] == 50 +# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[31])]][:lifted_constr_ref] == +# :(x[54] == x[6] * x[31]) +# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[31])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[31])]][:y_idx] == 99 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[31])]][:id] == 95 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[31])]][:lifted_constr_ref] == +# :(x[99] == x[1] * x[9] * x[31]) +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[31])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[35])]][:y_idx] == 36 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[35])]][:id] == 32 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[35])]][:lifted_constr_ref] == +# :(x[36] == x[1] * x[35]) +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[35])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9])]][:y_idx] == 14 +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9])]][:id] == 10 +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9])]][:lifted_constr_ref] == +# :(x[14] == x[5] * x[9]) +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[13])]][:y_idx] == 22 +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[13])]][:id] == 18 +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[13])]][:lifted_constr_ref] == +# :(x[22] == x[4] * x[13]) +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[13])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10]), :(x[28])]][:y_idx] == 64 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10]), :(x[28])]][:id] == 60 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10]), :(x[28])]][:lifted_constr_ref] == +# :(x[64] == x[1] * x[2] * x[10] * x[28]) +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10]), :(x[28])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[46]), :(x[28])]][:y_idx] == 72 +# @test alpine.nonconvex_terms[Expr[:(x[46]), :(x[28])]][:id] == 68 +# @test alpine.nonconvex_terms[Expr[:(x[46]), :(x[28])]][:lifted_constr_ref] == +# :(x[72] == x[46] * x[28]) +# @test alpine.nonconvex_terms[Expr[:(x[46]), :(x[28])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[31])]][:y_idx] == 55 +# @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[31])]][:id] == 51 +# @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[31])]][:lifted_constr_ref] == +# :(x[55] == x[17] * x[31]) +# @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[31])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[31])]][:y_idx] == 98 +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[31])]][:id] == 94 +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[31])]][:lifted_constr_ref] == +# :(x[98] == x[2] * x[5] * x[31]) +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[31])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[28])]][:y_idx] == 43 +# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[28])]][:id] == 39 +# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[28])]][:lifted_constr_ref] == +# :(x[43] == x[10] * x[28]) +# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[28])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[10])]][:y_idx] == 78 +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[10])]][:id] == 74 +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[10])]][:lifted_constr_ref] == +# :(x[78] == x[2] * x[10]) +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[10])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[10])]][:y_idx] == 52 +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[10])]][:id] == 48 +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[10])]][:lifted_constr_ref] == +# :(x[52] == x[2] * x[5] * x[10]) +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[10])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[90])]][:y_idx] == 91 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[90])]][:id] == 87 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[90])]][:lifted_constr_ref] == +# :(x[91] == x[1] * x[90]) +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[90])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[17])]][:y_idx] == 104 +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[17])]][:id] == 100 +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[17])]][:lifted_constr_ref] == +# :(x[104] == x[3] * x[4] * x[17]) +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[17])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[9])]][:y_idx] == 76 +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[9])]][:id] == 72 +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[9])]][:lifted_constr_ref] == +# :(x[76] == x[3] * x[9]) +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[9])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[78])]][:y_idx] == 79 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[78])]][:id] == 75 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[78])]][:lifted_constr_ref] == +# :(x[79] == x[1] * x[4] * x[78]) +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[78])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[3])]][:y_idx] == 10 +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[3])]][:id] == 6 +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[3])]][:lifted_constr_ref] == +# :(x[10] == (*)(x[3])) +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[3])]][:nonlinear_type] == :MONOMIAL +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[49])]][:y_idx] == 71 +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[49])]][:id] == 67 +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[49])]][:lifted_constr_ref] == +# :(x[71] == x[4] * x[49]) +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[49])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[9])]][:y_idx] == 88 +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[9])]][:id] == 84 +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[9])]][:lifted_constr_ref] == +# :(x[88] == x[3] * x[4] * x[9]) +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[9])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[15]), :(x[28])]][:y_idx] == 30 +# @test alpine.nonconvex_terms[Expr[:(x[15]), :(x[28])]][:id] == 26 +# @test alpine.nonconvex_terms[Expr[:(x[15]), :(x[28])]][:lifted_constr_ref] == +# :(x[30] == x[15] * x[28]) +# @test alpine.nonconvex_terms[Expr[:(x[15]), :(x[28])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[46])]][:y_idx] == 68 +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[46])]][:id] == 64 +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[46])]][:lifted_constr_ref] == +# :(x[68] == x[4] * x[46]) +# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[46])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[11])]][:y_idx] == 12 +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[11])]][:id] == 8 +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[11])]][:lifted_constr_ref] == +# :(x[12] == x[5] * x[11]) +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[11])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[7])]][:y_idx] == 74 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[7])]][:id] == 70 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[7])]][:lifted_constr_ref] == +# :(x[74] == x[1] * x[4] * x[7]) +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[7])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[20])]][:y_idx] == 105 +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[20])]][:id] == 101 +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[20])]][:lifted_constr_ref] == +# :(x[105] == x[3] * x[4] * x[20]) +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[20])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[11])]][:y_idx] == 82 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[11])]][:id] == 78 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[11])]][:lifted_constr_ref] == +# :(x[82] == x[1] * x[4] * x[11]) +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[11])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[43])]][:y_idx] == 44 +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[43])]][:id] == 40 +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[43])]][:lifted_constr_ref] == +# :(x[44] == x[9] * x[43]) +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[43])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:y_idx] == 61 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:id] == 57 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:lifted_constr_ref] == +# :(x[61] == x[1] * x[2] * x[3] * x[4]) +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[10])]][:y_idx] == 18 +# @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[10])]][:id] == 14 +# @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[10])]][:lifted_constr_ref] == +# :(x[18] == x[17] * x[10]) +# @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[10])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7])]][:y_idx] == 8 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7])]][:id] == 4 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7])]][:lifted_constr_ref] == +# :(x[8] == x[1] * x[7]) +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2])]][:y_idx] == 6 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2])]][:id] == 2 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2])]][:lifted_constr_ref] == +# :(x[6] == x[1] * x[2]) +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[40])]][:y_idx] == 101 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[40])]][:id] == 97 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[40])]][:lifted_constr_ref] == +# :(x[101] == x[1] * x[2] * x[40]) +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[40])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[37])]][:y_idx] == 60 +# @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[37])]][:id] == 56 +# @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[37])]][:lifted_constr_ref] == +# :(x[60] == x[17] * x[37]) +# @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[37])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[6])]][:y_idx] == 103 +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[6])]][:id] == 99 +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[6])]][:lifted_constr_ref] == +# :(x[103] == x[3] * x[4] * x[6]) +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[6])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3])]][:y_idx] == 7 +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3])]][:id] == 3 +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3])]][:lifted_constr_ref] == +# :(x[7] == x[2] * x[3]) +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5])]][:y_idx] == 47 +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5])]][:id] == 43 +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5])]][:lifted_constr_ref] == +# :(x[47] == x[2] * x[3] * x[5]) +# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6])]][:y_idx] == 13 +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6])]][:id] == 9 +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6])]][:lifted_constr_ref] == +# :(x[13] == x[3] * x[6]) +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[31])]][:y_idx] == 35 +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[31])]][:id] == 31 +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[31])]][:lifted_constr_ref] == +# :(x[35] == x[9] * x[31]) +# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[31])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[32])]][:y_idx] == 33 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[32])]][:id] == 29 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[32])]][:lifted_constr_ref] == +# :(x[33] == x[1] * x[32]) +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[32])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[20])]][:y_idx] == 21 +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[20])]][:id] == 17 +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[20])]][:lifted_constr_ref] == +# :(x[21] == x[3] * x[20]) +# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[20])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[44])]][:y_idx] == 45 +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[44])]][:id] == 41 +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[44])]][:lifted_constr_ref] == +# :(x[45] == x[5] * x[44]) +# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[44])]][:nonlinear_type] == :BILINEAR + +# @test alpine.bounding_constr_mip[1][:rhs] == 1.0 +# @test alpine.bounding_constr_mip[1][:vars] == Any[:(x[5])] +# @test alpine.bounding_constr_mip[1][:coefs] == Any[1.0] +# @test alpine.bounding_constr_mip[1][:sense] == :(>=) +# @test alpine.bounding_constr_mip[1][:cnt] == 1 +# @test alpine.bounding_constr_mip[2][:rhs] == 1.0 +# @test alpine.bounding_constr_mip[2][:vars] == Any[:(x[6])] +# @test alpine.bounding_constr_mip[2][:coefs] == Any[1.0] +# @test alpine.bounding_constr_mip[2][:sense] == :(<=) +# @test alpine.bounding_constr_mip[2][:cnt] == 1 +# @test alpine.bounding_constr_mip[3][:rhs] == 1.0 +# @test alpine.bounding_constr_mip[3][:vars] == Any[:(x[5]), :(x[7])] +# @test alpine.bounding_constr_mip[3][:coefs] == Any[1.0, 1.0] +# @test alpine.bounding_constr_mip[3][:sense] == :(<=) +# @test alpine.bounding_constr_mip[3][:cnt] == 2 +# @test alpine.bounding_constr_mip[4][:rhs] == 1.0 +# @test alpine.bounding_constr_mip[4][:vars] == Any[:(x[8])] +# @test alpine.bounding_constr_mip[4][:coefs] == Any[1.0] +# @test alpine.bounding_constr_mip[4][:sense] == :(>=) +# @test alpine.bounding_constr_mip[4][:cnt] == 1 +# @test alpine.bounding_constr_mip[5][:rhs] == 1.0 +# @test alpine.bounding_constr_mip[5][:vars] == Any[:(x[12])] +# @test alpine.bounding_constr_mip[5][:coefs] == Any[1.0] +# @test alpine.bounding_constr_mip[5][:sense] == :(<=) +# @test alpine.bounding_constr_mip[5][:cnt] == 1 +# @test alpine.bounding_constr_mip[6][:rhs] == 1.0 +# @test alpine.bounding_constr_mip[6][:vars] == Any[:(x[13])] +# @test alpine.bounding_constr_mip[6][:coefs] == Any[1.0] +# @test alpine.bounding_constr_mip[6][:sense] == :(>=) +# @test alpine.bounding_constr_mip[6][:cnt] == 1 +# @test alpine.bounding_constr_mip[7][:rhs] == 1.0 +# @test alpine.bounding_constr_mip[7][:vars] == Any[:(x[15])] +# @test alpine.bounding_constr_mip[7][:coefs] == Any[1.0] +# @test alpine.bounding_constr_mip[7][:sense] == :(<=) +# @test alpine.bounding_constr_mip[7][:cnt] == 1 +# @test alpine.bounding_constr_mip[8][:rhs] == 1.0 +# @test alpine.bounding_constr_mip[8][:vars] == Any[:(x[16])] +# @test alpine.bounding_constr_mip[8][:coefs] == Any[1.0] +# @test alpine.bounding_constr_mip[8][:sense] == :(>=) +# @test alpine.bounding_constr_mip[8][:cnt] == 1 +# @test alpine.bounding_constr_mip[9][:rhs] == 1.0 +# @test alpine.bounding_constr_mip[9][:vars] == Any[:(x[18])] +# @test alpine.bounding_constr_mip[9][:coefs] == Any[1.0] +# @test alpine.bounding_constr_mip[9][:sense] == :(<=) +# @test alpine.bounding_constr_mip[9][:cnt] == 1 +# @test alpine.bounding_constr_mip[10][:rhs] == 1.0 +# @test alpine.bounding_constr_mip[10][:vars] == Any[:(x[19])] +# @test alpine.bounding_constr_mip[10][:coefs] == Any[1.0] +# @test alpine.bounding_constr_mip[10][:sense] == :(>=) +# @test alpine.bounding_constr_mip[10][:cnt] == 1 +# @test alpine.bounding_constr_mip[11][:rhs] == 1.0 +# @test alpine.bounding_constr_mip[11][:vars] == Any[:(x[21])] +# @test alpine.bounding_constr_mip[11][:coefs] == Any[1.0] +# @test alpine.bounding_constr_mip[11][:sense] == :(<=) +# @test alpine.bounding_constr_mip[11][:cnt] == 1 +# @test alpine.bounding_constr_mip[12][:rhs] == 1.0 +# @test alpine.bounding_constr_mip[12][:vars] == Any[:(x[22])] +# @test alpine.bounding_constr_mip[12][:coefs] == Any[1.0] +# @test alpine.bounding_constr_mip[12][:sense] == :(>=) +# @test alpine.bounding_constr_mip[12][:cnt] == 1 +# @test alpine.bounding_constr_mip[13][:rhs] == 1.0 +# @test alpine.bounding_constr_mip[13][:vars] == Any[:(x[24])] +# @test alpine.bounding_constr_mip[13][:coefs] == Any[1.0] +# @test alpine.bounding_constr_mip[13][:sense] == :(<=) +# @test alpine.bounding_constr_mip[13][:cnt] == 1 +# @test alpine.bounding_constr_mip[14][:rhs] == 1.0 +# @test alpine.bounding_constr_mip[14][:vars] == Any[:(x[25])] +# @test alpine.bounding_constr_mip[14][:coefs] == Any[1.0] +# @test alpine.bounding_constr_mip[14][:sense] == :(>=) +# @test alpine.bounding_constr_mip[14][:cnt] == 1 +# @test alpine.bounding_constr_mip[15][:rhs] == 1.0 +# @test alpine.bounding_constr_mip[15][:vars] == Any[:(x[27])] +# @test alpine.bounding_constr_mip[15][:coefs] == Any[1.0] +# @test alpine.bounding_constr_mip[15][:sense] == :(<=) +# @test alpine.bounding_constr_mip[15][:cnt] == 1 +# end + +# @testset "Expression Parsing || corner cases" begin +# @testset "Corner Cases - 1 : sign convertor special case" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "minlp_solver" => JUNIPER, +# "log_level" => 100, +# ) + +# m = Model(test_solver) +# @variable(m, 0 <= x[1:5] <= 1, Bin) +# @NLconstraint(m, x[1] + -x[2] >= 2) +# @objective(m, Min, x[1] + x[2]) +# alpine = _build(m) + +# @test alpine.bounding_constr_mip[1][:rhs] == 2.0 +# @test alpine.bounding_constr_mip[1][:vars] == Any[:(x[1]), :(x[2])] +# @test alpine.bounding_constr_mip[1][:coefs] == Any[1.0, -1.0] +# @test alpine.bounding_constr_mip[1][:sense] == :(>=) +# @test alpine.bounding_constr_mip[1][:cnt] == 2 +# end + +# @testset "Corner Cases - 2 : full sub-expression" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "log_level" => 100, +# ) + +# m = Model(test_solver) +# @variable(m, x[1:5] >= 0) +# @NLconstraint(m, (x[1] + 10 + 4 * x[2] + 200) * 5 >= 2 * 5) +# @constraint(m, x[1] + x[2] + 200 >= 2) +# @objective(m, Min, x[1] + x[2]) +# alpine = _build(m) + +# @test alpine.bounding_constr_mip[1][:rhs] == -198.0 +# @test alpine.bounding_constr_mip[1][:vars] == Any[:(x[1]), :(x[2])] +# @test alpine.bounding_constr_mip[1][:coefs] == Any[1.0, 1.0] +# @test alpine.bounding_constr_mip[1][:sense] == :(>=) +# @test alpine.bounding_constr_mip[1][:cnt] == 2 +# @test alpine.bounding_constr_mip[2][:rhs] == -1040.0 +# @test alpine.bounding_constr_mip[2][:vars] == Any[:(x[1]), :(x[2])] +# @test alpine.bounding_constr_mip[2][:coefs] == Any[5.0, 20.0] +# @test alpine.bounding_constr_mip[2][:sense] == :(>=) +# @test alpine.bounding_constr_mip[2][:cnt] == 2 +# end + +# @testset "Corner Cases - 2 : full sub-expression" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "log_level" => 100, +# ) + +# m = Model(test_solver) +# @variable(m, x[1:5] >= 0) +# @NLconstraint(m, (x[1] + 10 + 4 * x[2] + 200) * 5 >= 2 * 5) +# @constraint(m, x[1] + x[2] + 200 >= 2) +# @objective(m, Min, x[1] + x[2]) +# alpine = _build(m) + +# @test alpine.bounding_constr_mip[1][:rhs] == -198.0 +# @test alpine.bounding_constr_mip[1][:vars] == Any[:(x[1]), :(x[2])] +# @test alpine.bounding_constr_mip[1][:coefs] == Any[1.0, 1.0] +# @test alpine.bounding_constr_mip[1][:sense] == :(>=) +# @test alpine.bounding_constr_mip[1][:cnt] == 2 +# @test alpine.bounding_constr_mip[2][:rhs] == -1040.0 +# @test alpine.bounding_constr_mip[2][:vars] == Any[:(x[1]), :(x[2])] +# @test alpine.bounding_constr_mip[2][:coefs] == Any[5.0, 20.0] +# @test alpine.bounding_constr_mip[2][:sense] == :(>=) +# @test alpine.bounding_constr_mip[2][:cnt] == 2 +# end +# end + +# @testset "Expression Parsing || Discrete Multilinear" begin +# @testset "Expression Parsing || bmpl && binlin && binprod" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "minlp_solver" => JUNIPER, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "log_level" => 100, +# ) + +# m = bpml(solver = test_solver) + +# alpine = _build(m) # Setup internal model + +# @test length(keys(alpine.nonconvex_terms)) == 12 + +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[6])]][:y_idx] == 11 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2])]][:y_idx] == 12 +# @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[6])]][:y_idx] == 13 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3])]][:y_idx] == 14 +# @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[6])]][:y_idx] == 15 +# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[7])]][:y_idx] == 16 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[16])]][:y_idx] == 17 +# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[7]), :(x[8])]][:y_idx] == 18 +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[18])]][:y_idx] == 19 +# @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[18])]][:y_idx] == 20 +# @test alpine.nonconvex_terms[Expr[ +# :(x[1]), +# :(x[2]), +# :(x[3]), +# :(x[4]), +# :(x[5]), +# ]][:y_idx] == 21 +# @test alpine.nonconvex_terms[Expr[ +# :(x[6]), +# :(x[7]), +# :(x[9]), +# :(x[10]), +# :(x[6]), +# ]][:y_idx] == 22 + +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[6])]][:nonlinear_type] == :BINLIN +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2])]][:nonlinear_type] == :BINPROD +# @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[6])]][:nonlinear_type] == :BINLIN +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3])]][:nonlinear_type] == +# :BINPROD +# @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[6])]][:nonlinear_type] == :BINLIN +# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[7])]][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[16])]][:nonlinear_type] == :BINLIN +# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[7]), :(x[8])]][:nonlinear_type] == +# :MULTILINEAR +# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[18])]][:nonlinear_type] == :BINLIN +# @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[18])]][:nonlinear_type] == :BINLIN +# @test alpine.nonconvex_terms[Expr[ +# :(x[1]), +# :(x[2]), +# :(x[3]), +# :(x[4]), +# :(x[5]), +# ]][:nonlinear_type] == :BINPROD +# @test alpine.nonconvex_terms[Expr[ +# :(x[6]), +# :(x[7]), +# :(x[9]), +# :(x[10]), +# :(x[6]), +# ]][:nonlinear_type] == :MULTILINEAR + +# @test length(alpine.var_type) == 22 +# @test alpine.var_type[11] == :Cont +# @test alpine.var_type[12] == :Bin +# @test alpine.var_type[13] == :Cont +# @test alpine.var_type[14] == :Bin +# @test alpine.var_type[15] == :Cont +# @test alpine.var_type[16] == :Cont +# @test alpine.var_type[17] == :Cont +# @test alpine.var_type[18] == :Cont +# @test alpine.var_type[19] == :Cont +# @test alpine.var_type[20] == :Cont +# @test alpine.var_type[21] == :Bin +# @test alpine.var_type[22] == :Cont +# end + +# @testset "Expression Parsing || bmpl && binlin && binprod with linear lifting and coefficients" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "minlp_solver" => JUNIPER, +# "nlp_solver" => IPOPT, +# "mip_solver" => HIGHS, +# "log_level" => 100, +# ) + +# m = bmpl_linearlifting(solver = test_solver) + +# alpine = _build(m) + +# lk1 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1), (1.0, 17)])), +# ) +# lk2 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 11), (1.0, 12)])), +# ) +# lk3 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 7), (2.0, 6)])), +# ) +# lk4 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6), (1.0, 19)])), +# ) +# lk5 = Dict{Symbol,Any}( +# Pair{Symbol,Any}(:sign, :+), +# Pair{Symbol,Any}(:scalar, 0.0), +# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6), (1.0, 25)])), +# ) + +# @test haskey(alpine.linear_terms, lk1) +# @test haskey(alpine.linear_terms, lk2) +# @test haskey(alpine.linear_terms, lk3) +# @test haskey(alpine.linear_terms, lk4) +# @test haskey(alpine.linear_terms, lk5) + +# @test alpine.linear_terms[lk1][:lifted_constr_ref] == :(x[20] == x[1] + x[17]) +# @test alpine.linear_terms[lk2][:lifted_constr_ref] == :(x[13] == x[11] + x[12]) +# @test alpine.linear_terms[lk3][:lifted_constr_ref] == :(x[15] == 2 * x[6] + x[7]) +# @test alpine.linear_terms[lk4][:lifted_constr_ref] == :(x[21] == x[6] + x[19]) +# @test alpine.linear_terms[lk5][:lifted_constr_ref] == :(x[26] == x[6] + x[25]) + +# @test alpine.linear_terms[lk1][:y_idx] == 20 +# @test alpine.linear_terms[lk2][:y_idx] == 13 +# @test alpine.linear_terms[lk3][:y_idx] == 15 +# @test alpine.linear_terms[lk4][:y_idx] == 21 +# @test alpine.linear_terms[lk5][:y_idx] == 26 + +# @test alpine.linear_terms[lk1][:y_type] == :Cont +# @test alpine.linear_terms[lk2][:y_type] == :Cont +# @test alpine.linear_terms[lk3][:y_type] == :Cont +# @test alpine.linear_terms[lk4][:y_type] == :Cont +# @test alpine.linear_terms[lk5][:y_type] == :Cont + +# nlk1 = Expr[:(x[18]), :(x[7])] +# nlk2 = Expr[:(x[6]), :(x[7]), :(x[8])] +# nlk3 = Expr[:(x[7]), :(x[10])] +# nlk4 = Expr[:(x[2]), :(x[26])] +# nlk5 = Expr[:(x[1]), :(x[13])] +# nlk6 = Expr[:(x[1]), :(x[15])] +# nlk7 = Expr[:(x[2]), :(x[6])] +# nlk8 = Expr[:(x[24]), :(x[23])] +# nlk9 = Expr[:(x[1]), :(x[2])] +# nlk10 = Expr[:(x[2]), :(x[3])] +# nlk11 = Expr[:(x[20]), :(x[21])] +# nlk12 = Expr[:(x[3]), :(x[4])] + +# @test haskey(alpine.nonconvex_terms, nlk1) +# @test haskey(alpine.nonconvex_terms, nlk2) +# @test haskey(alpine.nonconvex_terms, nlk3) +# @test haskey(alpine.nonconvex_terms, nlk4) +# @test haskey(alpine.nonconvex_terms, nlk5) +# @test haskey(alpine.nonconvex_terms, nlk6) +# @test haskey(alpine.nonconvex_terms, nlk7) +# @test haskey(alpine.nonconvex_terms, nlk8) +# @test haskey(alpine.nonconvex_terms, nlk9) +# @test haskey(alpine.nonconvex_terms, nlk10) +# @test haskey(alpine.nonconvex_terms, nlk11) +# @test haskey(alpine.nonconvex_terms, nlk12) + +# @test alpine.nonconvex_terms[nlk1][:id] == 7 +# @test alpine.nonconvex_terms[nlk2][:id] == 1 +# @test alpine.nonconvex_terms[nlk3][:id] == 9 +# @test alpine.nonconvex_terms[nlk4][:id] == 12 +# @test alpine.nonconvex_terms[nlk5][:id] == 3 +# @test alpine.nonconvex_terms[nlk6][:id] == 4 +# @test alpine.nonconvex_terms[nlk7][:id] == 5 +# @test alpine.nonconvex_terms[nlk8][:id] == 11 +# @test alpine.nonconvex_terms[nlk9][:id] == 6 +# @test alpine.nonconvex_terms[nlk10][:id] == 2 +# @test alpine.nonconvex_terms[nlk11][:id] == 8 +# @test alpine.nonconvex_terms[nlk12][:id] == 10 + +# @test alpine.nonconvex_terms[nlk1][:y_type] == :Cont +# @test alpine.nonconvex_terms[nlk2][:y_type] == :Cont +# @test alpine.nonconvex_terms[nlk3][:y_type] == :Cont +# @test alpine.nonconvex_terms[nlk4][:y_type] == :Cont +# @test alpine.nonconvex_terms[nlk5][:y_type] == :Cont +# @test alpine.nonconvex_terms[nlk6][:y_type] == :Cont +# @test alpine.nonconvex_terms[nlk7][:y_type] == :Cont +# @test alpine.nonconvex_terms[nlk8][:y_type] == :Cont +# @test alpine.nonconvex_terms[nlk9][:y_type] == :Bin +# @test alpine.nonconvex_terms[nlk10][:y_type] == :Bin +# @test alpine.nonconvex_terms[nlk11][:y_type] == :Cont +# @test alpine.nonconvex_terms[nlk12][:y_type] == :Bin + +# @test alpine.nonconvex_terms[nlk1][:y_idx] == 19 +# @test alpine.nonconvex_terms[nlk2][:y_idx] == 11 +# @test alpine.nonconvex_terms[nlk3][:y_idx] == 23 +# @test alpine.nonconvex_terms[nlk4][:y_idx] == 27 +# @test alpine.nonconvex_terms[nlk5][:y_idx] == 14 +# @test alpine.nonconvex_terms[nlk6][:y_idx] == 16 +# @test alpine.nonconvex_terms[nlk7][:y_idx] == 17 +# @test alpine.nonconvex_terms[nlk8][:y_idx] == 25 +# @test alpine.nonconvex_terms[nlk9][:y_idx] == 18 +# @test alpine.nonconvex_terms[nlk10][:y_idx] == 12 +# @test alpine.nonconvex_terms[nlk11][:y_idx] == 22 +# @test alpine.nonconvex_terms[nlk12][:y_idx] == 24 + +# @test alpine.nonconvex_terms[nlk1][:nonlinear_type] == :BINLIN +# @test alpine.nonconvex_terms[nlk2][:nonlinear_type] == :MULTILINEAR +# @test alpine.nonconvex_terms[nlk3][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[nlk4][:nonlinear_type] == :BINLIN +# @test alpine.nonconvex_terms[nlk5][:nonlinear_type] == :BINLIN +# @test alpine.nonconvex_terms[nlk6][:nonlinear_type] == :BINLIN +# @test alpine.nonconvex_terms[nlk7][:nonlinear_type] == :BINLIN +# @test alpine.nonconvex_terms[nlk8][:nonlinear_type] == :BINLIN +# @test alpine.nonconvex_terms[nlk9][:nonlinear_type] == :BINPROD +# @test alpine.nonconvex_terms[nlk10][:nonlinear_type] == :BINPROD +# @test alpine.nonconvex_terms[nlk11][:nonlinear_type] == :BILINEAR +# @test alpine.nonconvex_terms[nlk12][:nonlinear_type] == :BINPROD +# end +# end @testset "Expr dereferencing for @NLexpression" begin # Taken from Juniper.jl @@ -3647,11 +3647,12 @@ end "nlp_solver" => IPOPT, "mip_solver" => HIGHS, "presolve_bt" => true, + "linking_constraints" => false ) m = Model(test_solver) @variable(m, 0 <= x <= 1) - @variable(m, 0 <= z <= 1, Int) + @variable(m, 0 <= z <= 1, Bin) b_expr = @NLexpression(m, z / 1) @NLconstraint(m, 1.1 >= b_expr) an_expr = @NLexpression(m, x / 1) diff --git a/test/test_utility.jl b/test/test_utility.jl index 2c5d7e12..b55b42a8 100644 --- a/test/test_utility.jl +++ b/test/test_utility.jl @@ -107,7 +107,7 @@ end "nlp_solver" => IPOPT, "mip_solver" => PAVITO, "presolve_bt" => false, - "disc_ratio" => 5, + "partition_scaling_factor" => 5, "disc_consecutive_forbid" => false, ) @@ -122,7 +122,7 @@ end "nlp_solver" => IPOPT, "mip_solver" => PAVITO, "presolve_bt" => false, - "disc_ratio" => 5, + "partition_scaling_factor" => 5, "disc_consecutive_forbid" => true, ) From 4f05baf7f8b66173c8609b11872c58290b3b5b35 Mon Sep 17 00:00:00 2001 From: harshangrjn Date: Mon, 5 Sep 2022 19:34:27 -0600 Subject: [PATCH 13/18] formatting --- examples/JuMP_models.jl | 2 +- examples/MINLPs/mult3.jl | 294 ++++++++++++++++++++++++++++----- src/MOI_wrapper/MOI_wrapper.jl | 2 +- src/algorithm.jl | 20 ++- src/embedding.jl | 6 +- src/log.jl | 5 +- src/multilinear.jl | 37 +++-- src/relaxations.jl | 11 +- src/solver_options.jl | 3 +- test/test_algorithm.jl | 27 ++- test/test_expression.jl | 2 +- 11 files changed, 327 insertions(+), 82 deletions(-) diff --git a/examples/JuMP_models.jl b/examples/JuMP_models.jl index 3a2d7a87..e42e6ff8 100644 --- a/examples/JuMP_models.jl +++ b/examples/JuMP_models.jl @@ -10,4 +10,4 @@ include("MINLPs/exprstest.jl") include("MINLPs/linearlift.jl") include("MINLPs/multi.jl") include("MINLPs/mult3.jl") -include("MINLPs/rosenbrock.jl") \ No newline at end of file +include("MINLPs/rosenbrock.jl") diff --git a/examples/MINLPs/mult3.jl b/examples/MINLPs/mult3.jl index d0701563..e5bc1ee9 100644 --- a/examples/MINLPs/mult3.jl +++ b/examples/MINLPs/mult3.jl @@ -1,64 +1,282 @@ function linking_constraints_testing(; solver = nothing) m = JuMP.Model(solver) - - x_Idx = Any[1, 2, 3, 4] - @variable(m, 0 <= x[x_Idx] <= 1) - @variable(m, obj) - @objective(m, Min, obj) - @NLconstraint(m, e1, -(0.4931*x[1]*x[2] + - 0.6864*x[1]*x[3] - - 0.0577*x[1]*x[4] + - 0.3468*x[1]*x[2]*x[3] - - 0.6988*x[1]*x[3]*x[4] - - 0.9648*x[1]*x[2]*x[4]) + obj == 0.0) - - return m - end - -function m_10_3_0_100_1(; solver = nothing) - m = JuMP.Model(solver) - x_Idx = Any[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] - @variable(m, 0 <= x[x_Idx] <= 1) + x_Idx = Any[1, 2, 3, 4] + @variable(m, 0 <= x[x_Idx] <= 1) @variable(m, obj) @objective(m, Min, obj) - @NLconstraint(m, e1, -(0.4931*x[1]*x[2]+0.6864*x[1]*x[3]+0.0577*x[1]*x[4]+0.331*x[1]*x[5]+0.4615*x[1]*x[6]-0.1788*x[1]*x[7]-0.2886*x[1]*x[8]+0.4708*x[1]*x[9]-0.0574*x[1]*x[10]-0.0747*x[2]*x[3]+0.5194*x[2]*x[4]+0.4049*x[2]*x[5]-0.4841*x[2]*x[6]+0.8754*x[2]*x[7]-0.0878*x[2]*x[8]+0.617*x[2]*x[9]+0.8177*x[2]*x[10]+0.3898*x[3]*x[4]-0.561*x[3]*x[5]+0.7099*x[3]*x[6]+0.4888*x[3]*x[7]-0.3978*x[3]*x[8]+0.3439*x[3]*x[9]+0.2374*x[3]*x[10]+0.9351*x[4]*x[5]+0.9805*x[4]*x[6]-0.324*x[4]*x[7]+0.8415*x[4]*x[8]-0.3219*x[4]*x[9]+0.8619*x[4]*x[10]+0.0931*x[5]*x[6]-0.069*x[5]*x[7]-0.6462*x[5]*x[8]-0.244*x[5]*x[9]-0.6496*x[5]*x[10]-0.2863*x[6]*x[7]+0.3314*x[6]*x[8]+0.2371*x[6]*x[9]-0.0621*x[6]*x[10]-0.3675*x[7]*x[8]-0.4622*x[7]*x[9]-0.6002*x[7]*x[10]-0.1691*x[8]*x[9]+0.9586*x[8]*x[10]+0.0864*x[9]*x[10]-0.741*x[1]+0.6095*x[2]+0.6916*x[3]+0.4181*x[4]+0.0579*x[5]+0.3277*x[6]+0.8015*x[7]+0.8823*x[8]-0.7712*x[9]+0.7333*x[10]+0.9951*x[1]*x[2]*x[3]+0.1336*x[1]*x[2]*x[4]+0.9318*x[1]*x[2]*x[5]+0.4959*x[1]*x[2]*x[6]-0.2652*x[1]*x[2]*x[7]-0.0387*x[1]*x[2]*x[8]-0.8525*x[1]*x[2]*x[9]-0.9893*x[1]*x[2]*x[10]-0.3058*x[1]*x[3]*x[4]-0.3155*x[1]*x[3]*x[5]-0.5641*x[1]*x[3]*x[6]-0.7337*x[1]*x[3]*x[7]+0.801*x[1]*x[3]*x[8]-0.2265*x[1]*x[3]*x[9]-0.109*x[1]*x[3]*x[10]+0.3239*x[1]*x[4]*x[5]-0.9678*x[1]*x[4]*x[6]+0.3017*x[1]*x[4]*x[7]+0.2928*x[1]*x[4]*x[8]-0.354*x[1]*x[4]*x[9]+0.7114*x[1]*x[4]*x[10]-0.1974*x[1]*x[5]*x[6]-0.5863*x[1]*x[5]*x[7]+0.9371*x[1]*x[5]*x[8]+0.1968*x[1]*x[5]*x[9]+0.346*x[1]*x[5]*x[10]-0.0862*x[1]*x[6]*x[7]-0.34*x[1]*x[6]*x[8]-0.7992*x[1]*x[6]*x[9]+0.5109*x[1]*x[6]*x[10]+0.2114*x[1]*x[7]*x[8]+0.4381*x[1]*x[7]*x[9]+0.7947*x[1]*x[7]*x[10]+0.3165*x[1]*x[8]*x[9]-0.6986*x[1]*x[8]*x[10]+0.2246*x[1]*x[9]*x[10]+0.9573*x[2]*x[3]*x[4]+0.9983*x[2]*x[3]*x[5]-0.4864*x[2]*x[3]*x[6]+0.1017*x[2]*x[3]*x[7]+0.3181*x[2]*x[3]*x[8]+0.108*x[2]*x[3]*x[9]+0.9555*x[2]*x[3]*x[10]+0.8038*x[2]*x[4]*x[5]+0.3158*x[2]*x[4]*x[6]+0.4577*x[2]*x[4]*x[7]-0.1951*x[2]*x[4]*x[8]+0.8573*x[2]*x[4]*x[9]-0.7043*x[2]*x[4]*x[10]+0.3491*x[2]*x[5]*x[6]+0.5392*x[2]*x[5]*x[7]-0.3214*x[2]*x[5]*x[8]-0.7684*x[2]*x[5]*x[9]+0.2287*x[2]*x[5]*x[10]+0.6412*x[2]*x[6]*x[7]+0.8942*x[2]*x[6]*x[8]+0.4623*x[2]*x[6]*x[9]-0.0048*x[2]*x[6]*x[10]-0.2504*x[2]*x[7]*x[8]-0.157*x[2]*x[7]*x[9]+0.1058*x[2]*x[7]*x[10]+0.9958*x[2]*x[8]*x[9]+0.9808*x[2]*x[8]*x[10]+0.4926*x[2]*x[9]*x[10]+0.9075*x[3]*x[4]*x[5]-0.8135*x[3]*x[4]*x[6]+0.468*x[3]*x[4]*x[7]+0.5035*x[3]*x[4]*x[8]+0.8937*x[3]*x[4]*x[9]+0.4124*x[3]*x[4]*x[10]+0.6276*x[3]*x[5]*x[6]+0.1172*x[3]*x[5]*x[7]-0.8766*x[3]*x[5]*x[8]-0.0392*x[3]*x[5]*x[9]+0.1954*x[3]*x[5]*x[10]-0.7249*x[3]*x[6]*x[7]+0.1748*x[3]*x[6]*x[8]+0.0399*x[3]*x[6]*x[9]+0.7718*x[3]*x[6]*x[10]-0.3924*x[3]*x[7]*x[8]+0.3393*x[3]*x[7]*x[9]+0.3299*x[3]*x[7]*x[10]+0.0074*x[3]*x[8]*x[9]-0.4768*x[3]*x[8]*x[10]-0.8469*x[3]*x[9]*x[10]-0.7975*x[4]*x[5]*x[6]+0.0985*x[4]*x[5]*x[7]-0.2488*x[4]*x[5]*x[8]-0.9697*x[4]*x[5]*x[9]+0.5858*x[4]*x[5]*x[10]+0.2418*x[4]*x[6]*x[7]+0.5472*x[4]*x[6]*x[8]+0.9072*x[4]*x[6]*x[9]-0.7715*x[4]*x[6]*x[10]-0.3631*x[4]*x[7]*x[8]+0.1936*x[4]*x[7]*x[9]-0.9037*x[4]*x[7]*x[10]-0.7716*x[4]*x[8]*x[9]-0.5681*x[4]*x[8]*x[10]-0.7989*x[4]*x[9]*x[10]-0.8533*x[5]*x[6]*x[7]-0.5063*x[5]*x[6]*x[8]-0.1132*x[5]*x[6]*x[9]-0.5833*x[5]*x[6]*x[10]+0.134*x[5]*x[7]*x[8]-0.9514*x[5]*x[7]*x[9]-0.1594*x[5]*x[7]*x[10]-0.2043*x[5]*x[8]*x[9]+0.9532*x[5]*x[8]*x[10]+0.3852*x[5]*x[9]*x[10]-0.9901*x[6]*x[7]*x[8]-0.7402*x[6]*x[7]*x[9]-0.9064*x[6]*x[7]*x[10]+0.6796*x[6]*x[8]*x[9]+0.357*x[6]*x[8]*x[10]+0.1639*x[6]*x[9]*x[10]+0.4671*x[7]*x[8]*x[9]-0.7679*x[7]*x[8]*x[10]+0.6806*x[7]*x[9]*x[10]+0.67*x[8]*x[9]*x[10])+ obj == 0.0) + @NLconstraint( + m, + e1, + -( + 0.4931 * x[1] * x[2] + 0.6864 * x[1] * x[3] - 0.0577 * x[1] * x[4] + + 0.3468 * x[1] * x[2] * x[3] - 0.6988 * x[1] * x[3] * x[4] - + 0.9648 * x[1] * x[2] * x[4] + ) + obj == 0.0 + ) return m end -function m_10_3_0_100_2(; solver = nothing) +function m_10_3_0_100_1(; solver = nothing) m = JuMP.Model(solver) x_Idx = Any[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] - @variable(m, 0 <= x[x_Idx] <= 1) + @variable(m, 0 <= x[x_Idx] <= 1) @variable(m, obj) @objective(m, Min, obj) - @NLconstraint(m, e1, -(0.9844*x[1]*x[2]-0.5504*x[1]*x[3]+0.8946*x[1]*x[4]+0.6956*x[1]*x[5]+0.4003*x[1]*x[6]+0.1089*x[1]*x[7]-0.1168*x[1]*x[8]-0.5016*x[1]*x[9]+0.7953*x[1]*x[10]-0.7085*x[2]*x[3]-0.1308*x[2]*x[4]-0.0852*x[2]*x[5]-0.3812*x[2]*x[6]-0.0382*x[2]*x[7]+0.3795*x[2]*x[8]+0.6216*x[2]*x[9]-0.2157*x[2]*x[10]-0.4137*x[3]*x[4]+0.152*x[3]*x[5]+0.4507*x[3]*x[6]-0.7145*x[3]*x[7]-0.3329*x[3]*x[8]-0.6792*x[3]*x[9]+0.0692*x[3]*x[10]+0.4467*x[4]*x[5]-0.5436*x[4]*x[6]-0.602*x[4]*x[7]+0.9452*x[4]*x[8]+0.9871*x[4]*x[9]-0.8361*x[4]*x[10]-0.4982*x[5]*x[6]-0.5683*x[5]*x[7]-0.6084*x[5]*x[8]+0.7005*x[5]*x[9]-0.9106*x[5]*x[10]+0.7278*x[6]*x[7]-0.8657*x[6]*x[8]-0.1454*x[6]*x[9]-0.7254*x[6]*x[10]-0.7618*x[7]*x[8]-0.3881*x[7]*x[9]+0.2265*x[7]*x[10]+0.3273*x[8]*x[9]+0.7918*x[8]*x[10]+0.5074*x[9]*x[10]+0.2597*x[1]-0.558*x[2]-0.0323*x[3]+0.23*x[4]+0.9753*x[5]+0.1184*x[6]-0.2582*x[7]-0.3248*x[8]+0.4909*x[9]+0.1395*x[10]+0.2647*x[1]*x[2]*x[3]-0.5144*x[1]*x[2]*x[4]-0.6792*x[1]*x[2]*x[5]-0.9575*x[1]*x[2]*x[6]-0.6195*x[1]*x[2]*x[7]-0.3753*x[1]*x[2]*x[8]+0.6193*x[1]*x[2]*x[9]+0.1474*x[1]*x[2]*x[10]+0.6525*x[1]*x[3]*x[4]-0.4271*x[1]*x[3]*x[5]-0.679*x[1]*x[3]*x[6]-0.3382*x[1]*x[3]*x[7]-0.4683*x[1]*x[3]*x[8]+0.0896*x[1]*x[3]*x[9]+0.107*x[1]*x[3]*x[10]-0.9568*x[1]*x[4]*x[5]-0.7025*x[1]*x[4]*x[6]-0.7902*x[1]*x[4]*x[7]+0.2284*x[1]*x[4]*x[8]-0.1874*x[1]*x[4]*x[9]+0.8031*x[1]*x[4]*x[10]+0.8857*x[1]*x[5]*x[6]-0.6868*x[1]*x[5]*x[7]+0.8739*x[1]*x[5]*x[8]-0.7291*x[1]*x[5]*x[9]-0.2574*x[1]*x[5]*x[10]-0.357*x[1]*x[6]*x[7]+0.4299*x[1]*x[6]*x[8]+0.4594*x[1]*x[6]*x[9]-0.2428*x[1]*x[6]*x[10]+0.6579*x[1]*x[7]*x[8]+0.9073*x[1]*x[7]*x[9]-0.3832*x[1]*x[7]*x[10]+0.1595*x[1]*x[8]*x[9]-0.5331*x[1]*x[8]*x[10]+0.6888*x[1]*x[9]*x[10]-0.4837*x[2]*x[3]*x[4]+0.6795*x[2]*x[3]*x[5]+0.0753*x[2]*x[3]*x[6]+0.2431*x[2]*x[3]*x[7]-0.0184*x[2]*x[3]*x[8]-0.4303*x[2]*x[3]*x[9]-0.5289*x[2]*x[3]*x[10]+0.3028*x[2]*x[4]*x[5]+0.2143*x[2]*x[4]*x[6]-0.2037*x[2]*x[4]*x[7]+0.6976*x[2]*x[4]*x[8]+0.2752*x[2]*x[4]*x[9]-0.4824*x[2]*x[4]*x[10]-0.2823*x[2]*x[5]*x[6]+0.1237*x[2]*x[5]*x[7]-0.7571*x[2]*x[5]*x[8]+0.9569*x[2]*x[5]*x[9]-0.2336*x[2]*x[5]*x[10]+0.4414*x[2]*x[6]*x[7]-0.2835*x[2]*x[6]*x[8]+0.8198*x[2]*x[6]*x[9]+0.0874*x[2]*x[6]*x[10]+0.9194*x[2]*x[7]*x[8]+0.8589*x[2]*x[7]*x[9]+0.2666*x[2]*x[7]*x[10]-0.4088*x[2]*x[8]*x[9]-0.6505*x[2]*x[8]*x[10]+0.6852*x[2]*x[9]*x[10]+0.2372*x[3]*x[4]*x[5]+0.4118*x[3]*x[4]*x[6]-0.5151*x[3]*x[4]*x[7]+0.5959*x[3]*x[4]*x[8]-0.218*x[3]*x[4]*x[9]-0.7801*x[3]*x[4]*x[10]+0.5074*x[3]*x[5]*x[6]-0.9404*x[3]*x[5]*x[7]+0.4013*x[3]*x[5]*x[8]+0.0504*x[3]*x[5]*x[9]+0.5051*x[3]*x[5]*x[10]+0.2954*x[3]*x[6]*x[7]+0.7422*x[3]*x[6]*x[8]+0.6614*x[3]*x[6]*x[9]+0.9144*x[3]*x[6]*x[10]-0.5555*x[3]*x[7]*x[8]+0.159*x[3]*x[7]*x[9]+0.9815*x[3]*x[7]*x[10]+0.6799*x[3]*x[8]*x[9]-0.6504*x[3]*x[8]*x[10]+0.4191*x[3]*x[9]*x[10]-0.3969*x[4]*x[5]*x[6]-0.9499*x[4]*x[5]*x[7]+0.8335*x[4]*x[5]*x[8]+0.3776*x[4]*x[5]*x[9]+0.5135*x[4]*x[5]*x[10]+0.8655*x[4]*x[6]*x[7]-0.89*x[4]*x[6]*x[8]-0.0021*x[4]*x[6]*x[9]-0.881*x[4]*x[6]*x[10]-0.6563*x[4]*x[7]*x[8]+0.3767*x[4]*x[7]*x[9]-0.3868*x[4]*x[7]*x[10]+0.4704*x[4]*x[8]*x[9]+0.5043*x[4]*x[8]*x[10]-0.2086*x[4]*x[9]*x[10]-0.8244*x[5]*x[6]*x[7]-0.9021*x[5]*x[6]*x[8]+0.5587*x[5]*x[6]*x[9]+0.3616*x[5]*x[6]*x[10]-0.3769*x[5]*x[7]*x[8]+0.0455*x[5]*x[7]*x[9]+0.0116*x[5]*x[7]*x[10]-0.1229*x[5]*x[8]*x[9]+0.1753*x[5]*x[8]*x[10]-0.4053*x[5]*x[9]*x[10]-0.4102*x[6]*x[7]*x[8]-0.8524*x[6]*x[7]*x[9]+0.9499*x[6]*x[7]*x[10]+0.4563*x[6]*x[8]*x[9]+0.5162*x[6]*x[8]*x[10]-0.3816*x[6]*x[9]*x[10]-0.507*x[7]*x[8]*x[9]-0.4862*x[7]*x[8]*x[10]+0.2361*x[7]*x[9]*x[10]+0.8756*x[8]*x[9]*x[10])+obj == 0.0) + @NLconstraint( + m, + e1, + -( + 0.4931 * x[1] * x[2] + + 0.6864 * x[1] * x[3] + + 0.0577 * x[1] * x[4] + + 0.331 * x[1] * x[5] + + 0.4615 * x[1] * x[6] - 0.1788 * x[1] * x[7] - 0.2886 * x[1] * x[8] + + 0.4708 * x[1] * x[9] - 0.0574 * x[1] * x[10] - 0.0747 * x[2] * x[3] + + 0.5194 * x[2] * x[4] + + 0.4049 * x[2] * x[5] - 0.4841 * x[2] * x[6] + 0.8754 * x[2] * x[7] - + 0.0878 * x[2] * x[8] + + 0.617 * x[2] * x[9] + + 0.8177 * x[2] * x[10] + + 0.3898 * x[3] * x[4] - 0.561 * x[3] * x[5] + + 0.7099 * x[3] * x[6] + + 0.4888 * x[3] * x[7] - 0.3978 * x[3] * x[8] + + 0.3439 * x[3] * x[9] + + 0.2374 * x[3] * x[10] + + 0.9351 * x[4] * x[5] + + 0.9805 * x[4] * x[6] - 0.324 * x[4] * x[7] + 0.8415 * x[4] * x[8] - + 0.3219 * x[4] * x[9] + + 0.8619 * x[4] * x[10] + + 0.0931 * x[5] * x[6] - 0.069 * x[5] * x[7] - 0.6462 * x[5] * x[8] - + 0.244 * x[5] * x[9] - 0.6496 * x[5] * x[10] - 0.2863 * x[6] * x[7] + + 0.3314 * x[6] * x[8] + + 0.2371 * x[6] * x[9] - 0.0621 * x[6] * x[10] - 0.3675 * x[7] * x[8] - + 0.4622 * x[7] * x[9] - 0.6002 * x[7] * x[10] - 0.1691 * x[8] * x[9] + + 0.9586 * x[8] * x[10] + + 0.0864 * x[9] * x[10] - 0.741 * x[1] + + 0.6095 * x[2] + + 0.6916 * x[3] + + 0.4181 * x[4] + + 0.0579 * x[5] + + 0.3277 * x[6] + + 0.8015 * x[7] + + 0.8823 * x[8] - 0.7712 * x[9] + + 0.7333 * x[10] + + 0.9951 * x[1] * x[2] * x[3] + + 0.1336 * x[1] * x[2] * x[4] + + 0.9318 * x[1] * x[2] * x[5] + + 0.4959 * x[1] * x[2] * x[6] - 0.2652 * x[1] * x[2] * x[7] - + 0.0387 * x[1] * x[2] * x[8] - 0.8525 * x[1] * x[2] * x[9] - + 0.9893 * x[1] * x[2] * x[10] - 0.3058 * x[1] * x[3] * x[4] - + 0.3155 * x[1] * x[3] * x[5] - 0.5641 * x[1] * x[3] * x[6] - + 0.7337 * x[1] * x[3] * x[7] + 0.801 * x[1] * x[3] * x[8] - + 0.2265 * x[1] * x[3] * x[9] - 0.109 * x[1] * x[3] * x[10] + + 0.3239 * x[1] * x[4] * x[5] - 0.9678 * x[1] * x[4] * x[6] + + 0.3017 * x[1] * x[4] * x[7] + + 0.2928 * x[1] * x[4] * x[8] - 0.354 * x[1] * x[4] * x[9] + + 0.7114 * x[1] * x[4] * x[10] - 0.1974 * x[1] * x[5] * x[6] - + 0.5863 * x[1] * x[5] * x[7] + + 0.9371 * x[1] * x[5] * x[8] + + 0.1968 * x[1] * x[5] * x[9] + + 0.346 * x[1] * x[5] * x[10] - 0.0862 * x[1] * x[6] * x[7] - + 0.34 * x[1] * x[6] * x[8] - 0.7992 * x[1] * x[6] * x[9] + + 0.5109 * x[1] * x[6] * x[10] + + 0.2114 * x[1] * x[7] * x[8] + + 0.4381 * x[1] * x[7] * x[9] + + 0.7947 * x[1] * x[7] * x[10] + + 0.3165 * x[1] * x[8] * x[9] - 0.6986 * x[1] * x[8] * x[10] + + 0.2246 * x[1] * x[9] * x[10] + + 0.9573 * x[2] * x[3] * x[4] + + 0.9983 * x[2] * x[3] * x[5] - 0.4864 * x[2] * x[3] * x[6] + + 0.1017 * x[2] * x[3] * x[7] + + 0.3181 * x[2] * x[3] * x[8] + + 0.108 * x[2] * x[3] * x[9] + + 0.9555 * x[2] * x[3] * x[10] + + 0.8038 * x[2] * x[4] * x[5] + + 0.3158 * x[2] * x[4] * x[6] + + 0.4577 * x[2] * x[4] * x[7] - 0.1951 * x[2] * x[4] * x[8] + + 0.8573 * x[2] * x[4] * x[9] - 0.7043 * x[2] * x[4] * x[10] + + 0.3491 * x[2] * x[5] * x[6] + + 0.5392 * x[2] * x[5] * x[7] - 0.3214 * x[2] * x[5] * x[8] - + 0.7684 * x[2] * x[5] * x[9] + + 0.2287 * x[2] * x[5] * x[10] + + 0.6412 * x[2] * x[6] * x[7] + + 0.8942 * x[2] * x[6] * x[8] + + 0.4623 * x[2] * x[6] * x[9] - 0.0048 * x[2] * x[6] * x[10] - + 0.2504 * x[2] * x[7] * x[8] - 0.157 * x[2] * x[7] * x[9] + + 0.1058 * x[2] * x[7] * x[10] + + 0.9958 * x[2] * x[8] * x[9] + + 0.9808 * x[2] * x[8] * x[10] + + 0.4926 * x[2] * x[9] * x[10] + + 0.9075 * x[3] * x[4] * x[5] - 0.8135 * x[3] * x[4] * x[6] + + 0.468 * x[3] * x[4] * x[7] + + 0.5035 * x[3] * x[4] * x[8] + + 0.8937 * x[3] * x[4] * x[9] + + 0.4124 * x[3] * x[4] * x[10] + + 0.6276 * x[3] * x[5] * x[6] + + 0.1172 * x[3] * x[5] * x[7] - 0.8766 * x[3] * x[5] * x[8] - + 0.0392 * x[3] * x[5] * x[9] + 0.1954 * x[3] * x[5] * x[10] - + 0.7249 * x[3] * x[6] * x[7] + + 0.1748 * x[3] * x[6] * x[8] + + 0.0399 * x[3] * x[6] * x[9] + + 0.7718 * x[3] * x[6] * x[10] - 0.3924 * x[3] * x[7] * x[8] + + 0.3393 * x[3] * x[7] * x[9] + + 0.3299 * x[3] * x[7] * x[10] + + 0.0074 * x[3] * x[8] * x[9] - 0.4768 * x[3] * x[8] * x[10] - + 0.8469 * x[3] * x[9] * x[10] - 0.7975 * x[4] * x[5] * x[6] + + 0.0985 * x[4] * x[5] * x[7] - 0.2488 * x[4] * x[5] * x[8] - + 0.9697 * x[4] * x[5] * x[9] + + 0.5858 * x[4] * x[5] * x[10] + + 0.2418 * x[4] * x[6] * x[7] + + 0.5472 * x[4] * x[6] * x[8] + + 0.9072 * x[4] * x[6] * x[9] - 0.7715 * x[4] * x[6] * x[10] - + 0.3631 * x[4] * x[7] * x[8] + 0.1936 * x[4] * x[7] * x[9] - + 0.9037 * x[4] * x[7] * x[10] - 0.7716 * x[4] * x[8] * x[9] - + 0.5681 * x[4] * x[8] * x[10] - 0.7989 * x[4] * x[9] * x[10] - + 0.8533 * x[5] * x[6] * x[7] - 0.5063 * x[5] * x[6] * x[8] - + 0.1132 * x[5] * x[6] * x[9] - 0.5833 * x[5] * x[6] * x[10] + + 0.134 * x[5] * x[7] * x[8] - 0.9514 * x[5] * x[7] * x[9] - + 0.1594 * x[5] * x[7] * x[10] - 0.2043 * x[5] * x[8] * x[9] + + 0.9532 * x[5] * x[8] * x[10] + + 0.3852 * x[5] * x[9] * x[10] - 0.9901 * x[6] * x[7] * x[8] - + 0.7402 * x[6] * x[7] * x[9] - 0.9064 * x[6] * x[7] * x[10] + + 0.6796 * x[6] * x[8] * x[9] + + 0.357 * x[6] * x[8] * x[10] + + 0.1639 * x[6] * x[9] * x[10] + + 0.4671 * x[7] * x[8] * x[9] - 0.7679 * x[7] * x[8] * x[10] + + 0.6806 * x[7] * x[9] * x[10] + + 0.67 * x[8] * x[9] * x[10] + ) + obj == 0.0 + ) return m end -function m_10_3_10_100_1(; solver = nothing) +function m_10_3_0_100_2(; solver = nothing) m = JuMP.Model(solver) - x_Idx = Any[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] - @variable(m, 0 <= x[x_Idx] <= 1) + @variable(m, 0 <= x[x_Idx] <= 1) @variable(m, obj) @objective(m, Min, obj) - - @NLconstraint(m, e1, -(0.4931*x[1]*x[2]+0.6864*x[1]*x[3]+0.0577*x[1]*x[4]+0.331*x[1]*x[5]+0.4615*x[1]*x[6]-0.1788*x[1]*x[7]-0.2886*x[1]*x[8]+0.4708*x[1]*x[9]-0.0574*x[1]*x[10]-0.0747*x[2]*x[3]+0.5194*x[2]*x[4]+0.4049*x[2]*x[5]-0.4841*x[2]*x[6]+0.8754*x[2]*x[7]-0.0878*x[2]*x[8]+0.617*x[2]*x[9]+0.8177*x[2]*x[10]+0.3898*x[3]*x[4]-0.561*x[3]*x[5]+0.7099*x[3]*x[6]+0.4888*x[3]*x[7]-0.3978*x[3]*x[8]+0.3439*x[3]*x[9]+0.2374*x[3]*x[10]+0.9351*x[4]*x[5]+0.9805*x[4]*x[6]-0.324*x[4]*x[7]+0.8415*x[4]*x[8]-0.3219*x[4]*x[9]+0.8619*x[4]*x[10]+0.0931*x[5]*x[6]-0.069*x[5]*x[7]-0.6462*x[5]*x[8]-0.244*x[5]*x[9]-0.6496*x[5]*x[10]-0.2863*x[6]*x[7]+0.3314*x[6]*x[8]+0.2371*x[6]*x[9]-0.0621*x[6]*x[10]-0.3675*x[7]*x[8]-0.4622*x[7]*x[9]-0.6002*x[7]*x[10]-0.1691*x[8]*x[9]+0.9586*x[8]*x[10]+0.0864*x[9]*x[10]-0.741*x[1]+0.6095*x[2]+0.6916*x[3]+0.4181*x[4]+0.0579*x[5]+0.3277*x[6]+0.8015*x[7]+0.8823*x[8]-0.7712*x[9]+0.7333*x[10]+0.9951*x[1]*x[2]*x[3]+0.1336*x[1]*x[2]*x[4]+0.9318*x[1]*x[2]*x[5]+0.4959*x[1]*x[2]*x[6]-0.2652*x[1]*x[2]*x[7]-0.0387*x[1]*x[2]*x[8]-0.8525*x[1]*x[2]*x[9]-0.9893*x[1]*x[2]*x[10]-0.3058*x[1]*x[3]*x[4]-0.3155*x[1]*x[3]*x[5]-0.5641*x[1]*x[3]*x[6]-0.7337*x[1]*x[3]*x[7]+0.801*x[1]*x[3]*x[8]-0.2265*x[1]*x[3]*x[9]-0.109*x[1]*x[3]*x[10]+0.3239*x[1]*x[4]*x[5]-0.9678*x[1]*x[4]*x[6]+0.3017*x[1]*x[4]*x[7]+0.2928*x[1]*x[4]*x[8]-0.354*x[1]*x[4]*x[9]+0.7114*x[1]*x[4]*x[10]-0.1974*x[1]*x[5]*x[6]-0.5863*x[1]*x[5]*x[7]+0.9371*x[1]*x[5]*x[8]+0.1968*x[1]*x[5]*x[9]+0.346*x[1]*x[5]*x[10]-0.0862*x[1]*x[6]*x[7]-0.34*x[1]*x[6]*x[8]-0.7992*x[1]*x[6]*x[9]+0.5109*x[1]*x[6]*x[10]+0.2114*x[1]*x[7]*x[8]+0.4381*x[1]*x[7]*x[9]+0.7947*x[1]*x[7]*x[10]+0.3165*x[1]*x[8]*x[9]-0.6986*x[1]*x[8]*x[10]+0.2246*x[1]*x[9]*x[10]+0.9573*x[2]*x[3]*x[4]+0.9983*x[2]*x[3]*x[5]-0.4864*x[2]*x[3]*x[6]+0.1017*x[2]*x[3]*x[7]+0.3181*x[2]*x[3]*x[8]+0.108*x[2]*x[3]*x[9]+0.9555*x[2]*x[3]*x[10]+0.8038*x[2]*x[4]*x[5]+0.3158*x[2]*x[4]*x[6]+0.4577*x[2]*x[4]*x[7]-0.1951*x[2]*x[4]*x[8]+0.8573*x[2]*x[4]*x[9]-0.7043*x[2]*x[4]*x[10]+0.3491*x[2]*x[5]*x[6]+0.5392*x[2]*x[5]*x[7]-0.3214*x[2]*x[5]*x[8]-0.7684*x[2]*x[5]*x[9]+0.2287*x[2]*x[5]*x[10]+0.6412*x[2]*x[6]*x[7]+0.8942*x[2]*x[6]*x[8]+0.4623*x[2]*x[6]*x[9]-0.0048*x[2]*x[6]*x[10]-0.2504*x[2]*x[7]*x[8]-0.157*x[2]*x[7]*x[9]+0.1058*x[2]*x[7]*x[10]+0.9958*x[2]*x[8]*x[9]+0.9808*x[2]*x[8]*x[10]+0.4926*x[2]*x[9]*x[10]+0.9075*x[3]*x[4]*x[5]-0.8135*x[3]*x[4]*x[6]+0.468*x[3]*x[4]*x[7]+0.5035*x[3]*x[4]*x[8]+0.8937*x[3]*x[4]*x[9]+0.4124*x[3]*x[4]*x[10]+0.6276*x[3]*x[5]*x[6]+0.1172*x[3]*x[5]*x[7]-0.8766*x[3]*x[5]*x[8]-0.0392*x[3]*x[5]*x[9]+0.1954*x[3]*x[5]*x[10]-0.7249*x[3]*x[6]*x[7]+0.1748*x[3]*x[6]*x[8]+0.0399*x[3]*x[6]*x[9]+0.7718*x[3]*x[6]*x[10]-0.3924*x[3]*x[7]*x[8]+0.3393*x[3]*x[7]*x[9]+0.3299*x[3]*x[7]*x[10]+0.0074*x[3]*x[8]*x[9]-0.4768*x[3]*x[8]*x[10]-0.8469*x[3]*x[9]*x[10]-0.7975*x[4]*x[5]*x[6]+0.0985*x[4]*x[5]*x[7]-0.2488*x[4]*x[5]*x[8]-0.9697*x[4]*x[5]*x[9]+0.5858*x[4]*x[5]*x[10]+0.2418*x[4]*x[6]*x[7]+0.5472*x[4]*x[6]*x[8]+0.9072*x[4]*x[6]*x[9]-0.7715*x[4]*x[6]*x[10]-0.3631*x[4]*x[7]*x[8]+0.1936*x[4]*x[7]*x[9]-0.9037*x[4]*x[7]*x[10]-0.7716*x[4]*x[8]*x[9]-0.5681*x[4]*x[8]*x[10]-0.7989*x[4]*x[9]*x[10]-0.8533*x[5]*x[6]*x[7]-0.5063*x[5]*x[6]*x[8]-0.1132*x[5]*x[6]*x[9]-0.5833*x[5]*x[6]*x[10]+0.134*x[5]*x[7]*x[8]-0.9514*x[5]*x[7]*x[9]-0.1594*x[5]*x[7]*x[10]-0.2043*x[5]*x[8]*x[9]+0.9532*x[5]*x[8]*x[10]+0.3852*x[5]*x[9]*x[10]-0.9901*x[6]*x[7]*x[8]-0.7402*x[6]*x[7]*x[9]-0.9064*x[6]*x[7]*x[10]+0.6796*x[6]*x[8]*x[9]+0.357*x[6]*x[8]*x[10]+0.1639*x[6]*x[9]*x[10]+0.4671*x[7]*x[8]*x[9]-0.7679*x[7]*x[8]*x[10]+0.6806*x[7]*x[9]*x[10]+0.67*x[8]*x[9]*x[10])+obj == 0.0) - @NLconstraint(m, e2, 0.9844*x[1]*x[2]-0.5504*x[1]*x[3]+0.8946*x[1]*x[4]+0.6956*x[1]*x[5]+0.4003*x[1]*x[6]+0.1089*x[1]*x[7]-0.1168*x[1]*x[8]-0.5016*x[1]*x[9]+0.7953*x[1]*x[10]-0.7085*x[2]*x[3]-0.1308*x[2]*x[4]-0.0852*x[2]*x[5]-0.3812*x[2]*x[6]-0.0382*x[2]*x[7]+0.3795*x[2]*x[8]+0.6216*x[2]*x[9]-0.2157*x[2]*x[10]-0.4137*x[3]*x[4]+0.152*x[3]*x[5]+0.4507*x[3]*x[6]-0.7145*x[3]*x[7]-0.3329*x[3]*x[8]-0.6792*x[3]*x[9]+0.0692*x[3]*x[10]+0.4467*x[4]*x[5]-0.5436*x[4]*x[6]-0.602*x[4]*x[7]+0.9452*x[4]*x[8]+0.9871*x[4]*x[9]-0.8361*x[4]*x[10]-0.4982*x[5]*x[6]-0.5683*x[5]*x[7]-0.6084*x[5]*x[8]+0.7005*x[5]*x[9]-0.9106*x[5]*x[10]+0.7278*x[6]*x[7]-0.8657*x[6]*x[8]-0.1454*x[6]*x[9]-0.7254*x[6]*x[10]-0.7618*x[7]*x[8]-0.3881*x[7]*x[9]+0.2265*x[7]*x[10]+0.3273*x[8]*x[9]+0.7918*x[8]*x[10]+0.5074*x[9]*x[10]+0.2597*x[1]-0.558*x[2]-0.0323*x[3]+0.23*x[4]+0.9753*x[5]+0.1184*x[6]-0.2582*x[7]-0.3248*x[8]+0.4909*x[9]+0.1395*x[10]+0.2647*x[1]*x[2]*x[3]-0.5144*x[1]*x[2]*x[4]-0.6792*x[1]*x[2]*x[5]-0.9575*x[1]*x[2]*x[6]-0.6195*x[1]*x[2]*x[7]-0.3753*x[1]*x[2]*x[8]+0.6193*x[1]*x[2]*x[9]+0.1474*x[1]*x[2]*x[10]+0.6525*x[1]*x[3]*x[4]-0.4271*x[1]*x[3]*x[5]-0.679*x[1]*x[3]*x[6]-0.3382*x[1]*x[3]*x[7]-0.4683*x[1]*x[3]*x[8]+0.0896*x[1]*x[3]*x[9]+0.107*x[1]*x[3]*x[10]-0.9568*x[1]*x[4]*x[5]-0.7025*x[1]*x[4]*x[6]-0.7902*x[1]*x[4]*x[7]+0.2284*x[1]*x[4]*x[8]-0.1874*x[1]*x[4]*x[9]+0.8031*x[1]*x[4]*x[10]+0.8857*x[1]*x[5]*x[6]-0.6868*x[1]*x[5]*x[7]+0.8739*x[1]*x[5]*x[8]-0.7291*x[1]*x[5]*x[9]-0.2574*x[1]*x[5]*x[10]-0.357*x[1]*x[6]*x[7]+0.4299*x[1]*x[6]*x[8]+0.4594*x[1]*x[6]*x[9]-0.2428*x[1]*x[6]*x[10]+0.6579*x[1]*x[7]*x[8]+0.9073*x[1]*x[7]*x[9]-0.3832*x[1]*x[7]*x[10]+0.1595*x[1]*x[8]*x[9]-0.5331*x[1]*x[8]*x[10]+0.6888*x[1]*x[9]*x[10]-0.4837*x[2]*x[3]*x[4]+0.6795*x[2]*x[3]*x[5]+0.0753*x[2]*x[3]*x[6]+0.2431*x[2]*x[3]*x[7]-0.0184*x[2]*x[3]*x[8]-0.4303*x[2]*x[3]*x[9]-0.5289*x[2]*x[3]*x[10]+0.3028*x[2]*x[4]*x[5]+0.2143*x[2]*x[4]*x[6]-0.2037*x[2]*x[4]*x[7]+0.6976*x[2]*x[4]*x[8]+0.2752*x[2]*x[4]*x[9]-0.4824*x[2]*x[4]*x[10]-0.2823*x[2]*x[5]*x[6]+0.1237*x[2]*x[5]*x[7]-0.7571*x[2]*x[5]*x[8]+0.9569*x[2]*x[5]*x[9]-0.2336*x[2]*x[5]*x[10]+0.4414*x[2]*x[6]*x[7]-0.2835*x[2]*x[6]*x[8]+0.8198*x[2]*x[6]*x[9]+0.0874*x[2]*x[6]*x[10]+0.9194*x[2]*x[7]*x[8]+0.8589*x[2]*x[7]*x[9]+0.2666*x[2]*x[7]*x[10]-0.4088*x[2]*x[8]*x[9]-0.6505*x[2]*x[8]*x[10]+0.6852*x[2]*x[9]*x[10]+0.2372*x[3]*x[4]*x[5]+0.4118*x[3]*x[4]*x[6]-0.5151*x[3]*x[4]*x[7]+0.5959*x[3]*x[4]*x[8]-0.218*x[3]*x[4]*x[9]-0.7801*x[3]*x[4]*x[10]+0.5074*x[3]*x[5]*x[6]-0.9404*x[3]*x[5]*x[7]+0.4013*x[3]*x[5]*x[8]+0.0504*x[3]*x[5]*x[9]+0.5051*x[3]*x[5]*x[10]+0.2954*x[3]*x[6]*x[7]+0.7422*x[3]*x[6]*x[8]+0.6614*x[3]*x[6]*x[9]+0.9144*x[3]*x[6]*x[10]-0.5555*x[3]*x[7]*x[8]+0.159*x[3]*x[7]*x[9]+0.9815*x[3]*x[7]*x[10]+0.6799*x[3]*x[8]*x[9]-0.6504*x[3]*x[8]*x[10]+0.4191*x[3]*x[9]*x[10]-0.3969*x[4]*x[5]*x[6]-0.9499*x[4]*x[5]*x[7]+0.8335*x[4]*x[5]*x[8]+0.3776*x[4]*x[5]*x[9]+0.5135*x[4]*x[5]*x[10]+0.8655*x[4]*x[6]*x[7]-0.89*x[4]*x[6]*x[8]-0.0021*x[4]*x[6]*x[9]-0.881*x[4]*x[6]*x[10]-0.6563*x[4]*x[7]*x[8]+0.3767*x[4]*x[7]*x[9]-0.3868*x[4]*x[7]*x[10]+0.4704*x[4]*x[8]*x[9]+0.5043*x[4]*x[8]*x[10]-0.2086*x[4]*x[9]*x[10]-0.8244*x[5]*x[6]*x[7]-0.9021*x[5]*x[6]*x[8]+0.5587*x[5]*x[6]*x[9]+0.3616*x[5]*x[6]*x[10]-0.3769*x[5]*x[7]*x[8]+0.0455*x[5]*x[7]*x[9]+0.0116*x[5]*x[7]*x[10]-0.1229*x[5]*x[8]*x[9]+0.1753*x[5]*x[8]*x[10]-0.4053*x[5]*x[9]*x[10]-0.4102*x[6]*x[7]*x[8]-0.8524*x[6]*x[7]*x[9]+0.9499*x[6]*x[7]*x[10]+0.4563*x[6]*x[8]*x[9]+0.5162*x[6]*x[8]*x[10]-0.3816*x[6]*x[9]*x[10]-0.507*x[7]*x[8]*x[9]-0.4862*x[7]*x[8]*x[10]+0.2361*x[7]*x[9]*x[10]+0.8756*x[8]*x[9]*x[10] <= 45.614) - @NLconstraint(m, e3, 0.0242*x[1]*x[2]+0.5528*x[1]*x[3]-0.0143*x[1]*x[4]-0.5903*x[1]*x[5]-0.1097*x[1]*x[6]-0.1329*x[1]*x[7]-0.8906*x[1]*x[8]+0.401*x[1]*x[9]+0.8385*x[1]*x[10]-0.222*x[2]*x[3]-0.5022*x[2]*x[4]-0.2673*x[2]*x[5]+0.9973*x[2]*x[6]+0.3242*x[2]*x[7]-0.6405*x[2]*x[8]+0.7448*x[2]*x[9]-0.5121*x[2]*x[10]-0.7672*x[3]*x[4]+0.6364*x[3]*x[5]+0.0713*x[3]*x[6]+0.9761*x[3]*x[7]-0.1674*x[3]*x[8]+0.6164*x[3]*x[9]-0.5201*x[3]*x[10]+0.9405*x[4]*x[5]-0.2474*x[4]*x[6]+0.2668*x[4]*x[7]-0.7262*x[4]*x[8]+0.5369*x[4]*x[9]-0.7976*x[4]*x[10]+0.1039*x[5]*x[6]+0.6633*x[5]*x[7]-0.2455*x[5]*x[8]+0.7355*x[5]*x[9]+0.2493*x[5]*x[10]+0.1046*x[6]*x[7]-0.5768*x[6]*x[8]+0.6454*x[6]*x[9]-0.2728*x[6]*x[10]-0.539*x[7]*x[8]-0.3418*x[7]*x[9]+0.3602*x[7]*x[10]-0.1419*x[8]*x[9]-0.0954*x[8]*x[10]+0.8552*x[9]*x[10]-0.1075*x[1]+0.3345*x[2]+0.5617*x[3]+0.5817*x[4]-0.6045*x[5]-0.4872*x[6]+0.3536*x[7]+0.7971*x[8]-0.25*x[9]-0.9599*x[10]+0.2964*x[1]*x[2]*x[3]+0.3672*x[1]*x[2]*x[4]-0.6592*x[1]*x[2]*x[5]-0.4539*x[1]*x[2]*x[6]-0.1185*x[1]*x[2]*x[7]-0.0846*x[1]*x[2]*x[8]-0.2095*x[1]*x[2]*x[9]+0.3767*x[1]*x[2]*x[10]-0.4022*x[1]*x[3]*x[4]-0.5895*x[1]*x[3]*x[5]-0.6154*x[1]*x[3]*x[6]-0.162*x[1]*x[3]*x[7]+0.3813*x[1]*x[3]*x[8]-0.7189*x[1]*x[3]*x[9]-0.7125*x[1]*x[3]*x[10]+0.3249*x[1]*x[4]*x[5]+0.1514*x[1]*x[4]*x[6]+0.5499*x[1]*x[4]*x[7]+0.5506*x[1]*x[4]*x[8]+0.5307*x[1]*x[4]*x[9]+0.753*x[1]*x[4]*x[10]-0.8016*x[1]*x[5]*x[6]-0.331*x[1]*x[5]*x[7]+0.2902*x[1]*x[5]*x[8]-0.7368*x[1]*x[5]*x[9]+0.6151*x[1]*x[5]*x[10]+0.0837*x[1]*x[6]*x[7]-0.4685*x[1]*x[6]*x[8]-0.0823*x[1]*x[6]*x[9]+0.0219*x[1]*x[6]*x[10]+0.0097*x[1]*x[7]*x[8]+0.9235*x[1]*x[7]*x[9]+0.1005*x[1]*x[7]*x[10]-0.6207*x[1]*x[8]*x[9]-0.5978*x[1]*x[8]*x[10]-0.5025*x[1]*x[9]*x[10]+0.9402*x[2]*x[3]*x[4]+0.5528*x[2]*x[3]*x[5]-0.4546*x[2]*x[3]*x[6]-0.0061*x[2]*x[3]*x[7]-0.2025*x[2]*x[3]*x[8]+0.2266*x[2]*x[3]*x[9]-0.8295*x[2]*x[3]*x[10]+0.474*x[2]*x[4]*x[5]+0.7257*x[2]*x[4]*x[6]-0.3179*x[2]*x[4]*x[7]+0.3889*x[2]*x[4]*x[8]+0.2838*x[2]*x[4]*x[9]-0.829*x[2]*x[4]*x[10]+0.416*x[2]*x[5]*x[6]+0.1849*x[2]*x[5]*x[7]-0.5344*x[2]*x[5]*x[8]-0.8496*x[2]*x[5]*x[9]-0.3513*x[2]*x[5]*x[10]+0.8262*x[2]*x[6]*x[7]-0.5914*x[2]*x[6]*x[8]-0.0945*x[2]*x[6]*x[9]+0.4543*x[2]*x[6]*x[10]-0.9433*x[2]*x[7]*x[8]+0.0341*x[2]*x[7]*x[9]+0.5353*x[2]*x[7]*x[10]+0.7887*x[2]*x[8]*x[9]+0.889*x[2]*x[8]*x[10]-0.4204*x[2]*x[9]*x[10]+0.0629*x[3]*x[4]*x[5]-0.5343*x[3]*x[4]*x[6]-0.3744*x[3]*x[4]*x[7]-0.717*x[3]*x[4]*x[8]-0.3148*x[3]*x[4]*x[9]-0.6929*x[3]*x[4]*x[10]+0.6984*x[3]*x[5]*x[6]+0.9441*x[3]*x[5]*x[7]-0.1182*x[3]*x[5]*x[8]+0.5489*x[3]*x[5]*x[9]-0.0876*x[3]*x[5]*x[10]+0.729*x[3]*x[6]*x[7]+0.456*x[3]*x[6]*x[8]+0.2747*x[3]*x[6]*x[9]+0.4481*x[3]*x[6]*x[10]+0.2084*x[3]*x[7]*x[8]-0.9474*x[3]*x[7]*x[9]-0.4145*x[3]*x[7]*x[10]-0.6056*x[3]*x[8]*x[9]+0.8973*x[3]*x[8]*x[10]+0.0637*x[3]*x[9]*x[10]-0.9793*x[4]*x[5]*x[6]-0.0957*x[4]*x[5]*x[7]+0.9272*x[4]*x[5]*x[8]+0.9722*x[4]*x[5]*x[9]-0.3182*x[4]*x[5]*x[10]+0.9186*x[4]*x[6]*x[7]-0.3466*x[4]*x[6]*x[8]+0.4085*x[4]*x[6]*x[9]+0.5809*x[4]*x[6]*x[10]+0.4471*x[4]*x[7]*x[8]+0.4579*x[4]*x[7]*x[9]-0.1092*x[4]*x[7]*x[10]-0.2364*x[4]*x[8]*x[9]+0.8444*x[4]*x[8]*x[10]+0.4968*x[4]*x[9]*x[10]-0.1465*x[5]*x[6]*x[7]-0.5651*x[5]*x[6]*x[8]+0.4588*x[5]*x[6]*x[9]+0.5938*x[5]*x[6]*x[10]+0.1168*x[5]*x[7]*x[8]+0.7708*x[5]*x[7]*x[9]-0.2337*x[5]*x[7]*x[10]-0.5184*x[5]*x[8]*x[9]-0.3698*x[5]*x[8]*x[10]-0.1342*x[5]*x[9]*x[10]-0.904*x[6]*x[7]*x[8]-0.1518*x[6]*x[7]*x[9]+0.4747*x[6]*x[7]*x[10]+0.7456*x[6]*x[8]*x[9]-0.384*x[6]*x[8]*x[10]+0.6866*x[6]*x[9]*x[10]+0.6322*x[7]*x[8]*x[9]-0.1864*x[7]*x[8]*x[10]+0.73*x[7]*x[9]*x[10]+0.7045*x[8]*x[9]*x[10] <= 40.2) - @NLconstraint(m, e4, (-0.2692*x[1]*x[2])-0.5992*x[1]*x[3]-0.1808*x[1]*x[4]-0.5216*x[1]*x[5]+0.41*x[1]*x[6]-0.8418*x[1]*x[7]-0.5924*x[1]*x[8]-0.9653*x[1]*x[9]-0.3314*x[1]*x[10]-0.4303*x[2]*x[3]+0.6908*x[2]*x[4]-0.0111*x[2]*x[5]+0.4202*x[2]*x[6]-0.4907*x[2]*x[7]+0.6454*x[2]*x[8]-0.4368*x[2]*x[9]+0.2496*x[2]*x[10]+0.4916*x[3]*x[4]+0.7479*x[3]*x[5]-0.7442*x[3]*x[6]-0.4416*x[3]*x[7]+0.847*x[3]*x[8]+0.9726*x[3]*x[9]+0.5786*x[3]*x[10]-0.3041*x[4]*x[5]+0.5286*x[4]*x[6]-0.6138*x[4]*x[7]-0.8712*x[4]*x[8]-0.9096*x[4]*x[9]-0.707*x[4]*x[10]+0.6138*x[5]*x[6]+0.312*x[5]*x[7]-0.5107*x[5]*x[8]-0.3513*x[5]*x[9]+0.9673*x[5]*x[10]+0.2275*x[6]*x[7]-0.415*x[6]*x[8]-0.0089*x[6]*x[9]+0.4723*x[6]*x[10]-0.9209*x[7]*x[8]-0.9687*x[7]*x[9]-0.043*x[7]*x[10]+0.5532*x[8]*x[9]+0.8139*x[8]*x[10]+0.8304*x[9]*x[10]-0.3323*x[1]-0.4014*x[2]+0.6574*x[3]-0.0813*x[4]-0.9703*x[5]-0.3218*x[6]-0.8836*x[7]-0.8145*x[8]+0.3035*x[9]-0.2096*x[10]+0.9819*x[1]*x[2]*x[3]+0.9495*x[1]*x[2]*x[4]+0.9406*x[1]*x[2]*x[5]+0.9377*x[1]*x[2]*x[6]-0.2505*x[1]*x[2]*x[7]-0.8054*x[1]*x[2]*x[8]+0.5014*x[1]*x[2]*x[9]+0.649*x[1]*x[2]*x[10]+0.4489*x[1]*x[3]*x[4]-0.2659*x[1]*x[3]*x[5]+0.2441*x[1]*x[3]*x[6]-0.3874*x[1]*x[3]*x[7]-0.3974*x[1]*x[3]*x[8]+0.3528*x[1]*x[3]*x[9]+0.6601*x[1]*x[3]*x[10]+0.1126*x[1]*x[4]*x[5]+0.1189*x[1]*x[4]*x[6]-0.3444*x[1]*x[4]*x[7]+0.4614*x[1]*x[4]*x[8]-0.6835*x[1]*x[4]*x[9]+0.0658*x[1]*x[4]*x[10]+0.5684*x[1]*x[5]*x[6]-0.5684*x[1]*x[5]*x[7]-0.3494*x[1]*x[5]*x[8]+0.0029*x[1]*x[5]*x[9]-0.5542*x[1]*x[5]*x[10]-0.067*x[1]*x[6]*x[7]-0.6264*x[1]*x[6]*x[8]-0.6098*x[1]*x[6]*x[9]-0.5862*x[1]*x[6]*x[10]+0.8116*x[1]*x[7]*x[8]+0.5998*x[1]*x[7]*x[9]+0.4699*x[1]*x[7]*x[10]-0.1693*x[1]*x[8]*x[9]+0.622*x[1]*x[8]*x[10]+0.9767*x[1]*x[9]*x[10]-0.0178*x[2]*x[3]*x[4]-0.5614*x[2]*x[3]*x[5]+0.5238*x[2]*x[3]*x[6]+0.8146*x[2]*x[3]*x[7]+0.1793*x[2]*x[3]*x[8]+0.7412*x[2]*x[3]*x[9]-0.9228*x[2]*x[3]*x[10]+0.8761*x[2]*x[4]*x[5]-0.9062*x[2]*x[4]*x[6]+0.7942*x[2]*x[4]*x[7]-0.9605*x[2]*x[4]*x[8]+0.9985*x[2]*x[4]*x[9]+0.9604*x[2]*x[4]*x[10]+0.2233*x[2]*x[5]*x[6]+0.1751*x[2]*x[5]*x[7]+0.9245*x[2]*x[5]*x[8]+0.7868*x[2]*x[5]*x[9]-0.5956*x[2]*x[5]*x[10]-0.9745*x[2]*x[6]*x[7]-0.49*x[2]*x[6]*x[8]+0.7809*x[2]*x[6]*x[9]-0.4609*x[2]*x[6]*x[10]+0.778*x[2]*x[7]*x[8]+0.0383*x[2]*x[7]*x[9]-0.2656*x[2]*x[7]*x[10]+0.9676*x[2]*x[8]*x[9]+0.7539*x[2]*x[8]*x[10]+0.3629*x[2]*x[9]*x[10]-0.2751*x[3]*x[4]*x[5]-0.6036*x[3]*x[4]*x[6]-0.6255*x[3]*x[4]*x[7]+0.9753*x[3]*x[4]*x[8]-0.6347*x[3]*x[4]*x[9]-0.9763*x[3]*x[4]*x[10]+0.8874*x[3]*x[5]*x[6]-0.0161*x[3]*x[5]*x[7]+0.9611*x[3]*x[5]*x[8]+0.2266*x[3]*x[5]*x[9]-0.2746*x[3]*x[5]*x[10]+0.0648*x[3]*x[6]*x[7]-0.7084*x[3]*x[6]*x[8]-0.7343*x[3]*x[6]*x[9]-0.2376*x[3]*x[6]*x[10]+0.4007*x[3]*x[7]*x[8]+0.0995*x[3]*x[7]*x[9]+0.6511*x[3]*x[7]*x[10]+0.0747*x[3]*x[8]*x[9]+0.3247*x[3]*x[8]*x[10]-0.8937*x[3]*x[9]*x[10]-0.6571*x[4]*x[5]*x[6]+0.2373*x[4]*x[5]*x[7]+0.5175*x[4]*x[5]*x[8]+0.8201*x[4]*x[5]*x[9]+0.428*x[4]*x[5]*x[10]+0.48*x[4]*x[6]*x[7]-0.2866*x[4]*x[6]*x[8]+0.6437*x[4]*x[6]*x[9]+0.1041*x[4]*x[6]*x[10]+0.3016*x[4]*x[7]*x[8]-0.6249*x[4]*x[7]*x[9]+0.6366*x[4]*x[7]*x[10]-0.9552*x[4]*x[8]*x[9]+0.3144*x[4]*x[8]*x[10]-0.7607*x[4]*x[9]*x[10]-0.2293*x[5]*x[6]*x[7]-0.5147*x[5]*x[6]*x[8]+0.9307*x[5]*x[6]*x[9]-0.0294*x[5]*x[6]*x[10]+0.9847*x[5]*x[7]*x[8]-0.4374*x[5]*x[7]*x[9]+0.9569*x[5]*x[7]*x[10]+0.9057*x[5]*x[8]*x[9]-0.5138*x[5]*x[8]*x[10]-0.1668*x[5]*x[9]*x[10]+0.4716*x[6]*x[7]*x[8]-0.6094*x[6]*x[7]*x[9]+0.2787*x[6]*x[7]*x[10]+0.2594*x[6]*x[8]*x[9]-0.7943*x[6]*x[8]*x[10]-0.7225*x[6]*x[9]*x[10]-0.0902*x[7]*x[8]*x[9]+0.9687*x[7]*x[8]*x[10]-0.1502*x[7]*x[9]*x[10]+0.4096*x[8]*x[9]*x[10] <= 61.993) - @NLconstraint(m, e5, 0.269*x[1]*x[3]-0.0967*x[1]*x[2]-0.5516*x[1]*x[4]-0.2037*x[1]*x[5]+0.6602*x[1]*x[6]-0.722*x[1]*x[7]+0.5119*x[1]*x[8]+0.586*x[1]*x[9]-0.5442*x[1]*x[10]+0.0562*x[2]*x[3]-0.7251*x[2]*x[4]-0.6521*x[2]*x[5]-0.7049*x[2]*x[6]+0.62*x[2]*x[7]-0.497*x[2]*x[8]-0.1799*x[2]*x[9]+0.9132*x[2]*x[10]+0.4395*x[3]*x[4]+0.6708*x[3]*x[5]+0.5537*x[3]*x[6]+0.0758*x[3]*x[7]+0.2226*x[3]*x[8]+0.3882*x[3]*x[9]+0.2014*x[3]*x[10]-0.8073*x[4]*x[5]+0.0984*x[4]*x[6]-0.4142*x[4]*x[7]-0.5883*x[4]*x[8]+0.6861*x[4]*x[9]+0.303*x[4]*x[10]+0.9262*x[5]*x[6]+0.2199*x[5]*x[7]-0.1922*x[5]*x[8]-0.7428*x[5]*x[9]-0.7244*x[5]*x[10]-0.5698*x[6]*x[7]+0.046*x[6]*x[8]+0.4195*x[6]*x[9]+0.0448*x[6]*x[10]-0.6311*x[7]*x[8]+0.7262*x[7]*x[9]-0.3714*x[7]*x[10]-0.9939*x[8]*x[9]+0.9992*x[8]*x[10]+0.7608*x[9]*x[10]-0.5125*x[1]+0.0878*x[2]+0.522*x[3]+0.3632*x[4]-0.1574*x[5]+0.1895*x[6]-0.1071*x[7]+0.889*x[8]-0.6673*x[9]+0.9491*x[10]+0.6504*x[1]*x[2]*x[3]-0.3218*x[1]*x[2]*x[4]-0.3831*x[1]*x[2]*x[5]-0.2782*x[1]*x[2]*x[6]-0.1766*x[1]*x[2]*x[7]-0.0781*x[1]*x[2]*x[8]-0.2352*x[1]*x[2]*x[9]+0.2862*x[1]*x[2]*x[10]-0.5167*x[1]*x[3]*x[4]+0.4314*x[1]*x[3]*x[5]+0.7136*x[1]*x[3]*x[6]-0.6721*x[1]*x[3]*x[7]+0.4626*x[1]*x[3]*x[8]+0.0198*x[1]*x[3]*x[9]-0.4397*x[1]*x[3]*x[10]+0.9861*x[1]*x[4]*x[5]+0.5225*x[1]*x[4]*x[6]-0.9346*x[1]*x[4]*x[7]+0.4133*x[1]*x[4]*x[8]+0.3442*x[1]*x[4]*x[9]-0.8199*x[1]*x[4]*x[10]-0.0776*x[1]*x[5]*x[6]-0.4723*x[1]*x[5]*x[7]-0.289*x[1]*x[5]*x[8]+0.4463*x[1]*x[5]*x[9]-0.9454*x[1]*x[5]*x[10]+0.1697*x[1]*x[6]*x[7]+0.3885*x[1]*x[6]*x[8]-0.7786*x[1]*x[6]*x[9]+0.0525*x[1]*x[6]*x[10]+0.9874*x[1]*x[7]*x[8]+0.4525*x[1]*x[7]*x[9]+0.521*x[1]*x[7]*x[10]-0.5928*x[1]*x[8]*x[9]+0.7265*x[1]*x[8]*x[10]-0.615*x[1]*x[9]*x[10]-0.8237*x[2]*x[3]*x[4]-0.5174*x[2]*x[3]*x[5]+0.821*x[2]*x[3]*x[6]+0.6597*x[2]*x[3]*x[7]-0.8449*x[2]*x[3]*x[8]+0.743*x[2]*x[3]*x[9]+0.1144*x[2]*x[3]*x[10]-0.2056*x[2]*x[4]*x[5]+0.9986*x[2]*x[4]*x[6]+0.54*x[2]*x[4]*x[7]+0.5713*x[2]*x[4]*x[8]+0.5068*x[2]*x[4]*x[9]+0.1204*x[2]*x[4]*x[10]+0.3888*x[2]*x[5]*x[6]+0.7512*x[2]*x[5]*x[7]-0.9713*x[2]*x[5]*x[8]-0.4285*x[2]*x[5]*x[9]-0.6373*x[2]*x[5]*x[10]+0.6154*x[2]*x[6]*x[7]+0.1051*x[2]*x[6]*x[8]-0.0283*x[2]*x[6]*x[9]+0.0735*x[2]*x[6]*x[10]-0.9093*x[2]*x[7]*x[8]-0.7123*x[2]*x[7]*x[9]+0.5603*x[2]*x[7]*x[10]+0.5412*x[2]*x[8]*x[9]-0.6809*x[2]*x[8]*x[10]-0.0621*x[2]*x[9]*x[10]-0.674*x[3]*x[4]*x[5]+0.0977*x[3]*x[4]*x[6]-0.3899*x[3]*x[4]*x[7]-0.6912*x[3]*x[4]*x[8]+0.15*x[3]*x[4]*x[9]-0.7118*x[3]*x[4]*x[10]-0.6134*x[3]*x[5]*x[6]+0.3822*x[3]*x[5]*x[7]+0.9004*x[3]*x[5]*x[8]-0.7372*x[3]*x[5]*x[9]+0.42*x[3]*x[5]*x[10]-0.2405*x[3]*x[6]*x[7]-0.204*x[3]*x[6]*x[8]-0.998*x[3]*x[6]*x[9]-0.1736*x[3]*x[6]*x[10]+0.6076*x[3]*x[7]*x[8]+0.7557*x[3]*x[7]*x[9]-0.7184*x[3]*x[7]*x[10]-0.9139*x[3]*x[8]*x[9]+0.1313*x[3]*x[8]*x[10]-0.8836*x[3]*x[9]*x[10]+0.7427*x[4]*x[5]*x[6]-0.3114*x[4]*x[5]*x[7]-0.0203*x[4]*x[5]*x[8]-0.4356*x[4]*x[5]*x[9]-0.5229*x[4]*x[5]*x[10]+0.0993*x[4]*x[6]*x[7]+0.4277*x[4]*x[6]*x[8]+0.8057*x[4]*x[6]*x[9]+0.5147*x[4]*x[6]*x[10]+0.0785*x[4]*x[7]*x[8]+0.2918*x[4]*x[7]*x[9]+0.5539*x[4]*x[7]*x[10]+0.758*x[4]*x[8]*x[9]+0.2055*x[4]*x[8]*x[10]-0.877*x[4]*x[9]*x[10]-0.1218*x[5]*x[6]*x[7]-0.9826*x[5]*x[6]*x[8]-0.4008*x[5]*x[6]*x[9]+0.947*x[5]*x[6]*x[10]+0.9103*x[5]*x[7]*x[8]-0.5734*x[5]*x[7]*x[9]+0.3479*x[5]*x[7]*x[10]+0.0723*x[5]*x[8]*x[9]-0.2806*x[5]*x[8]*x[10]-0.9973*x[5]*x[9]*x[10]+0.6989*x[6]*x[7]*x[8]-0.1571*x[6]*x[7]*x[9]+0.4957*x[6]*x[7]*x[10]-0.9767*x[6]*x[8]*x[9]+0.2287*x[6]*x[8]*x[10]-0.1111*x[6]*x[9]*x[10]+0.3253*x[7]*x[8]*x[9]+0.3775*x[7]*x[8]*x[10]+0.8783*x[7]*x[9]*x[10]+0.4335*x[8]*x[9]*x[10] <= 8.691) - @NLconstraint(m, e6, (-0.21*x[1]*x[2])-0.5062*x[1]*x[3]-0.8757*x[1]*x[4]+0.8153*x[1]*x[5]+0.0395*x[1]*x[6]-0.8308*x[1]*x[7]-0.2081*x[1]*x[8]-0.797*x[1]*x[9]-0.9042*x[1]*x[10]-0.5208*x[2]*x[3]+0.2869*x[2]*x[4]+0.0977*x[2]*x[5]-0.6313*x[2]*x[6]-0.1462*x[2]*x[7]+0.2552*x[2]*x[8]-0.8255*x[2]*x[9]+0.0742*x[2]*x[10]+0.6895*x[3]*x[4]-0.181*x[3]*x[5]-0.5937*x[3]*x[6]+0.6543*x[3]*x[7]+0.9317*x[3]*x[8]-0.2445*x[3]*x[9]+0.2943*x[3]*x[10]+0.3555*x[4]*x[5]-0.1086*x[4]*x[6]-0.6558*x[4]*x[7]-0.296*x[4]*x[8]-0.3417*x[4]*x[9]+0.4937*x[4]*x[10]-0.457*x[5]*x[6]+0.1226*x[5]*x[7]-0.7351*x[5]*x[8]+0.5968*x[5]*x[9]-0.5881*x[5]*x[10]-0.9469*x[6]*x[7]-0.6075*x[6]*x[8]-0.9843*x[6]*x[9]+0.6435*x[6]*x[10]+0.8889*x[7]*x[8]-0.064*x[7]*x[9]-0.7728*x[7]*x[10]-0.679*x[8]*x[9]+0.6905*x[8]*x[10]+0.7074*x[9]*x[10]-0.3972*x[1]-0.4977*x[2]-0.5983*x[3]-0.4784*x[4]-0.4858*x[5]+0.2572*x[6]-0.0521*x[7]+0.7398*x[8]+0.2972*x[9]+0.7789*x[10]+0.8198*x[1]*x[2]*x[4]-0.6978*x[1]*x[2]*x[3]-0.5889*x[1]*x[2]*x[5]-0.5569*x[1]*x[2]*x[6]-0.7317*x[1]*x[2]*x[7]+0.3949*x[1]*x[2]*x[8]+0.9541*x[1]*x[2]*x[9]-0.9943*x[1]*x[2]*x[10]-0.0116*x[1]*x[3]*x[4]-0.5047*x[1]*x[3]*x[5]+0.8051*x[1]*x[3]*x[6]-0.7914*x[1]*x[3]*x[7]+0.5505*x[1]*x[3]*x[8]-0.7908*x[1]*x[3]*x[9]+0.2414*x[1]*x[3]*x[10]-0.3313*x[1]*x[4]*x[5]+0.9555*x[1]*x[4]*x[6]+0.3839*x[1]*x[4]*x[7]+0.6554*x[1]*x[4]*x[8]+0.9363*x[1]*x[4]*x[9]-0.4451*x[1]*x[4]*x[10]-0.2679*x[1]*x[5]*x[6]-0.6916*x[1]*x[5]*x[7]+0.9618*x[1]*x[5]*x[8]+0.8635*x[1]*x[5]*x[9]-0.5314*x[1]*x[5]*x[10]-0.7532*x[1]*x[6]*x[7]-0.2676*x[1]*x[6]*x[8]+0.6789*x[1]*x[6]*x[9]-0.7484*x[1]*x[6]*x[10]+0.9799*x[1]*x[7]*x[8]-0.04*x[1]*x[7]*x[9]+0.9229*x[1]*x[7]*x[10]+0.9211*x[1]*x[8]*x[9]+0.5065*x[1]*x[8]*x[10]+0.2912*x[1]*x[9]*x[10]+0.3298*x[2]*x[3]*x[4]+0.7586*x[2]*x[3]*x[5]+0.4593*x[2]*x[3]*x[6]+0.3926*x[2]*x[3]*x[7]+0.0687*x[2]*x[3]*x[8]+0.4976*x[2]*x[3]*x[9]+0.6535*x[2]*x[3]*x[10]-0.9917*x[2]*x[4]*x[5]-0.5502*x[2]*x[4]*x[6]-0.1718*x[2]*x[4]*x[7]+0.2573*x[2]*x[4]*x[8]-0.9025*x[2]*x[4]*x[9]+0.3264*x[2]*x[4]*x[10]-0.6443*x[2]*x[5]*x[6]+0.1642*x[2]*x[5]*x[7]+0.9221*x[2]*x[5]*x[8]-0.428*x[2]*x[5]*x[9]-0.4399*x[2]*x[5]*x[10]+0.7566*x[2]*x[6]*x[7]+0.354*x[2]*x[6]*x[8]-0.5276*x[2]*x[6]*x[9]-0.6272*x[2]*x[6]*x[10]-0.8758*x[2]*x[7]*x[8]-0.6662*x[2]*x[7]*x[9]-0.5727*x[2]*x[7]*x[10]-0.1467*x[2]*x[8]*x[9]-0.8066*x[2]*x[8]*x[10]-0.53*x[2]*x[9]*x[10]-0.7406*x[3]*x[4]*x[5]+0.8858*x[3]*x[4]*x[6]-0.3289*x[3]*x[4]*x[7]-0.8604*x[3]*x[4]*x[8]-0.0148*x[3]*x[4]*x[9]+0.3933*x[3]*x[4]*x[10]+0.4846*x[3]*x[5]*x[6]-0.7567*x[3]*x[5]*x[7]+0.083*x[3]*x[5]*x[8]-0.0985*x[3]*x[5]*x[9]+0.3703*x[3]*x[5]*x[10]+0.6679*x[3]*x[6]*x[7]+0.8643*x[3]*x[6]*x[8]+0.533*x[3]*x[6]*x[9]+0.1871*x[3]*x[6]*x[10]-0.1905*x[3]*x[7]*x[8]+0.9994*x[3]*x[7]*x[9]-0.7306*x[3]*x[7]*x[10]-0.2797*x[3]*x[8]*x[9]-0.7742*x[3]*x[8]*x[10]+0.2634*x[3]*x[9]*x[10]-0.6882*x[4]*x[5]*x[6]-0.1916*x[4]*x[5]*x[7]-0.6292*x[4]*x[5]*x[8]+0.3706*x[4]*x[5]*x[9]+0.2252*x[4]*x[5]*x[10]-0.5111*x[4]*x[6]*x[7]-0.7106*x[4]*x[6]*x[8]+0.436*x[4]*x[6]*x[9]+0.6397*x[4]*x[6]*x[10]-0.7626*x[4]*x[7]*x[8]-0.7465*x[4]*x[7]*x[9]-0.4273*x[4]*x[7]*x[10]+0.9735*x[4]*x[8]*x[9]-0.5091*x[4]*x[8]*x[10]-0.0217*x[4]*x[9]*x[10]-0.9406*x[5]*x[6]*x[7]-0.5301*x[5]*x[6]*x[8]-0.0925*x[5]*x[6]*x[9]-0.4232*x[5]*x[6]*x[10]+0.4301*x[5]*x[7]*x[8]-0.1282*x[5]*x[7]*x[9]+0.2232*x[5]*x[7]*x[10]+0.124*x[5]*x[8]*x[9]-0.3137*x[5]*x[8]*x[10]+0.5432*x[5]*x[9]*x[10]-0.0037*x[6]*x[7]*x[8]-0.0924*x[6]*x[7]*x[9]+0.3913*x[6]*x[7]*x[10]-0.6371*x[6]*x[8]*x[9]-0.1172*x[6]*x[8]*x[10]-0.1265*x[6]*x[9]*x[10]-0.8825*x[7]*x[8]*x[9]-0.2623*x[7]*x[8]*x[10]-0.1383*x[7]*x[9]*x[10]-0.6027*x[8]*x[9]*x[10] <= 79.525) - @NLconstraint(m, e7, 0.9658*x[1]*x[2]-0.8057*x[1]*x[3]+0.2716*x[1]*x[4]-0.8667*x[1]*x[5]-0.6541*x[1]*x[6]-0.0723*x[1]*x[7]-0.1218*x[1]*x[8]+0.6082*x[1]*x[9]-0.1423*x[1]*x[10]+0.5249*x[2]*x[3]+0.4167*x[2]*x[4]-0.507*x[2]*x[5]+0.8024*x[2]*x[6]-0.8732*x[2]*x[7]-0.9641*x[2]*x[8]+0.8948*x[2]*x[9]-0.0228*x[2]*x[10]-0.2308*x[3]*x[4]-0.8365*x[3]*x[5]-0.0407*x[3]*x[6]-0.6009*x[3]*x[7]-0.2916*x[3]*x[8]-0.1374*x[3]*x[9]+0.8125*x[3]*x[10]+0.8725*x[4]*x[5]+0.4909*x[4]*x[6]+0.9356*x[4]*x[7]+0.7571*x[4]*x[8]-0.4834*x[4]*x[9]+0.5875*x[4]*x[10]-0.8418*x[5]*x[6]-0.9637*x[5]*x[7]-0.3318*x[5]*x[8]-0.3304*x[5]*x[9]+0.0086*x[5]*x[10]-0.2382*x[6]*x[7]+0.7865*x[6]*x[8]-0.4775*x[6]*x[9]-0.0112*x[6]*x[10]+0.4793*x[7]*x[8]+0.2361*x[7]*x[9]+0.3537*x[7]*x[10]+0.4693*x[8]*x[9]+0.7316*x[8]*x[10]+0.3182*x[9]*x[10]+0.8041*x[1]-0.4561*x[2]+0.8676*x[3]-0.7196*x[4]-0.3273*x[5]-0.0517*x[6]-0.9975*x[7]-0.5365*x[8]+0.9168*x[9]+0.7715*x[10]+0.7603*x[1]*x[2]*x[3]-0.5705*x[1]*x[2]*x[4]+0.9037*x[1]*x[2]*x[5]+0.4382*x[1]*x[2]*x[6]-0.7787*x[1]*x[2]*x[7]+0.9149*x[1]*x[2]*x[8]+0.2939*x[1]*x[2]*x[9]+0.1637*x[1]*x[2]*x[10]-0.9742*x[1]*x[3]*x[4]-0.4477*x[1]*x[3]*x[5]+0.6009*x[1]*x[3]*x[6]-0.3442*x[1]*x[3]*x[7]+0.1588*x[1]*x[3]*x[8]-0.9521*x[1]*x[3]*x[9]+0.3398*x[1]*x[3]*x[10]-0.6371*x[1]*x[4]*x[5]-0.4268*x[1]*x[4]*x[6]+0.3169*x[1]*x[4]*x[7]+0.1779*x[1]*x[4]*x[8]-0.8726*x[1]*x[4]*x[9]-0.7344*x[1]*x[4]*x[10]+0.4833*x[1]*x[5]*x[6]+0.0007*x[1]*x[5]*x[7]-0.9371*x[1]*x[5]*x[8]+0.9815*x[1]*x[5]*x[9]-0.9932*x[1]*x[5]*x[10]+0.3986*x[1]*x[6]*x[7]+0.5181*x[1]*x[6]*x[8]-0.4916*x[1]*x[6]*x[9]-0.3371*x[1]*x[6]*x[10]+0.1457*x[1]*x[7]*x[8]+0.9832*x[1]*x[7]*x[9]-0.0207*x[1]*x[7]*x[10]+0.1223*x[1]*x[8]*x[9]+0.2128*x[1]*x[8]*x[10]-0.8286*x[1]*x[9]*x[10]-0.4837*x[2]*x[3]*x[4]-0.0592*x[2]*x[3]*x[5]+0.6266*x[2]*x[3]*x[6]+0.4492*x[2]*x[3]*x[7]+0.9861*x[2]*x[3]*x[8]-0.8687*x[2]*x[3]*x[9]-0.8504*x[2]*x[3]*x[10]+0.6624*x[2]*x[4]*x[5]-0.1745*x[2]*x[4]*x[6]+0.3241*x[2]*x[4]*x[7]-0.4919*x[2]*x[4]*x[8]-0.0339*x[2]*x[4]*x[9]+0.2248*x[2]*x[4]*x[10]+0.366*x[2]*x[5]*x[6]-0.1987*x[2]*x[5]*x[7]-0.5784*x[2]*x[5]*x[8]+0.8198*x[2]*x[5]*x[9]-0.0486*x[2]*x[5]*x[10]+0.7126*x[2]*x[6]*x[7]+0.8337*x[2]*x[6]*x[8]+0.0308*x[2]*x[6]*x[9]+0.4378*x[2]*x[6]*x[10]-0.4249*x[2]*x[7]*x[8]-0.876*x[2]*x[7]*x[9]-0.247*x[2]*x[7]*x[10]-0.482*x[2]*x[8]*x[9]+0.0808*x[2]*x[8]*x[10]+0.0687*x[2]*x[9]*x[10]-0.9379*x[3]*x[4]*x[5]-0.1556*x[3]*x[4]*x[6]-0.1534*x[3]*x[4]*x[7]+0.2972*x[3]*x[4]*x[8]-0.682*x[3]*x[4]*x[9]-0.2246*x[3]*x[4]*x[10]+0.2078*x[3]*x[5]*x[6]+0.0801*x[3]*x[5]*x[7]+0.412*x[3]*x[5]*x[8]-0.7653*x[3]*x[5]*x[9]+0.7097*x[3]*x[5]*x[10]+0.1609*x[3]*x[6]*x[7]+0.0463*x[3]*x[6]*x[8]-0.049*x[3]*x[6]*x[9]-0.9321*x[3]*x[6]*x[10]+0.5337*x[3]*x[7]*x[8]+0.6369*x[3]*x[7]*x[9]-0.8873*x[3]*x[7]*x[10]-0.5746*x[3]*x[8]*x[9]+0.4865*x[3]*x[8]*x[10]-0.3803*x[3]*x[9]*x[10]-0.7699*x[4]*x[5]*x[6]+0.7363*x[4]*x[5]*x[7]-0.2812*x[4]*x[5]*x[8]+0.8172*x[4]*x[5]*x[9]-0.5754*x[4]*x[5]*x[10]-0.2821*x[4]*x[6]*x[7]-0.8113*x[4]*x[6]*x[8]+0.3038*x[4]*x[6]*x[9]+0.8093*x[4]*x[6]*x[10]+0.5277*x[4]*x[7]*x[8]+0.7849*x[4]*x[7]*x[9]+0.6706*x[4]*x[7]*x[10]+0.0152*x[4]*x[8]*x[9]-0.009*x[4]*x[8]*x[10]+0.0082*x[4]*x[9]*x[10]+0.5372*x[5]*x[6]*x[7]-0.2333*x[5]*x[6]*x[8]-0.8164*x[5]*x[6]*x[9]+0.8521*x[5]*x[6]*x[10]+0.4163*x[5]*x[7]*x[8]+0.6625*x[5]*x[7]*x[9]+0.6022*x[5]*x[7]*x[10]+0.1782*x[5]*x[8]*x[9]+0.63*x[5]*x[8]*x[10]+0.4385*x[5]*x[9]*x[10]+0.9963*x[6]*x[7]*x[8]+0.8737*x[6]*x[7]*x[9]+0.382*x[6]*x[7]*x[10]+0.4417*x[6]*x[8]*x[9]+0.2669*x[6]*x[8]*x[10]+0.7712*x[6]*x[9]*x[10]+0.5226*x[7]*x[8]*x[9]+0.3681*x[7]*x[8]*x[10]+0.7255*x[7]*x[9]*x[10]-0.4059*x[8]*x[9]*x[10] <= 55.647) - @NLconstraint(m, e8, 0.5619*x[1]*x[2]+0.6594*x[1]*x[3]-0.6765*x[1]*x[4]+0.8412*x[1]*x[5]-0.6171*x[1]*x[6]+0.5953*x[1]*x[7]+0.9679*x[1]*x[8]+0.7684*x[1]*x[9]+0.3959*x[1]*x[10]+0.61*x[2]*x[3]+0.6235*x[2]*x[4]-0.2316*x[2]*x[5]+0.2738*x[2]*x[6]-0.5261*x[2]*x[7]+0.6011*x[2]*x[8]+0.421*x[2]*x[9]-0.9893*x[2]*x[10]-0.5615*x[3]*x[4]+0.7985*x[3]*x[5]+0.1976*x[3]*x[6]-0.1837*x[3]*x[7]-0.7994*x[3]*x[8]-0.7895*x[3]*x[9]+0.146*x[3]*x[10]-0.5227*x[4]*x[5]+0.3006*x[4]*x[6]+0.8038*x[4]*x[7]-0.0596*x[4]*x[8]+0.152*x[4]*x[9]+0.5178*x[4]*x[10]-0.1747*x[5]*x[6]+0.9976*x[5]*x[7]+0.1196*x[5]*x[8]-0.5697*x[5]*x[9]-0.8498*x[5]*x[10]-0.6921*x[6]*x[7]-0.0832*x[6]*x[8]+0.7875*x[6]*x[9]+0.2374*x[6]*x[10]+0.2773*x[7]*x[8]+0.8304*x[7]*x[9]-0.2771*x[7]*x[10]+0.8288*x[8]*x[9]-0.6953*x[8]*x[10]+0.9491*x[9]*x[10]-0.1701*x[1]+0.4837*x[2]-0.9392*x[3]-0.0295*x[4]+0.8232*x[5]+0.8049*x[6]+0.8403*x[7]+0.0402*x[8]+0.4708*x[9]+0.653*x[10]+(-0.3254*x[1]*x[2]*x[3])-0.6267*x[1]*x[2]*x[4]-0.2341*x[1]*x[2]*x[5]+0.332*x[1]*x[2]*x[6]+0.8281*x[1]*x[2]*x[7]-0.1747*x[1]*x[2]*x[8]+0.9767*x[1]*x[2]*x[9]-0.6643*x[1]*x[2]*x[10]-0.7506*x[1]*x[3]*x[4]+0.0168*x[1]*x[3]*x[5]-0.0513*x[1]*x[3]*x[6]-0.6878*x[1]*x[3]*x[7]-0.0265*x[1]*x[3]*x[8]+0.6138*x[1]*x[3]*x[9]+0.9757*x[1]*x[3]*x[10]-0.8293*x[1]*x[4]*x[5]+0.9219*x[1]*x[4]*x[6]+0.403*x[1]*x[4]*x[7]-0.0383*x[1]*x[4]*x[8]-0.1156*x[1]*x[4]*x[9]-0.9505*x[1]*x[4]*x[10]-0.5166*x[1]*x[5]*x[6]-0.7652*x[1]*x[5]*x[7]-0.9915*x[1]*x[5]*x[8]-0.477*x[1]*x[5]*x[9]+0.1948*x[1]*x[5]*x[10]-0.9361*x[1]*x[6]*x[7]-0.0442*x[1]*x[6]*x[8]-0.4517*x[1]*x[6]*x[9]-0.8448*x[1]*x[6]*x[10]-0.8462*x[1]*x[7]*x[8]+0.7179*x[1]*x[7]*x[9]+0.1438*x[1]*x[7]*x[10]-0.831*x[1]*x[8]*x[9]+0.1377*x[1]*x[8]*x[10]+0.2404*x[1]*x[9]*x[10]+0.4776*x[2]*x[3]*x[4]+0.9781*x[2]*x[3]*x[5]-0.4061*x[2]*x[3]*x[6]-0.8912*x[2]*x[3]*x[7]+0.9125*x[2]*x[3]*x[8]+0.706*x[2]*x[3]*x[9]-0.8906*x[2]*x[3]*x[10]+0.942*x[2]*x[4]*x[5]-0.0261*x[2]*x[4]*x[6]-0.068*x[2]*x[4]*x[7]-0.847*x[2]*x[4]*x[8]+0.5746*x[2]*x[4]*x[9]-0.3526*x[2]*x[4]*x[10]+0.4389*x[2]*x[5]*x[6]+0.4542*x[2]*x[5]*x[7]+0.0367*x[2]*x[5]*x[8]-0.3709*x[2]*x[5]*x[9]+0.8193*x[2]*x[5]*x[10]+0.5633*x[2]*x[6]*x[7]-0.0382*x[2]*x[6]*x[8]-0.959*x[2]*x[6]*x[9]-0.7036*x[2]*x[6]*x[10]+0.7485*x[2]*x[7]*x[8]-0.0868*x[2]*x[7]*x[9]-0.6044*x[2]*x[7]*x[10]+0.3054*x[2]*x[8]*x[9]+0.6064*x[2]*x[8]*x[10]-0.5288*x[2]*x[9]*x[10]-0.0285*x[3]*x[4]*x[5]-0.5481*x[3]*x[4]*x[6]-0.7647*x[3]*x[4]*x[7]+0.6671*x[3]*x[4]*x[8]-0.0921*x[3]*x[4]*x[9]+0.7822*x[3]*x[4]*x[10]-0.688*x[3]*x[5]*x[6]-0.623*x[3]*x[5]*x[7]-0.6958*x[3]*x[5]*x[8]+0.2072*x[3]*x[5]*x[9]+0.8573*x[3]*x[5]*x[10]+0.9353*x[3]*x[6]*x[7]-0.7581*x[3]*x[6]*x[8]-0.6678*x[3]*x[6]*x[9]+0.7244*x[3]*x[6]*x[10]+0.497*x[3]*x[7]*x[8]+0.8841*x[3]*x[7]*x[9]-0.419*x[3]*x[7]*x[10]-0.5639*x[3]*x[8]*x[9]+0.3384*x[3]*x[8]*x[10]+0.8517*x[3]*x[9]*x[10]+0.2487*x[4]*x[5]*x[6]+0.352*x[4]*x[5]*x[7]-0.9956*x[4]*x[5]*x[8]+0.1963*x[4]*x[5]*x[9]+0.6505*x[4]*x[5]*x[10]+0.8868*x[4]*x[6]*x[7]+0.064*x[4]*x[6]*x[8]-0.2306*x[4]*x[6]*x[9]+0.3456*x[4]*x[6]*x[10]-0.0124*x[4]*x[7]*x[8]-0.7644*x[4]*x[7]*x[9]-0.9407*x[4]*x[7]*x[10]-0.5041*x[4]*x[8]*x[9]-0.4612*x[4]*x[8]*x[10]+0.6372*x[4]*x[9]*x[10]-0.9423*x[5]*x[6]*x[7]+0.4769*x[5]*x[6]*x[8]+0.6691*x[5]*x[6]*x[9]-0.6518*x[5]*x[6]*x[10]+0.5892*x[5]*x[7]*x[8]+0.1282*x[5]*x[7]*x[9]-0.0097*x[5]*x[7]*x[10]-0.0037*x[5]*x[8]*x[9]-0.4974*x[5]*x[8]*x[10]-0.1368*x[5]*x[9]*x[10]-0.663*x[6]*x[7]*x[8]-0.3471*x[6]*x[7]*x[9]-0.9665*x[6]*x[7]*x[10]-0.6331*x[6]*x[8]*x[9]-0.0998*x[6]*x[8]*x[10]+0.9348*x[6]*x[9]*x[10]-0.5585*x[7]*x[8]*x[9]-0.1588*x[7]*x[8]*x[10]+0.3535*x[7]*x[9]*x[10]-0.5013*x[8]*x[9]*x[10] <= 70.358) - @NLconstraint(m, e9, 0.5066*x[1]*x[2]+0.5209*x[1]*x[3]-0.8096*x[1]*x[4]+0.2097*x[1]*x[5]-0.8223*x[1]*x[6]+0.8219*x[1]*x[7]+0.8915*x[1]*x[8]+0.4384*x[1]*x[9]+0.0104*x[1]*x[10]-0.6145*x[2]*x[3]+0.3569*x[2]*x[4]-0.0835*x[2]*x[5]-0.1778*x[2]*x[6]+0.1688*x[2]*x[7]-0.6302*x[2]*x[8]+0.0573*x[2]*x[9]+0.8851*x[2]*x[10]+0.9515*x[3]*x[4]-0.0604*x[3]*x[5]-0.8915*x[3]*x[6]-0.0968*x[3]*x[7]-0.5954*x[3]*x[8]-0.902*x[3]*x[9]+0.9315*x[3]*x[10]+0.4294*x[4]*x[5]+0.7398*x[4]*x[6]-0.6759*x[4]*x[7]-0.0166*x[4]*x[8]+0.3176*x[4]*x[9]-0.434*x[4]*x[10]-0.8219*x[5]*x[6]-0.9323*x[5]*x[7]-0.2384*x[5]*x[8]+0.2604*x[5]*x[9]+0.4567*x[5]*x[10]+0.7508*x[6]*x[7]+0.1384*x[6]*x[8]-0.5557*x[6]*x[9]-0.2385*x[6]*x[10]+0.0199*x[7]*x[8]+0.7632*x[7]*x[9]-0.9947*x[7]*x[10]-0.3877*x[8]*x[9]+0.8177*x[8]*x[10]-0.3725*x[9]*x[10]-0.3487*x[1]-0.8521*x[2]+0.7201*x[3]-0.9411*x[4]-0.6075*x[5]+0.4446*x[6]-0.6889*x[7]+0.5368*x[8]+0.9675*x[9]-0.1386*x[10]+0.3477*x[1]*x[2]*x[3]-0.8469*x[1]*x[2]*x[4]-0.0643*x[1]*x[2]*x[5]+0.9855*x[1]*x[2]*x[6]+0.169*x[1]*x[2]*x[7]+0.1277*x[1]*x[2]*x[8]+0.1701*x[1]*x[2]*x[9]-0.2288*x[1]*x[2]*x[10]+0.6269*x[1]*x[3]*x[4]-0.165*x[1]*x[3]*x[5]-0.3328*x[1]*x[3]*x[6]+0.0711*x[1]*x[3]*x[7]+0.8548*x[1]*x[3]*x[8]+0.4886*x[1]*x[3]*x[9]-0.4103*x[1]*x[3]*x[10]+0.1394*x[1]*x[4]*x[5]-0.3792*x[1]*x[4]*x[6]-0.061*x[1]*x[4]*x[7]-0.6923*x[1]*x[4]*x[8]+0.194*x[1]*x[4]*x[9]-0.2253*x[1]*x[4]*x[10]-0.6197*x[1]*x[5]*x[6]-0.799*x[1]*x[5]*x[7]-0.9851*x[1]*x[5]*x[8]-0.164*x[1]*x[5]*x[9]+0.1448*x[1]*x[5]*x[10]+0.0185*x[1]*x[6]*x[7]+0.3829*x[1]*x[6]*x[8]+0.2687*x[1]*x[6]*x[9]+0.9428*x[1]*x[6]*x[10]+0.9418*x[1]*x[7]*x[8]+0.4694*x[1]*x[7]*x[9]+0.8523*x[1]*x[7]*x[10]-0.87*x[1]*x[8]*x[9]-0.5796*x[1]*x[8]*x[10]-0.486*x[1]*x[9]*x[10]+0.3746*x[2]*x[3]*x[4]+0.4788*x[2]*x[3]*x[5]+0.0586*x[2]*x[3]*x[6]+0.1473*x[2]*x[3]*x[7]+0.2498*x[2]*x[3]*x[8]-0.6388*x[2]*x[3]*x[9]+0.2472*x[2]*x[3]*x[10]-0.3687*x[2]*x[4]*x[5]+0.3536*x[2]*x[4]*x[6]+0.0072*x[2]*x[4]*x[7]-0.5806*x[2]*x[4]*x[8]-0.5058*x[2]*x[4]*x[9]-0.116*x[2]*x[4]*x[10]+0.191*x[2]*x[5]*x[6]+0.3699*x[2]*x[5]*x[7]+0.3731*x[2]*x[5]*x[8]+0.0031*x[2]*x[5]*x[9]+0.9294*x[2]*x[5]*x[10]-0.6047*x[2]*x[6]*x[7]+0.2348*x[2]*x[6]*x[8]+0.8324*x[2]*x[6]*x[9]+0.6608*x[2]*x[6]*x[10]-0.1673*x[2]*x[7]*x[8]-0.9519*x[2]*x[7]*x[9]+0.8066*x[2]*x[7]*x[10]-0.9313*x[2]*x[8]*x[9]-0.0297*x[2]*x[8]*x[10]-0.7382*x[2]*x[9]*x[10]-0.672*x[3]*x[4]*x[5]+0.3061*x[3]*x[4]*x[6]-0.1984*x[3]*x[4]*x[7]-0.8696*x[3]*x[4]*x[8]-0.5035*x[3]*x[4]*x[9]+0.2835*x[3]*x[4]*x[10]+0.2576*x[3]*x[5]*x[6]-0.5016*x[3]*x[5]*x[7]-0.738*x[3]*x[5]*x[8]-0.6402*x[3]*x[5]*x[9]+0.2333*x[3]*x[5]*x[10]-0.1863*x[3]*x[6]*x[7]+0.6045*x[3]*x[6]*x[8]-0.5819*x[3]*x[6]*x[9]-0.809*x[3]*x[6]*x[10]-0.3189*x[3]*x[7]*x[8]+0.802*x[3]*x[7]*x[9]-0.8383*x[3]*x[7]*x[10]+0.3569*x[3]*x[8]*x[9]+0.0003*x[3]*x[8]*x[10]+0.8089*x[3]*x[9]*x[10]-0.875*x[4]*x[5]*x[6]+0.4462*x[4]*x[5]*x[7]-0.3338*x[4]*x[5]*x[8]+0.1814*x[4]*x[5]*x[9]-0.8771*x[4]*x[5]*x[10]-0.9101*x[4]*x[6]*x[7]+0.1635*x[4]*x[6]*x[8]-0.1352*x[4]*x[6]*x[9]-0.8026*x[4]*x[6]*x[10]+0.9155*x[4]*x[7]*x[8]+0.5442*x[4]*x[7]*x[9]-0.7053*x[4]*x[7]*x[10]+0.4455*x[4]*x[8]*x[9]+0.9929*x[4]*x[8]*x[10]-0.3529*x[4]*x[9]*x[10]-0.8803*x[5]*x[6]*x[7]-0.9694*x[5]*x[6]*x[8]+0.7938*x[5]*x[6]*x[9]+0.664*x[5]*x[6]*x[10]+0.5083*x[5]*x[7]*x[8]-0.3124*x[5]*x[7]*x[9]-0.4061*x[5]*x[7]*x[10]+0.0858*x[5]*x[8]*x[9]-0.2714*x[5]*x[8]*x[10]-0.8232*x[5]*x[9]*x[10]-0.1146*x[6]*x[7]*x[8]+0.9703*x[6]*x[7]*x[9]+0.9858*x[6]*x[7]*x[10]+0.859*x[6]*x[8]*x[9]+0.0264*x[6]*x[8]*x[10]-0.8325*x[6]*x[9]*x[10]-0.2402*x[7]*x[8]*x[9]+0.9962*x[7]*x[8]*x[10]-0.612*x[7]*x[9]*x[10]-0.7468*x[8]*x[9]*x[10] <= 27.631) - @NLconstraint(m, e10, 0.6845*x[1]*x[2]-0.7219*x[1]*x[3]+0.7798*x[1]*x[4]+0.0733*x[1]*x[5]-0.7376*x[1]*x[6]+0.0256*x[1]*x[7]-0.2386*x[1]*x[8]+0.8016*x[1]*x[9]+0.6794*x[1]*x[10]+0.6011*x[2]*x[3]-0.1622*x[2]*x[4]-0.0369*x[2]*x[5]-0.5992*x[2]*x[6]+0.9241*x[2]*x[7]+0.9873*x[2]*x[8]+0.5992*x[2]*x[9]+0.8133*x[2]*x[10]+0.4239*x[3]*x[4]-0.1981*x[3]*x[5]+0.5006*x[3]*x[6]-0.5385*x[3]*x[7]+0.1593*x[3]*x[8]-0.0871*x[3]*x[9]-0.9382*x[3]*x[10]-0.0148*x[4]*x[5]-0.4904*x[4]*x[6]+0.5096*x[4]*x[7]-0.4809*x[4]*x[8]-0.4848*x[4]*x[9]+0.3062*x[4]*x[10]+0.9318*x[5]*x[6]-0.1853*x[5]*x[7]+0.5946*x[5]*x[8]-0.9998*x[5]*x[9]+0.054*x[5]*x[10]+0.9006*x[6]*x[7]-0.322*x[6]*x[8]-0.4127*x[6]*x[9]-0.6934*x[6]*x[10]+0.408*x[7]*x[8]-0.6923*x[7]*x[9]-0.0869*x[7]*x[10]-0.0219*x[8]*x[9]+0.4814*x[8]*x[10]-0.0782*x[9]*x[10]-0.3978*x[1]-0.0586*x[2]+0.8491*x[3]-0.9975*x[4]+0.5027*x[5]+0.496*x[6]-0.6663*x[7]+0.2055*x[8]-0.1878*x[9]+0.5555*x[10]+(-0.8875*x[1]*x[2]*x[3])-0.7171*x[1]*x[2]*x[4]-0.2179*x[1]*x[2]*x[5]-0.317*x[1]*x[2]*x[6]-0.0332*x[1]*x[2]*x[7]-0.625*x[1]*x[2]*x[8]+0.2913*x[1]*x[2]*x[9]+0.0755*x[1]*x[2]*x[10]-0.0178*x[1]*x[3]*x[4]-0.215*x[1]*x[3]*x[5]-0.7588*x[1]*x[3]*x[6]+0.2416*x[1]*x[3]*x[7]-0.1383*x[1]*x[3]*x[8]+0.2175*x[1]*x[3]*x[9]-0.5311*x[1]*x[3]*x[10]-0.6322*x[1]*x[4]*x[5]-0.8211*x[1]*x[4]*x[6]-0.2421*x[1]*x[4]*x[7]-0.9794*x[1]*x[4]*x[8]+0.6866*x[1]*x[4]*x[9]+0.144*x[1]*x[4]*x[10]+0.935*x[1]*x[5]*x[6]-0.7224*x[1]*x[5]*x[7]-0.79*x[1]*x[5]*x[8]-0.6261*x[1]*x[5]*x[9]-0.59*x[1]*x[5]*x[10]+0.8708*x[1]*x[6]*x[7]+0.5423*x[1]*x[6]*x[8]+0.3356*x[1]*x[6]*x[9]+0.142*x[1]*x[6]*x[10]+0.5119*x[1]*x[7]*x[8]+0.7599*x[1]*x[7]*x[9]-0.4022*x[1]*x[7]*x[10]+0.4446*x[1]*x[8]*x[9]-0.8166*x[1]*x[8]*x[10]+0.6446*x[1]*x[9]*x[10]-0.1284*x[2]*x[3]*x[4]-0.3651*x[2]*x[3]*x[5]-0.2567*x[2]*x[3]*x[6]+0.1421*x[2]*x[3]*x[7]-0.8825*x[2]*x[3]*x[8]-0.6058*x[2]*x[3]*x[9]+0.503*x[2]*x[3]*x[10]-0.0462*x[2]*x[4]*x[5]-0.717*x[2]*x[4]*x[6]+0.0253*x[2]*x[4]*x[7]-0.9476*x[2]*x[4]*x[8]-0.3171*x[2]*x[4]*x[9]+0.5691*x[2]*x[4]*x[10]-0.3612*x[2]*x[5]*x[6]+0.0488*x[2]*x[5]*x[7]+0.423*x[2]*x[5]*x[8]+0.2762*x[2]*x[5]*x[9]+0.0221*x[2]*x[5]*x[10]+0.3975*x[2]*x[6]*x[7]-0.5281*x[2]*x[6]*x[8]-0.722*x[2]*x[6]*x[9]-0.1433*x[2]*x[6]*x[10]+0.1957*x[2]*x[7]*x[8]+0.7882*x[2]*x[7]*x[9]+0.9988*x[2]*x[7]*x[10]+0.8552*x[2]*x[8]*x[9]+0.3681*x[2]*x[8]*x[10]-0.6187*x[2]*x[9]*x[10]-0.2208*x[3]*x[4]*x[5]-0.8222*x[3]*x[4]*x[6]+0.3944*x[3]*x[4]*x[7]+0.4808*x[3]*x[4]*x[8]-0.8075*x[3]*x[4]*x[9]-0.8579*x[3]*x[4]*x[10]-0.5665*x[3]*x[5]*x[6]-0.895*x[3]*x[5]*x[7]-0.3975*x[3]*x[5]*x[8]+0.4934*x[3]*x[5]*x[9]+0.2624*x[3]*x[5]*x[10]+0.2931*x[3]*x[6]*x[7]-0.8108*x[3]*x[6]*x[8]-0.6769*x[3]*x[6]*x[9]-0.2571*x[3]*x[6]*x[10]+0.1818*x[3]*x[7]*x[8]-0.5706*x[3]*x[7]*x[9]+0.6166*x[3]*x[7]*x[10]-0.7727*x[3]*x[8]*x[9]-0.2887*x[3]*x[8]*x[10]-0.6625*x[3]*x[9]*x[10]-0.4673*x[4]*x[5]*x[6]+0.9985*x[4]*x[5]*x[7]-0.0513*x[4]*x[5]*x[8]-0.243*x[4]*x[5]*x[9]+0.9283*x[4]*x[5]*x[10]-0.9095*x[4]*x[6]*x[7]+0.0583*x[4]*x[6]*x[8]+0.823*x[4]*x[6]*x[9]-0.5969*x[4]*x[6]*x[10]+0.8222*x[4]*x[7]*x[8]-0.0405*x[4]*x[7]*x[9]-0.131*x[4]*x[7]*x[10]-0.3485*x[4]*x[8]*x[9]+0.8998*x[4]*x[8]*x[10]-0.2805*x[4]*x[9]*x[10]+0.5217*x[5]*x[6]*x[7]-0.933*x[5]*x[6]*x[8]+0.9836*x[5]*x[6]*x[9]-0.9513*x[5]*x[6]*x[10]-0.9415*x[5]*x[7]*x[8]-0.4551*x[5]*x[7]*x[9]+0.4972*x[5]*x[7]*x[10]-0.429*x[5]*x[8]*x[9]-0.5465*x[5]*x[8]*x[10]-0.1411*x[5]*x[9]*x[10]+0.5444*x[6]*x[7]*x[8]+0.1779*x[6]*x[7]*x[9]+0.0402*x[6]*x[7]*x[10]-0.9732*x[6]*x[8]*x[9]-0.3496*x[6]*x[8]*x[10]-0.2575*x[6]*x[9]*x[10]+0.6694*x[7]*x[8]*x[9]-0.4773*x[7]*x[8]*x[10]+0.4754*x[7]*x[9]*x[10]-0.9142*x[8]*x[9]*x[10] <= 54.766) - @NLconstraint(m, e11, 0.1794*x[1]*x[3]-0.1986*x[1]*x[2]-0.2451*x[1]*x[4]-0.1578*x[1]*x[5]+0.2522*x[1]*x[6]+0.562*x[1]*x[7]+0.9868*x[1]*x[8]+0.0232*x[1]*x[9]+0.5897*x[1]*x[10]+0.1998*x[2]*x[3]-0.9026*x[2]*x[4]+0.5954*x[2]*x[5]-0.0184*x[2]*x[6]-0.9132*x[2]*x[7]-0.0269*x[2]*x[8]+0.5776*x[2]*x[9]+0.2437*x[2]*x[10]-0.9638*x[3]*x[4]+0.4683*x[3]*x[5]-0.0524*x[3]*x[6]+0.865*x[3]*x[7]-0.0714*x[3]*x[8]-0.5196*x[3]*x[9]+0.2146*x[3]*x[10]+0.2514*x[4]*x[5]-0.9667*x[4]*x[6]-0.328*x[4]*x[7]+0.185*x[4]*x[8]-0.1588*x[4]*x[9]-0.6343*x[4]*x[10]+0.7847*x[5]*x[6]+0.2423*x[5]*x[7]-0.357*x[5]*x[8]-0.2066*x[5]*x[9]-0.1247*x[5]*x[10]-0.9086*x[6]*x[7]-0.4053*x[6]*x[8]-0.6526*x[6]*x[9]-0.7753*x[6]*x[10]+0.6139*x[7]*x[8]+0.0606*x[7]*x[9]-0.4917*x[7]*x[10]+0.82*x[8]*x[9]-0.8487*x[8]*x[10]-0.4958*x[9]*x[10]-0.4949*x[1]+0.7862*x[2]+0.7091*x[3]-0.6288*x[4]+0.7083*x[5]+0.4814*x[6]+0.1703*x[7]+0.511*x[8]+0.9122*x[9]+0.1772*x[10]+(-0.3364*x[1]*x[2]*x[3])-0.0269*x[1]*x[2]*x[4]+0.958*x[1]*x[2]*x[5]-0.871*x[1]*x[2]*x[6]-0.3226*x[1]*x[2]*x[7]-0.8197*x[1]*x[2]*x[8]-0.1814*x[1]*x[2]*x[9]-0.8487*x[1]*x[2]*x[10]+0.2095*x[1]*x[3]*x[4]-0.2767*x[1]*x[3]*x[5]-0.3641*x[1]*x[3]*x[6]-0.0245*x[1]*x[3]*x[7]+0.4568*x[1]*x[3]*x[8]+0.3128*x[1]*x[3]*x[9]+0.4853*x[1]*x[3]*x[10]+0.9152*x[1]*x[4]*x[5]-0.5344*x[1]*x[4]*x[6]+0.9609*x[1]*x[4]*x[7]+0.1761*x[1]*x[4]*x[8]+0.344*x[1]*x[4]*x[9]-0.3941*x[1]*x[4]*x[10]+0.8352*x[1]*x[5]*x[6]-0.8145*x[1]*x[5]*x[7]+0.4713*x[1]*x[5]*x[8]-0.2967*x[1]*x[5]*x[9]+0.1227*x[1]*x[5]*x[10]+0.6128*x[1]*x[6]*x[7]-0.5156*x[1]*x[6]*x[8]-0.1357*x[1]*x[6]*x[9]+0.4391*x[1]*x[6]*x[10]-0.916*x[1]*x[7]*x[8]-0.9986*x[1]*x[7]*x[9]+0.3863*x[1]*x[7]*x[10]-0.0975*x[1]*x[8]*x[9]+0.8211*x[1]*x[8]*x[10]+0.6467*x[1]*x[9]*x[10]+0.054*x[2]*x[3]*x[4]+0.0186*x[2]*x[3]*x[5]+0.3056*x[2]*x[3]*x[6]+0.6154*x[2]*x[3]*x[7]+0.0074*x[2]*x[3]*x[8]+0.4949*x[2]*x[3]*x[9]+0.6723*x[2]*x[3]*x[10]+0.3352*x[2]*x[4]*x[5]+0.0008*x[2]*x[4]*x[6]+0.5953*x[2]*x[4]*x[7]-0.6033*x[2]*x[4]*x[8]+0.5045*x[2]*x[4]*x[9]-0.269*x[2]*x[4]*x[10]+0.6495*x[2]*x[5]*x[6]+0.8248*x[2]*x[5]*x[7]-0.6363*x[2]*x[5]*x[8]+0.6394*x[2]*x[5]*x[9]+0.1078*x[2]*x[5]*x[10]+0.8161*x[2]*x[6]*x[7]-0.4037*x[2]*x[6]*x[8]+0.2088*x[2]*x[6]*x[9]-0.6234*x[2]*x[6]*x[10]-0.5131*x[2]*x[7]*x[8]-0.3159*x[2]*x[7]*x[9]-0.3376*x[2]*x[7]*x[10]-0.8348*x[2]*x[8]*x[9]-0.4805*x[2]*x[8]*x[10]+0.8075*x[2]*x[9]*x[10]+0.1383*x[3]*x[4]*x[5]-0.8913*x[3]*x[4]*x[6]-0.4103*x[3]*x[4]*x[7]+0.4252*x[3]*x[4]*x[8]-0.7663*x[3]*x[4]*x[9]-0.9546*x[3]*x[4]*x[10]+0.1664*x[3]*x[5]*x[6]-0.1357*x[3]*x[5]*x[7]+0.843*x[3]*x[5]*x[8]-0.4141*x[3]*x[5]*x[9]+0.9824*x[3]*x[5]*x[10]+0.8706*x[3]*x[6]*x[7]+0.3098*x[3]*x[6]*x[8]-0.8453*x[3]*x[6]*x[9]+0.4691*x[3]*x[6]*x[10]-0.4006*x[3]*x[7]*x[8]+0.3848*x[3]*x[7]*x[9]+0.9792*x[3]*x[7]*x[10]-0.4612*x[3]*x[8]*x[9]-0.9516*x[3]*x[8]*x[10]-0.4543*x[3]*x[9]*x[10]+0.5378*x[4]*x[5]*x[6]-0.8641*x[4]*x[5]*x[7]+0.6423*x[4]*x[5]*x[8]-0.8484*x[4]*x[5]*x[9]-0.3092*x[4]*x[5]*x[10]+0.6513*x[4]*x[6]*x[7]+0.0055*x[4]*x[6]*x[8]+0.0029*x[4]*x[6]*x[9]+0.9821*x[4]*x[6]*x[10]+0.477*x[4]*x[7]*x[8]+0.9873*x[4]*x[7]*x[9]+0.2413*x[4]*x[7]*x[10]+0.3671*x[4]*x[8]*x[9]-0.2025*x[4]*x[8]*x[10]-0.5689*x[4]*x[9]*x[10]+0.6425*x[5]*x[6]*x[7]+0.4043*x[5]*x[6]*x[8]-0.2493*x[5]*x[6]*x[9]-0.4849*x[5]*x[6]*x[10]+0.3103*x[5]*x[7]*x[8]-0.2523*x[5]*x[7]*x[9]+0.7611*x[5]*x[7]*x[10]+0.3698*x[5]*x[8]*x[9]-0.8896*x[5]*x[8]*x[10]+0.7634*x[5]*x[9]*x[10]-0.3524*x[6]*x[7]*x[8]-0.7996*x[6]*x[7]*x[9]+0.4739*x[6]*x[7]*x[10]+0.5203*x[6]*x[8]*x[9]-0.1375*x[6]*x[8]*x[10]-0.0134*x[6]*x[9]*x[10]-0.7802*x[7]*x[8]*x[9]+0.1529*x[7]*x[8]*x[10]-0.7427*x[7]*x[9]*x[10]+0.034*x[8]*x[9]*x[10] <= 80.713) + @NLconstraint( + m, + e1, + -( + 0.9844 * x[1] * x[2] - 0.5504 * x[1] * x[3] + + 0.8946 * x[1] * x[4] + + 0.6956 * x[1] * x[5] + + 0.4003 * x[1] * x[6] + + 0.1089 * x[1] * x[7] - 0.1168 * x[1] * x[8] - 0.5016 * x[1] * x[9] + + 0.7953 * x[1] * x[10] - 0.7085 * x[2] * x[3] - 0.1308 * x[2] * x[4] - + 0.0852 * x[2] * x[5] - 0.3812 * x[2] * x[6] - 0.0382 * x[2] * x[7] + + 0.3795 * x[2] * x[8] + + 0.6216 * x[2] * x[9] - 0.2157 * x[2] * x[10] - 0.4137 * x[3] * x[4] + + 0.152 * x[3] * x[5] + + 0.4507 * x[3] * x[6] - 0.7145 * x[3] * x[7] - 0.3329 * x[3] * x[8] - + 0.6792 * x[3] * x[9] + + 0.0692 * x[3] * x[10] + + 0.4467 * x[4] * x[5] - 0.5436 * x[4] * x[6] - 0.602 * x[4] * x[7] + + 0.9452 * x[4] * x[8] + + 0.9871 * x[4] * x[9] - 0.8361 * x[4] * x[10] - 0.4982 * x[5] * x[6] - + 0.5683 * x[5] * x[7] - 0.6084 * x[5] * x[8] + 0.7005 * x[5] * x[9] - + 0.9106 * x[5] * x[10] + 0.7278 * x[6] * x[7] - 0.8657 * x[6] * x[8] - + 0.1454 * x[6] * x[9] - 0.7254 * x[6] * x[10] - 0.7618 * x[7] * x[8] - + 0.3881 * x[7] * x[9] + + 0.2265 * x[7] * x[10] + + 0.3273 * x[8] * x[9] + + 0.7918 * x[8] * x[10] + + 0.5074 * x[9] * x[10] + + 0.2597 * x[1] - 0.558 * x[2] - 0.0323 * x[3] + + 0.23 * x[4] + + 0.9753 * x[5] + + 0.1184 * x[6] - 0.2582 * x[7] - 0.3248 * x[8] + + 0.4909 * x[9] + + 0.1395 * x[10] + + 0.2647 * x[1] * x[2] * x[3] - 0.5144 * x[1] * x[2] * x[4] - + 0.6792 * x[1] * x[2] * x[5] - 0.9575 * x[1] * x[2] * x[6] - + 0.6195 * x[1] * x[2] * x[7] - 0.3753 * x[1] * x[2] * x[8] + + 0.6193 * x[1] * x[2] * x[9] + + 0.1474 * x[1] * x[2] * x[10] + + 0.6525 * x[1] * x[3] * x[4] - 0.4271 * x[1] * x[3] * x[5] - + 0.679 * x[1] * x[3] * x[6] - 0.3382 * x[1] * x[3] * x[7] - + 0.4683 * x[1] * x[3] * x[8] + + 0.0896 * x[1] * x[3] * x[9] + + 0.107 * x[1] * x[3] * x[10] - 0.9568 * x[1] * x[4] * x[5] - + 0.7025 * x[1] * x[4] * x[6] - 0.7902 * x[1] * x[4] * x[7] + + 0.2284 * x[1] * x[4] * x[8] - 0.1874 * x[1] * x[4] * x[9] + + 0.8031 * x[1] * x[4] * x[10] + + 0.8857 * x[1] * x[5] * x[6] - 0.6868 * x[1] * x[5] * x[7] + + 0.8739 * x[1] * x[5] * x[8] - 0.7291 * x[1] * x[5] * x[9] - + 0.2574 * x[1] * x[5] * x[10] - 0.357 * x[1] * x[6] * x[7] + + 0.4299 * x[1] * x[6] * x[8] + + 0.4594 * x[1] * x[6] * x[9] - 0.2428 * x[1] * x[6] * x[10] + + 0.6579 * x[1] * x[7] * x[8] + + 0.9073 * x[1] * x[7] * x[9] - 0.3832 * x[1] * x[7] * x[10] + + 0.1595 * x[1] * x[8] * x[9] - 0.5331 * x[1] * x[8] * x[10] + + 0.6888 * x[1] * x[9] * x[10] - 0.4837 * x[2] * x[3] * x[4] + + 0.6795 * x[2] * x[3] * x[5] + + 0.0753 * x[2] * x[3] * x[6] + + 0.2431 * x[2] * x[3] * x[7] - 0.0184 * x[2] * x[3] * x[8] - + 0.4303 * x[2] * x[3] * x[9] - 0.5289 * x[2] * x[3] * x[10] + + 0.3028 * x[2] * x[4] * x[5] + + 0.2143 * x[2] * x[4] * x[6] - 0.2037 * x[2] * x[4] * x[7] + + 0.6976 * x[2] * x[4] * x[8] + + 0.2752 * x[2] * x[4] * x[9] - 0.4824 * x[2] * x[4] * x[10] - + 0.2823 * x[2] * x[5] * x[6] + 0.1237 * x[2] * x[5] * x[7] - + 0.7571 * x[2] * x[5] * x[8] + 0.9569 * x[2] * x[5] * x[9] - + 0.2336 * x[2] * x[5] * x[10] + 0.4414 * x[2] * x[6] * x[7] - + 0.2835 * x[2] * x[6] * x[8] + + 0.8198 * x[2] * x[6] * x[9] + + 0.0874 * x[2] * x[6] * x[10] + + 0.9194 * x[2] * x[7] * x[8] + + 0.8589 * x[2] * x[7] * x[9] + + 0.2666 * x[2] * x[7] * x[10] - 0.4088 * x[2] * x[8] * x[9] - + 0.6505 * x[2] * x[8] * x[10] + + 0.6852 * x[2] * x[9] * x[10] + + 0.2372 * x[3] * x[4] * x[5] + + 0.4118 * x[3] * x[4] * x[6] - 0.5151 * x[3] * x[4] * x[7] + + 0.5959 * x[3] * x[4] * x[8] - 0.218 * x[3] * x[4] * x[9] - + 0.7801 * x[3] * x[4] * x[10] + 0.5074 * x[3] * x[5] * x[6] - + 0.9404 * x[3] * x[5] * x[7] + + 0.4013 * x[3] * x[5] * x[8] + + 0.0504 * x[3] * x[5] * x[9] + + 0.5051 * x[3] * x[5] * x[10] + + 0.2954 * x[3] * x[6] * x[7] + + 0.7422 * x[3] * x[6] * x[8] + + 0.6614 * x[3] * x[6] * x[9] + + 0.9144 * x[3] * x[6] * x[10] - 0.5555 * x[3] * x[7] * x[8] + + 0.159 * x[3] * x[7] * x[9] + + 0.9815 * x[3] * x[7] * x[10] + + 0.6799 * x[3] * x[8] * x[9] - 0.6504 * x[3] * x[8] * x[10] + + 0.4191 * x[3] * x[9] * x[10] - 0.3969 * x[4] * x[5] * x[6] - + 0.9499 * x[4] * x[5] * x[7] + + 0.8335 * x[4] * x[5] * x[8] + + 0.3776 * x[4] * x[5] * x[9] + + 0.5135 * x[4] * x[5] * x[10] + + 0.8655 * x[4] * x[6] * x[7] - 0.89 * x[4] * x[6] * x[8] - + 0.0021 * x[4] * x[6] * x[9] - 0.881 * x[4] * x[6] * x[10] - + 0.6563 * x[4] * x[7] * x[8] + 0.3767 * x[4] * x[7] * x[9] - + 0.3868 * x[4] * x[7] * x[10] + + 0.4704 * x[4] * x[8] * x[9] + + 0.5043 * x[4] * x[8] * x[10] - 0.2086 * x[4] * x[9] * x[10] - + 0.8244 * x[5] * x[6] * x[7] - 0.9021 * x[5] * x[6] * x[8] + + 0.5587 * x[5] * x[6] * x[9] + + 0.3616 * x[5] * x[6] * x[10] - 0.3769 * x[5] * x[7] * x[8] + + 0.0455 * x[5] * x[7] * x[9] + + 0.0116 * x[5] * x[7] * x[10] - 0.1229 * x[5] * x[8] * x[9] + + 0.1753 * x[5] * x[8] * x[10] - 0.4053 * x[5] * x[9] * x[10] - + 0.4102 * x[6] * x[7] * x[8] - 0.8524 * x[6] * x[7] * x[9] + + 0.9499 * x[6] * x[7] * x[10] + + 0.4563 * x[6] * x[8] * x[9] + + 0.5162 * x[6] * x[8] * x[10] - 0.3816 * x[6] * x[9] * x[10] - + 0.507 * x[7] * x[8] * x[9] - 0.4862 * x[7] * x[8] * x[10] + + 0.2361 * x[7] * x[9] * x[10] + + 0.8756 * x[8] * x[9] * x[10] + ) + obj == 0.0 + ) return m end \ No newline at end of file diff --git a/src/MOI_wrapper/MOI_wrapper.jl b/src/MOI_wrapper/MOI_wrapper.jl index c0a47a4d..634e97a6 100644 --- a/src/MOI_wrapper/MOI_wrapper.jl +++ b/src/MOI_wrapper/MOI_wrapper.jl @@ -96,7 +96,7 @@ mutable struct Optimizer <: MOI.AbstractOptimizer bound_sol_pool::Dict{Any,Any} # A pool of solutions from solving model_mip # Linking constraints info for Multilinear terms - linking_constraints_info::Union{Nothing, Dict{Any, Any}} # Stored multilinear linking constraints info + linking_constraints_info::Union{Nothing,Dict{Any,Any}} # Stored multilinear linking constraints info # Logging information and status logs::Dict{Symbol,Any} # Logging information diff --git a/src/algorithm.jl b/src/algorithm.jl index e41ef737..adb026af 100644 --- a/src/algorithm.jl +++ b/src/algorithm.jl @@ -213,16 +213,22 @@ function presolve(m::Optimizer) ) Alp.bound_tightening(m, use_bound = true) # performs bound-tightening with the local solve objective value Alp.get_option(m, :presolve_bt) && init_disc(m) # Re-initialize discretization dictionary on tight bounds - Alp.get_option(m, :partition_scaling_factor_branch) && - (Alp.set_option(m, :partition_scaling_factor, Alp.update_partition_scaling_factor(m, true))) + Alp.get_option(m, :partition_scaling_factor_branch) && (Alp.set_option( + m, + :partition_scaling_factor, + Alp.update_partition_scaling_factor(m, true), + )) Alp.add_partition(m, use_solution = m.best_sol) # Setting up the initial discretization elseif m.status[:local_solve] in STATUS_INF (Alp.get_option(m, :log_level) > 0) && println(" Bound tightening without objective bounds (OBBT)") Alp.bound_tightening(m, use_bound = false) # do bound tightening without objective value - (Alp.get_option(m, :partition_scaling_factor_branch)) && - (Alp.set_option(m, :partition_scaling_factor, Alp.update_partition_scaling_factor(m, true))) + (Alp.get_option(m, :partition_scaling_factor_branch)) && (Alp.set_option( + m, + :partition_scaling_factor, + Alp.update_partition_scaling_factor(m, true), + )) Alp.get_option(m, :presolve_bt) && Alp.init_disc(m) elseif m.status[:local_solve] == MOI.INVALID_MODEL @@ -255,7 +261,11 @@ function algorithm_automation(m::Optimizer) Alp.get_option(m, :disc_var_pick) == 3 && Alp.update_disc_cont_var(m) if Alp.get_option(m, :partition_scaling_factor_branch) - Alp.set_option(m, :partition_scaling_factor, Alp.update_partition_scaling_factor(m, true)) # Only perform for a maximum three times + Alp.set_option( + m, + :partition_scaling_factor, + Alp.update_partition_scaling_factor(m, true), + ) # Only perform for a maximum three times end return diff --git a/src/embedding.jl b/src/embedding.jl index cd056fbe..2b26c2e5 100644 --- a/src/embedding.jl +++ b/src/embedding.jl @@ -145,7 +145,11 @@ function ebd_link_xα( base_name = "αA$(var_idx)" ) for i in keys(lifters) # Build first-level evaluation - Alp.relaxation_multilinear_binary(m.model_mip, α_A[lifters[i]-L], [α[j] for j in i]) + Alp.relaxation_multilinear_binary( + m.model_mip, + α_A[lifters[i]-L], + [α[j] for j in i], + ) end α_R = [α; α_A] # Initialize/re-arrgange the variable sequence diff --git a/src/log.jl b/src/log.jl index 4b302db7..a779db29 100644 --- a/src/log.jl +++ b/src/log.jl @@ -99,7 +99,10 @@ function logging_summary(m::Optimizer) if Alp.get_option(m, :partition_scaling_factor_branch) println(" Partition scaling factor branch activated") else - println(" Partition scaling factor = ", Alp.get_option(m, :partition_scaling_factor)) + println( + " Partition scaling factor = ", + Alp.get_option(m, :partition_scaling_factor), + ) end (Alp.get_option(m, :convhull_ebd)) && println(" Using convhull_ebd formulation") (Alp.get_option(m, :convhull_ebd)) && diff --git a/src/multilinear.jl b/src/multilinear.jl index 88f36795..1b60ffca 100644 --- a/src/multilinear.jl +++ b/src/multilinear.jl @@ -707,21 +707,25 @@ Reference: J. Kim, J.P. Richard, M. Tawarmalani, Piecewise Polyhedral Relaxation http://www.optimization-online.org/DB_HTML/2022/07/8974.html """ function _add_multilinear_linking_constraints(m::Optimizer, λ::Dict) - if isnothing(m.linking_constraints_info) - m.linking_constraints_info = Alp._get_shared_multilinear_terms_info(λ, m.options.linking_constraints_degree_limit) + m.linking_constraints_info = Alp._get_shared_multilinear_terms_info( + λ, + m.options.linking_constraints_degree_limit, + ) end - if isnothing(m.linking_constraints_info) + if isnothing(m.linking_constraints_info) return - end + end # Additional linking variables (μ) to the MIP model to keep the constraints sparse - linking_variables = JuMP.@variable(m.model_mip, [i in keys(m.linking_constraints_info)]) - + linking_variables = + JuMP.@variable(m.model_mip, [i in keys(m.linking_constraints_info)]) + # Add linking constraints to the MIP model for (shared_multilinear_idx, multilinear_terms_idx) in m.linking_constraints_info, (i, multilinear_idx) in enumerate(multilinear_terms_idx) + var_location = [findfirst(multilinear_idx .== i) for i in shared_multilinear_idx] lambda_expr = 0 @@ -734,7 +738,10 @@ function _add_multilinear_linking_constraints(m::Optimizer, λ::Dict) lambda_expr += partitions_info * var end - JuMP.@constraint(m.model_mip, linking_variables[shared_multilinear_idx] == lambda_expr) + JuMP.@constraint( + m.model_mip, + linking_variables[shared_multilinear_idx] == lambda_expr + ) end end @@ -746,19 +753,20 @@ necessary for a given vector of each multilinear terms and returns the approapri linking constraints information. """ function _get_shared_multilinear_terms_info( - λ::Dict, - linking_constraints_degree_limit::Union{Nothing,T} where {T<:Int64} = nothing + λ::Dict, + linking_constraints_degree_limit::Union{Nothing,T} where {T<:Int64} = nothing, ) - + # Compute maximum degree of multilinear terms and return if bilinear - max_degree = maximum([length(k) for k in keys(λ)]) + max_degree = maximum([length(k) for k in keys(λ)]) if max_degree <= 2 return (linking_constraints_info = nothing) end # Limit the linking constraints to a prescribed multilinear degree - if !isnothing(linking_constraints_degree_limit) && (linking_constraints_degree_limit < max_degree) + if !isnothing(linking_constraints_degree_limit) && + (linking_constraints_degree_limit < max_degree) max_degree = linking_constraints_degree_limit end @@ -766,7 +774,8 @@ function _get_shared_multilinear_terms_info( all_variables_idx = collect(union((keys(λ) |> collect)...)) |> sort linking_constraints_info = Dict( - shared_multilinear_idx => filter(r -> issubset(shared_multilinear_idx, r), keys(λ)) for + shared_multilinear_idx => + filter(r -> issubset(shared_multilinear_idx, r), keys(λ)) for deg in 2:(max_degree-1) for shared_multilinear_idx in Combinatorics.combinations(all_variables_idx, deg) ) @@ -777,4 +786,4 @@ function _get_shared_multilinear_terms_info( end return (linking_constraints_info = linking_constraints_info) -end \ No newline at end of file +end diff --git a/src/relaxations.jl b/src/relaxations.jl index 96f853ad..955dcfa0 100644 --- a/src/relaxations.jl +++ b/src/relaxations.jl @@ -25,9 +25,8 @@ function relaxation_bilinear( lb_x::Number, ub_x::Number, lb_y::Number, - ub_y::Number + ub_y::Number, ) - JuMP.@constraint(m, z >= lb_x * y + lb_y * x - lb_x * lb_y) JuMP.@constraint(m, z >= ub_x * y + ub_y * x - ub_x * ub_y) JuMP.@constraint(m, z <= lb_x * y + ub_y * x - lb_x * ub_y) @@ -45,7 +44,11 @@ end Applies Fortet linearization (see https://doi.org/10.1007/s10288-006-0015-3) for z = prod(x), where x is a vector of binary variables. """ -function relaxation_multilinear_binary(m::JuMP.Model, z::JuMP.VariableRef, x::Vector{VariableRef}) +function relaxation_multilinear_binary( + m::JuMP.Model, + z::JuMP.VariableRef, + x::Vector{VariableRef}, +) for i in x JuMP.@constraint(m, z <= i) end @@ -78,4 +81,4 @@ function relaxation_quadratic_univariate( return end -=# \ No newline at end of file +=# diff --git a/src/solver_options.jl b/src/solver_options.jl index 9fdba88b..fc494d5e 100644 --- a/src/solver_options.jl +++ b/src/solver_options.jl @@ -61,7 +61,6 @@ mutable struct OptimizerOptions # Domain Reduction presolve_bp::Bool # Conduct basic bound propagation - end function get_default_options() @@ -155,6 +154,6 @@ function get_default_options() presolve_bt_algo, presolve_bt_relax_integrality, presolve_bt_mip_time_limit, - presolve_bp + presolve_bp, ) end diff --git a/test/test_algorithm.jl b/test/test_algorithm.jl index f3b1878a..e197fe0c 100644 --- a/test/test_algorithm.jl +++ b/test/test_algorithm.jl @@ -590,7 +590,7 @@ # @test termination_status(m) == MOI.OTHER_LIMIT # @test isapprox(objective_value(m), 58.38367169858795; atol = 1e-5) # @test isapprox(alp.best_bound, 57.012, atol = 1E-4) - + # @test MOI.get(m, Alpine.NumberOfIterations()) == 1 # end @@ -937,7 +937,7 @@ "mip_solver" => HIGHS, "presolve_bt" => false, "apply_partitioning" => true, - "linking_constraints" => false + "linking_constraints" => false, ) m = linking_constraints_testing(solver = test_solver) JuMP.optimize!(m) @@ -953,21 +953,20 @@ "mip_solver" => HIGHS, "presolve_bt" => false, "apply_partitioning" => true, - "linking_constraints" => true + "linking_constraints" => true, ) m = linking_constraints_testing(solver = test_solver) JuMP.optimize!(m) alp = JuMP.backend(m).optimizer.model @test isapprox(JuMP.objective_value(m), -0.5294000135, atol = 1E-5) @test MOI.get(m, Alpine.NumberOfIterations()) == 1 - @test in(Set{Any}([1,2]), alp.linking_constraints_info[[1,2]]) - @test in(Set{Any}([1,2,3]), alp.linking_constraints_info[[1,2]]) - @test in(Set{Any}([1,2,4]), alp.linking_constraints_info[[1,2]]) - @test in(Set{Any}([1,3]), alp.linking_constraints_info[[1,3]]) - @test in(Set{Any}([1,2,3]), alp.linking_constraints_info[[1,3]]) - @test in(Set{Any}([1,3,4]), alp.linking_constraints_info[[1,3]]) - @test in(Set{Any}([1,4]), alp.linking_constraints_info[[1,4]]) - @test in(Set{Any}([1,2,4]), alp.linking_constraints_info[[1,4]]) - @test in(Set{Any}([1,3,4]), alp.linking_constraints_info[[1,4]]) - -end \ No newline at end of file + @test in(Set{Any}([1, 2]), alp.linking_constraints_info[[1, 2]]) + @test in(Set{Any}([1, 2, 3]), alp.linking_constraints_info[[1, 2]]) + @test in(Set{Any}([1, 2, 4]), alp.linking_constraints_info[[1, 2]]) + @test in(Set{Any}([1, 3]), alp.linking_constraints_info[[1, 3]]) + @test in(Set{Any}([1, 2, 3]), alp.linking_constraints_info[[1, 3]]) + @test in(Set{Any}([1, 3, 4]), alp.linking_constraints_info[[1, 3]]) + @test in(Set{Any}([1, 4]), alp.linking_constraints_info[[1, 4]]) + @test in(Set{Any}([1, 2, 4]), alp.linking_constraints_info[[1, 4]]) + @test in(Set{Any}([1, 3, 4]), alp.linking_constraints_info[[1, 4]]) +end diff --git a/test/test_expression.jl b/test/test_expression.jl index 154a9685..7ece0cd4 100644 --- a/test/test_expression.jl +++ b/test/test_expression.jl @@ -3647,7 +3647,7 @@ "nlp_solver" => IPOPT, "mip_solver" => HIGHS, "presolve_bt" => true, - "linking_constraints" => false + "linking_constraints" => false, ) m = Model(test_solver) From 0db0fc1865428d3ed46b2590773f84645fad1838 Mon Sep 17 00:00:00 2001 From: harshangrjn Date: Mon, 5 Sep 2022 19:47:15 -0600 Subject: [PATCH 14/18] tests activated --- examples/MINLPs/mult3.jl | 2 +- test/runtests.jl | 6 +- test/test_algorithm.jl | 1858 +++++----- test/test_expression.jl | 7280 +++++++++++++++++++------------------- 4 files changed, 4573 insertions(+), 4573 deletions(-) diff --git a/examples/MINLPs/mult3.jl b/examples/MINLPs/mult3.jl index e5bc1ee9..2351d622 100644 --- a/examples/MINLPs/mult3.jl +++ b/examples/MINLPs/mult3.jl @@ -279,4 +279,4 @@ function m_10_3_0_100_2(; solver = nothing) ) return m -end \ No newline at end of file +end diff --git a/test/runtests.jl b/test/runtests.jl index 9035a6bc..2464a074 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -51,8 +51,8 @@ end # Perform Tests @testset "Alpine tests" begin - # include(joinpath(@__DIR__, "test_solver.jl")) + include(joinpath(@__DIR__, "test_solver.jl")) include(joinpath(@__DIR__, "test_expression.jl")) - # include(joinpath(@__DIR__, "test_algorithm.jl")) - # include(joinpath(@__DIR__, "test_utility.jl")) + include(joinpath(@__DIR__, "test_algorithm.jl")) + include(joinpath(@__DIR__, "test_utility.jl")) end diff --git a/test/test_algorithm.jl b/test/test_algorithm.jl index e197fe0c..588bc14b 100644 --- a/test/test_algorithm.jl +++ b/test/test_algorithm.jl @@ -1,932 +1,932 @@ -# @testset " Validation Test || AMP-TMC || basic solve || examples/nlp3.jl (2 iterations)" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# # "bilinear_convexhull" => false, -# # "monomial_convexhull" => false, -# "presolve_bp" => true, -# "max_iter" => 2, -# "presolve_bt_width_tol" => 1e-3, -# "presolve_bt" => false, -# "partition_scaling_factor" => 10, -# "disc_var_pick" => 0, -# ) -# m = nlp3(solver = test_solver) -# JuMP.optimize!(m) - -# @test termination_status(m) == MOI.OTHER_LIMIT - -# @test isapprox(objective_value(m), 7049.247897696512; atol = 1e-4) -# @test MOI.get(m, Alpine.NumberOfIterations()) == 2 -# end - -# @testset " Validation Test || AMP-TMC || minimum-vertex solving || examples/nlp3.jl (3 iterations)" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# # "bilinear_convexhull" => false, -# # "monomial_convexhull" => false, -# "presolve_bp" => true, -# "disc_var_pick" => 1, -# "max_iter" => 2, -# "partition_scaling_factor" => 10, -# "presolve_bt_width_tol" => 1e-3, -# "presolve_bt" => false, -# ) -# m = nlp3(solver = test_solver) -# JuMP.optimize!(m) - -# @test termination_status(m) == MOI.OTHER_LIMIT -# @test isapprox(objective_value(m), 7049.247897696512; atol = 1e-4) -# @test MOI.get(m, Alpine.NumberOfIterations()) == 2 -# end - -# @testset " Validation Test || BT-AMP-TMC || basic solve || examples/nlp3.jl" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# # "bilinear_convexhull" => false, -# "log_level" => 100, -# "max_iter" => 2, -# "partition_scaling_factor" => 10, -# "presolve_bt_width_tol" => 1e-3, -# "presolve_bt_bound_tol" => 1e-1, -# "presolve_bt" => true, -# "presolve_bt_algo" => 1, -# "presolve_bp" => true, -# "presolve_bt_max_iter" => 2, -# "presolve_track_time" => true, -# "disc_var_pick" => max_cover_var_picker, -# ) -# m = nlp3(solver = test_solver) - -# JuMP.optimize!(m) - -# @test termination_status(m) == MOI.OTHER_LIMIT -# @test MOI.get(m, Alpine.NumberOfIterations()) == 2 -# @test MOI.get(m, Alpine.NumberOfPresolveIterations()) == 2 - -# vars = all_variables(m) -# LB = [100, 1000, 1000, 10, 150.2, 10, 35.4, 168] -# UB = [4573.6, 5547.8, 5913.3, 332.4, 551, 390, 571.1, 638.7] -# @test isapprox(MOI.get.(m, Alpine.TightenedLowerBound(), vars), LB, atol = 1E-6) -# @test isapprox(MOI.get.(m, Alpine.TightenedUpperBound(), vars), UB, atol = 1E-6) -# end - -# # FIXME Pavito terminates with `NUMERICAL_ERROR` on Julia v1.0: -# @testset " Validation Test || PBT-AMP-TMC || basic solve || examples/nlp3.jl" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# # "bilinear_convexhull" => false, -# "log_level" => 100, -# "max_iter" => 2, -# "partition_scaling_factor" => 10, -# "presolve_bt" => true, -# "presolve_bt_width_tol" => 1e-3, -# "presolve_bt_bound_tol" => 1e-1, -# "presolve_bt_algo" => 2, -# "presolve_bp" => true, -# "presolve_bt_max_iter" => 2, -# "disc_var_pick" => max_cover_var_picker, -# ) - -# m = nlp3(solver = test_solver) -# JuMP.optimize!(m) -# @test termination_status(m) == MOI.OTHER_LIMIT -# @test MOI.get(m, Alpine.NumberOfIterations()) == 2 -# end - -# @testset " Validation Test || AMP-CONV || basic solve || examples/nlp1.jl" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => PAVITO, -# # "bilinear_convexhull" => true, -# # "monomial_convexhull" => true, -# "presolve_bt" => false, -# "presolve_bp" => true, -# "partition_scaling_factor" => 12, -# "max_iter" => 1, -# ) -# m = nlp1(solver = test_solver) -# JuMP.optimize!(m) - -# @test termination_status(m) == MOI.OTHER_LIMIT -# @test isapprox(objective_value(m), 58.38367169858795; atol = 1e-5) -# @test MOI.get(m, Alpine.NumberOfIterations()) == 1 -# end - -# @testset " Validation Test || AMP-CONV || basic solve || examples/nlp3.jl" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# # "bilinear_convexhull" => true, -# # "monomial_convexhull" => true, -# "presolve_bt" => false, -# "presolve_bp" => false, -# "partition_scaling_factor" => 14, -# "max_iter" => 4, -# "log_level" => 100, -# ) -# m = nlp3(solver = test_solver) -# JuMP.optimize!(m) - -# @test termination_status(m) == MOI.OTHER_LIMIT -# @test isapprox(objective_value(m), 7049.24789; atol = 1e-4) -# @test isapprox(objective_bound(m), 6839.487709940, atol = 1E-4) -# @test MOI.get(m, Alpine.NumberOfIterations()) == 4 -# end - -# @testset " Validation Test || AMP || basic solve || examples/circle.jl" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => PAVITO, -# "disc_abs_width_tol" => 1e-3, -# "partition_scaling_factor" => 8, -# "max_iter" => 6, -# "presolve_bt" => false, -# "log_level" => 100, -# ) - -# m = circle(solver = test_solver) -# # This is fixed in Alpine - TODO (odow): cycling detected in Pavito when disc_abs_width_tol = 1E-2 -# JuMP.optimize!(m) -# @test isapprox(objective_value(m), 1.4142135534556992; atol = 1e-3) -# end - -# @testset " Validation Test || AMP || basic solve || examples/circle_MINLPLib.jl" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => PAVITO, -# "presolve_bt" => false, -# "partition_scaling_factor" => 15, -# "max_iter" => 2, -# ) - -# m = circle_MINLPLib(solver = test_solver) - -# JuMP.optimize!(m) -# @test termination_status(m) == MOI.OPTIMAL -# @test isapprox(objective_value(m), 4.45670663096; atol = 1E-6) -# end - -# @testset " Validation Test || AMP-CONV-FACET || basic solve || examples/nlp3.jl" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# # "bilinear_convexhull" => true, -# # "monomial_convexhull" => true, -# "presolve_bt" => false, -# "presolve_bp" => true, -# "convhull_formulation" => "facet", -# "max_iter" => 3, -# "log_level" => 100, -# ) -# m = nlp3(solver = test_solver) -# JuMP.optimize!(m) - -# @test isapprox(objective_value(m), 7049.247897696188; atol = 1e-4) -# @test isapprox(objective_bound(m), 6654.6983279983; atol = 1e-4) -# @test MOI.get(m, Alpine.NumberOfIterations()) == 3 -# end - -# @testset " Validation Test || AMP || multi4N || N = 2 || exprmode=1:11" begin -# n_instances = 5 -# objValVec = 2.0 * ones(n_instances) - -# for i in 1:n_instances -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "disc_abs_width_tol" => 1e-2, -# "max_iter" => 4, -# "partition_scaling_factor" => 4, -# "presolve_bp" => false, -# "presolve_bt" => false, -# "log_level" => 1, -# ) - -# m = multi4N(solver = test_solver, N = 2, exprmode = i) -# JuMP.optimize!(m) - -# @test termination_status(m) == MOI.OTHER_LIMIT -# @test isapprox(objective_value(m), objValVec[i]; atol = 1e-3) -# end -# end - -# @testset " Validation Test || AMP || multi2 || exprmode=1:11" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "disc_abs_width_tol" => 1e-2, -# "max_iter" => 5, -# "presolve_bt" => false, -# "log_level" => 1, -# ) - -# m = multi2(solver = test_solver) -# JuMP.optimize!(m) -# @test termination_status(m) == MOI.OPTIMAL -# @test isapprox(objective_value(m), 0.92906489; atol = 1e-3) -# end - -# @testset " Validation Test || AMP || multi3N || N = 2 || exprmode=1:11" begin -# n_instances = 3 -# objValVec = 2.0 * ones(n_instances) - -# objBoundVec = Any[2.97186, 3.85492, 4.23375] - -# for i in 1:n_instances -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "disc_abs_width_tol" => 1e-2, -# "max_iter" => 4, -# "partition_scaling_factor" => 4, -# "presolve_bp" => false, -# "presolve_bt" => false, -# "log_level" => 1, -# ) - -# m = multi3N(solver = test_solver, N = 2, exprmode = i) -# JuMP.optimize!(m) - -# @test termination_status(m) == MOI.OTHER_LIMIT -# @test isapprox(objective_value(m), objValVec[i]; atol = 1e-3) -# @test objective_bound(m) <= objBoundVec[i] + 1e-3 -# end -# end - -# @testset " Validation Test || AMP || multiKND || K = 3, N = 3, D = 0 " begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "disc_abs_width_tol" => 1e-2, -# "max_iter" => 3, -# "partition_scaling_factor" => 4, -# "presolve_bp" => false, -# "presolve_bt" => false, -# "log_level" => 1, -# ) - -# m = multiKND(solver = test_solver, randomub = 50, K = 3, N = 3, D = 0) -# JuMP.optimize!(m) - -# @test termination_status(m) == MOI.OTHER_LIMIT -# @test isapprox(objective_value(m), 3.0000000824779454; atol = 1e-3) -# @test isapprox(objective_bound(m), 12.054604248046875; atol = 1e-3) -# end - -# @testset " Validation Test || AMP-CONV-FACET || basic solve || examples/nlp3.jl" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# # "bilinear_convexhull" => true, -# # "monomial_convexhull" => true, -# "presolve_bt" => false, -# "presolve_bp" => false, -# "max_iter" => 3, -# "partition_scaling_factor" => 4, -# "convhull_formulation" => "facet", -# "log_level" => 100, -# ) -# m = nlp3(solver = test_solver) -# JuMP.optimize!(m) - -# @test termination_status(m) == MOI.OTHER_LIMIT -# @test isapprox(objective_value(m), 7049.247897696188; atol = 1e-4) -# @test isapprox(objective_bound(m), 5871.530692199214; atol = 1E-5) -# @test MOI.get(m, Alpine.NumberOfIterations()) == 3 -# end - -# @testset " Validation Test || AMP || PARTITION-SCALING-FACTOR || examples/nlp3.jl " begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "disc_abs_width_tol" => 1e-2, -# "partition_scaling_factor_branch" => false, -# "partition_scaling_factor" => 18, -# "max_iter" => 1, -# "presolve_bp" => true, -# "presolve_bt" => false, -# "log_level" => 100, -# ) - -# m = nlp3(solver = test_solver) -# JuMP.optimize!(m) - -# @test MOI.get(m, Alpine.NumberOfIterations()) == 1 -# @test MOI.get(m, MOI.RawOptimizerAttribute("partition_scaling_factor")) == 18 -# end - -# @testset " Validation Test || AMP || PARTITION-SCALING-FACTOR-BRANCH || examples/nlp3.jl " begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "disc_abs_width_tol" => 1e-2, -# "partition_scaling_factor_branch" => true, -# "max_iter" => 1, -# "presolve_bp" => true, -# "presolve_bt" => false, -# "log_level" => 100, -# ) - -# m = nlp3(solver = test_solver) -# JuMP.optimize!(m) - -# @test MOI.get(m, Alpine.NumberOfIterations()) == 1 -# @test MOI.get(m, MOI.RawOptimizerAttribute("partition_scaling_factor")) == 14 -# end - -# @testset " Validation Test || AMP || PARTITION-SCALING-FACTOR-BRANCH || examples/castro2m2.jl " begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "disc_abs_width_tol" => 1e-2, -# "partition_scaling_factor_branch" => true, -# "max_iter" => 1, -# "presolve_bp" => true, -# "presolve_bt" => false, -# "log_level" => 100, -# ) - -# m = castro2m2(solver = test_solver) -# JuMP.optimize!(m) - -# @test MOI.get(m, Alpine.NumberOfIterations()) == 1 -# @test MOI.get(m, MOI.RawOptimizerAttribute("partition_scaling_factor")) == 8 -# end - -# @testset " Validation Test || AMP || PARTITION-SCALING-FACTOR-BRANCH || examples/multi3N.jl exprmode=2" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "disc_abs_width_tol" => 1e-2, -# "partition_scaling_factor_branch" => true, -# "max_iter" => 1, -# "presolve_bp" => true, -# "presolve_bt" => false, -# "log_level" => 100, -# ) - -# m = multi3N(solver = test_solver, N = 3, exprmode = 1) -# JuMP.optimize!(m) - -# @test MOI.get(m, Alpine.NumberOfIterations()) == 1 -# @test MOI.get(m, MOI.RawOptimizerAttribute("partition_scaling_factor")) == 16 -# end - -# @testset " Validation Test || AMP || PARTITION-SCALING-FACTOR-BRANCH || examples/multi3N.jl exprmode=2" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "disc_abs_width_tol" => 1e-2, -# "partition_scaling_factor_branch" => true, -# "max_iter" => 1, -# "presolve_bp" => false, -# "presolve_bt" => false, -# "log_level" => 100, -# ) - -# m = multi3N(solver = test_solver, N = 3, exprmode = 1) -# JuMP.optimize!(m) - -# @test MOI.get(m, Alpine.NumberOfIterations()) == 1 -# @test MOI.get(m, MOI.RawOptimizerAttribute("partition_scaling_factor")) == 20 -# end - -# @testset " Validation Test || AMP || PARTITION-SCALING-FACTOR-BRANCH || examples/multi4N.jl exprmode=1" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "disc_abs_width_tol" => 1e-2, -# "partition_scaling_factor_branch" => true, -# "max_iter" => 1, -# "presolve_bp" => true, -# "presolve_bt" => false, -# "log_level" => 100, -# ) - -# m = multi4N(solver = test_solver, N = 2, exprmode = 1) -# JuMP.optimize!(m) - -# @test MOI.get(m, Alpine.NumberOfIterations()) == 1 -# @test MOI.get(m, MOI.RawOptimizerAttribute("partition_scaling_factor")) == 12 -# end - -# @testset " Validation Test || AMP || PARTITION-SCALING-FACTOR-BRANCH || examples/multi4N.jl exprmode=2" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "disc_abs_width_tol" => 1e-2, -# "partition_scaling_factor_branch" => true, -# "max_iter" => 1, -# "presolve_bp" => false, -# "presolve_bt" => false, -# "log_level" => 100, -# ) - -# m = multi4N(solver = test_solver, N = 2, exprmode = 1) -# JuMP.optimize!(m) - -# @test MOI.get(m, Alpine.NumberOfIterations()) == 1 -# @test MOI.get(m, MOI.RawOptimizerAttribute("partition_scaling_factor")) == 20 -# end - -# @testset " Validation Test || AMP || PARTITION-SCALING-FACTOR-BRANCH || examples/multi4N.jl exprmode=2" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "disc_abs_width_tol" => 1e-2, -# "partition_scaling_factor_branch" => true, -# "max_iter" => 1, -# "presolve_bp" => true, -# "presolve_bt" => false, -# "log_level" => 100, -# ) - -# m = multi4N(solver = test_solver, N = 2, exprmode = 2) -# JuMP.optimize!(m) - -# @test MOI.get(m, Alpine.NumberOfIterations()) == 1 -# @test MOI.get(m, MOI.RawOptimizerAttribute("partition_scaling_factor")) == 20 -# end - -# @testset "Operator :: bmpl && binlin && binprod solve test I" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "minlp_solver" => PAVITO, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "presolve_bt" => false, -# "log_level" => 100, -# ) - -# m = bpml_lnl(solver = test_solver) -# JuMP.optimize!(m) -# @test isapprox(objective_value(m), 0.3; atol = 1e-6) -# alpine = JuMP.backend(m).optimizer.model -# @test haskey(alpine.nonconvex_terms, Expr[:(x[1]), :(x[6])]) -# @test haskey(alpine.nonconvex_terms, Expr[:(x[2]), :(x[7])]) -# @test haskey(alpine.nonconvex_terms, Expr[:(x[3]), :(x[8])]) -# @test haskey(alpine.nonconvex_terms, Expr[:(x[4]), :(x[9])]) -# @test haskey(alpine.nonconvex_terms, Expr[:(x[5]), :(x[10])]) - -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[6])]][:nonlinear_type] == :BINLIN -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[7])]][:nonlinear_type] == :BINLIN -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[8])]][:nonlinear_type] == :BINLIN -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[9])]][:nonlinear_type] == :BINLIN -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[10])]][:nonlinear_type] == :BINLIN -# end - -# @testset "Operator :: bmpl && binlin && binprod solve test II" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "minlp_solver" => JUNIPER, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "presolve_bt" => false, -# "partition_scaling_factor" => 4, -# "log_level" => 100, -# ) - -# m = bpml_binl(solver = test_solver) - -# # FIXME: Deactivating this until Juniper v0.9.0's numerical issues are fixed. -# # JuMP.optimize!(m) -# # @test isapprox(JuMP.objective_value(m), 22812.76415926; atol=1e-6) -# # alpine = JuMP.backend(m).optimizer.model - -# alpine = _build(m) -# @test haskey(alpine.nonconvex_terms, Expr[:(x[6]), :(x[7])]) -# @test haskey(alpine.nonconvex_terms, Expr[:(x[7]), :(x[8])]) -# @test haskey(alpine.nonconvex_terms, Expr[:(x[8]), :(x[9])]) -# @test haskey(alpine.nonconvex_terms, Expr[:(x[9]), :(x[10])]) -# @test haskey(alpine.nonconvex_terms, Expr[:(x[10]), :(x[6])]) -# @test haskey(alpine.nonconvex_terms, Expr[:(x[1]), :(x[11])]) -# @test haskey(alpine.nonconvex_terms, Expr[:(x[2]), :(x[13])]) -# @test haskey(alpine.nonconvex_terms, Expr[:(x[3]), :(x[15])]) -# @test haskey(alpine.nonconvex_terms, Expr[:(x[4]), :(x[17])]) -# @test haskey(alpine.nonconvex_terms, Expr[:(x[5]), :(x[19])]) - -# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[7])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[7]), :(x[8])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[8]), :(x[9])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[6])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[11])]][:nonlinear_type] == :BINLIN -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[13])]][:nonlinear_type] == :BINLIN -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[15])]][:nonlinear_type] == :BINLIN -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[17])]][:nonlinear_type] == :BINLIN -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[19])]][:nonlinear_type] == :BINLIN -# end - -# @testset "Embedding Test || AMP-CONV || basic solve || examples/nlp1.jl" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => PAVITO, -# # "bilinear_convexhull" => true, -# # "monomial_convexhull" => true, -# "presolve_bt" => false, -# "presolve_bp" => true, -# "convhull_ebd" => true, -# "max_iter" => 1, -# "partition_scaling_factor" => 4, -# "log_level" => 100, -# ) - -# m = nlp1(solver = test_solver) -# JuMP.optimize!(m) -# alp = JuMP.backend(m).optimizer.model - -# @test termination_status(m) == MOI.OTHER_LIMIT -# @test isapprox(objective_value(m), 58.38367169858795; atol = 1e-4) -# @test isapprox(alp.best_bound, 52.9702, atol = 1E-4) -# @test MOI.get(m, Alpine.NumberOfIterations()) == 1 -# end - -# @testset "Embedding IBS Test || AMP-CONV || basic solve || examples/nlp1.jl" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => PAVITO, -# # "bilinear_convexhull" => true, -# # "monomial_convexhull" => true, -# "presolve_bt" => false, -# "presolve_bp" => true, -# "convhull_ebd" => true, -# "convhull_ebd_ibs" => true, -# "partition_scaling_factor" => 8, -# "max_iter" => 1, -# "log_level" => 100, -# ) -# m = nlp1(solver = test_solver) -# JuMP.optimize!(m) -# alp = JuMP.backend(m).optimizer.model - -# @test termination_status(m) == MOI.OTHER_LIMIT -# @test isapprox(objective_value(m), 58.38367169858795; atol = 1e-5) -# @test isapprox(alp.best_bound, 57.012, atol = 1E-4) - -# @test MOI.get(m, Alpine.NumberOfIterations()) == 1 -# end - -# @testset "Embedding IBS Test || AMP-CONV || basic solve || examples/nlp3.jl" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# # "bilinear_convexhull" => true, -# # "monomial_convexhull" => true, -# "presolve_bt" => false, -# "presolve_bp" => false, -# "convhull_ebd" => true, -# "convhull_ebd_ibs" => true, -# "max_iter" => 3, -# ) -# m = nlp3(solver = test_solver) -# JuMP.optimize!(m) -# alp = JuMP.backend(m).optimizer.model - -# @test termination_status(m) == MOI.OTHER_LIMIT -# @test isapprox(objective_value(m), 7049.247897696188; atol = 1e-5) -# @test MOI.get(m, Alpine.NumberOfIterations()) == 3 -# @test isapprox(alp.best_bound, 6893.2067, atol = 1E-4) -# end - -# @testset "Embedding IBS Test || AMP || special problem || ... " begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => PAVITO, -# "disc_abs_width_tol" => 1e-3, -# "partition_scaling_factor" => 8, -# "max_iter" => 6, -# "presolve_bt" => false, -# "presolve_bp" => true, -# "presolve_bt_algo" => 1, -# "presolve_bt_bound_tol" => 1e-1, -# "convhull_ebd" => true, -# "convhull_ebd_ibs" => true, -# "log_level" => 100, -# ) - -# m = circle(solver = test_solver) -# # This is fixed in Alpine - TODO(odow): mixed-integer cycling detected, terminating Pavito -# JuMP.optimize!(m) -# @test isapprox(objective_value(m), 1.41421355; atol = 1e-3) -# end - -# @testset "Embedding LINK Test || AMP-CONV || basic solve || examples/nlp3.jl" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# # "bilinear_convexhull" => true, -# # "monomial_convexhull" => true, -# "presolve_bt" => false, -# "presolve_bp" => false, -# "convhull_ebd" => true, -# "convhull_ebd_link" => true, -# "partition_scaling_factor" => 10, -# "max_iter" => 3, -# "log_level" => 100, -# ) -# m = nlp3(solver = test_solver) -# JuMP.optimize!(m) - -# @test termination_status(m) == MOI.OTHER_LIMIT -# @test isapprox(objective_value(m), 7049.247897696188; atol = 1e-4) -# @test MOI.get(m, Alpine.NumberOfIterations()) == 3 -# end - -# @testset "Algorithm Logic Test || castro4m2 || 1 iteration || Error case" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "max_iter" => 1, -# "presolve_bt" => false, -# "partition_scaling_factor" => 10, -# "log_level" => 100, -# ) - -# m = castro4m2(solver = test_solver) -# JuMP.optimize!(m) -# @test termination_status(m) == MOI.OTHER_LIMIT -# end - -# @testset " Algorithm Logic Test || blend029_gl || 3 iterations || Infeasible Case" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "minlp_solver" => PAVITO, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "presolve_bp" => true, -# "disc_var_pick" => 1, -# "log_level" => 100, -# "max_iter" => 3, -# "partition_scaling_factor" => 10, -# "presolve_bt_width_tol" => 1e-3, -# "presolve_bt" => false, -# ) -# m = blend029_gl(solver = test_solver) -# JuMP.optimize!(m) - -# @test termination_status(m) == MOI.OTHER_LIMIT -# @test MOI.get(m, Alpine.NumberOfIterations()) == 3 -# @test objective_bound(m) <= 14.0074 -# end - -# @testset "Convex Model Solve" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => PAVITO, -# "max_iter" => 1, -# "presolve_bt" => false, -# "log_level" => 100, -# ) -# m = convex_solve(solver = test_solver) -# JuMP.optimize!(m) -# @test termination_status(m) == MOI.OPTIMAL -# end - -# @testset "Uniform partitioning" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "disc_add_partition_method" => "uniform", -# "disc_uniform_rate" => 10, -# "max_iter" => 1, -# "presolve_bt" => false, -# "time_limit" => 100000, -# "log_level" => 100, -# ) -# m = nlp3(solver = test_solver) -# JuMP.optimize!(m) -# @test isapprox(objective_bound(m), 6561.7841; atol = 1e-3) -# end - -# @testset "Algorithm Test with binprod terms" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "minlp_solver" => PAVITO, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# # "bilinear_convexhull" => true, -# # "monomial_convexhull" => true, -# "presolve_bp" => true, -# "presolve_bt" => false, -# "partition_scaling_factor" => 10, -# "log_level" => 100, -# ) -# m = binprod_nlp3(solver = test_solver) -# JuMP.optimize!(m) - -# @test termination_status(m) == MOI.OPTIMAL -# @test isapprox(objective_value(m), 3651.020370626844; atol = 1e-4) -# @test isapprox(objective_bound(m), 3650.786358471944; atol = 1e-4) - -# alpine = JuMP.backend(m).optimizer.model -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4])]][:y_idx] == 19 -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4])]][:id] == 6 -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4])]][:lifted_constr_ref] == -# :(x[19] == x[2] * x[4]) -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[8])]][:y_idx] == 25 -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[8])]][:id] == 12 -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[8])]][:lifted_constr_ref] == -# :(x[25] == x[3] * x[8]) -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[8])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5])]][:y_idx] == 22 -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5])]][:id] == 9 -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5])]][:lifted_constr_ref] == -# :(x[22] == x[3] * x[5]) -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[19])]][:y_idx] == 20 -# @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[19])]][:id] == 7 -# @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[19])]][:lifted_constr_ref] == -# :(x[20] == x[12] * x[19]) -# @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[19])]][:nonlinear_type] == :BINLIN -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[4])]][:y_idx] == 14 -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[4])]][:id] == 1 -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[4])]][:lifted_constr_ref] == -# :(x[14] == x[9] * x[4]) -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[4])]][:nonlinear_type] == :BINLIN -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[6])]][:y_idx] == 17 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[6])]][:id] == 4 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[6])]][:lifted_constr_ref] == -# :(x[17] == x[1] * x[6]) -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[6])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[11]), :(x[5])]][:y_idx] == 16 -# @test alpine.nonconvex_terms[Expr[:(x[11]), :(x[5])]][:id] == 3 -# @test alpine.nonconvex_terms[Expr[:(x[11]), :(x[5])]][:lifted_constr_ref] == -# :(x[16] == x[11] * x[5]) -# @test alpine.nonconvex_terms[Expr[:(x[11]), :(x[5])]][:nonlinear_type] == :BINLIN -# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[11])]][:y_idx] == 30 -# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[11])]][:id] == 17 -# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[11])]][:lifted_constr_ref] == -# :(x[30] == x[10] * x[11]) -# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[11])]][:nonlinear_type] == :BINPROD -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[11])]][:y_idx] == 29 -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[11])]][:id] == 16 -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[11])]][:lifted_constr_ref] == -# :(x[29] == x[9] * x[10] * x[11]) -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[11])]][:nonlinear_type] == -# :BINPROD -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[7])]][:y_idx] == 21 -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[7])]][:id] == 8 -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[7])]][:lifted_constr_ref] == -# :(x[21] == x[2] * x[7]) -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[7])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[13])]][:y_idx] == 32 -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[13])]][:id] == 19 -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[13])]][:lifted_constr_ref] == -# :(x[32] == x[9] * x[13]) -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[13])]][:nonlinear_type] == :BINPROD -# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[6])]][:y_idx] == 15 -# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[6])]][:id] == 2 -# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[6])]][:lifted_constr_ref] == -# :(x[15] == x[10] * x[6]) -# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[6])]][:nonlinear_type] == :BINLIN -# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[12])]][:y_idx] == 33 -# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[12])]][:id] == 20 -# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[12])]][:lifted_constr_ref] == -# :(x[33] == x[10] * x[12]) -# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[12])]][:nonlinear_type] == :BINPROD -# @test alpine.nonconvex_terms[Expr[:(x[27]), :(x[5])]][:y_idx] == 28 -# @test alpine.nonconvex_terms[Expr[:(x[27]), :(x[5])]][:id] == 15 -# @test alpine.nonconvex_terms[Expr[:(x[27]), :(x[5])]][:lifted_constr_ref] == -# :(x[28] == x[27] * x[5]) -# @test alpine.nonconvex_terms[Expr[:(x[27]), :(x[5])]][:nonlinear_type] == :BINLIN -# @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[25])]][:y_idx] == 26 -# @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[25])]][:id] == 13 -# @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[25])]][:lifted_constr_ref] == -# :(x[26] == x[13] * x[25]) -# @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[25])]][:nonlinear_type] == :BINLIN -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[12])]][:y_idx] == 27 -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[12])]][:id] == 14 -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[12])]][:lifted_constr_ref] == -# :(x[27] == x[9] * x[12]) -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[12])]][:nonlinear_type] == :BINPROD -# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[13])]][:y_idx] == 23 -# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[13])]][:id] == 10 -# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[13])]][:lifted_constr_ref] == -# :(x[23] == x[10] * x[13]) -# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[13])]][:nonlinear_type] == :BINPROD -# @test alpine.nonconvex_terms[Expr[:(x[23]), :(x[22])]][:y_idx] == 24 -# @test alpine.nonconvex_terms[Expr[:(x[23]), :(x[22])]][:id] == 11 -# @test alpine.nonconvex_terms[Expr[:(x[23]), :(x[22])]][:lifted_constr_ref] == -# :(x[24] == x[23] * x[22]) -# @test alpine.nonconvex_terms[Expr[:(x[23]), :(x[22])]][:nonlinear_type] == :BINLIN -# @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[13])]][:y_idx] == 31 -# @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[13])]][:id] == 18 -# @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[13])]][:lifted_constr_ref] == -# :(x[31] == x[12] * x[13]) -# @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[13])]][:nonlinear_type] == :BINPROD -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[17])]][:y_idx] == 18 -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[17])]][:id] == 5 -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[17])]][:lifted_constr_ref] == -# :(x[18] == x[9] * x[17]) -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[17])]][:nonlinear_type] == :BINLIN -# @test alpine.bounding_constr_mip[1][:rhs] == 1.0 -# @test alpine.bounding_constr_mip[1][:vars] == Any[:(x[14]), :(x[15])] -# @test alpine.bounding_constr_mip[1][:coefs] == Any[0.0025, 0.0025] -# @test alpine.bounding_constr_mip[1][:sense] == :(<=) -# @test alpine.bounding_constr_mip[1][:cnt] == 2 -# @test alpine.bounding_constr_mip[2][:rhs] == 1.0 -# @test alpine.bounding_constr_mip[2][:vars] == Any[:(x[14]), :(x[5]), :(x[7])] -# @test alpine.bounding_constr_mip[2][:coefs] == Any[-0.0025, 0.0025, 0.0025] -# @test alpine.bounding_constr_mip[2][:sense] == :(<=) -# @test alpine.bounding_constr_mip[2][:cnt] == 3 -# @test alpine.bounding_constr_mip[3][:rhs] == 1.0 -# @test alpine.bounding_constr_mip[3][:vars] == Any[:(x[16]), :(x[8])] -# @test alpine.bounding_constr_mip[3][:coefs] == Any[-0.01, 0.01] -# @test alpine.bounding_constr_mip[3][:sense] == :(<=) -# @test alpine.bounding_constr_mip[3][:cnt] == 2 -# @test alpine.bounding_constr_mip[4][:rhs] == 83333.333 -# @test alpine.bounding_constr_mip[4][:vars] == Any[:(x[1]), :(x[18]), :(x[14])] -# @test alpine.bounding_constr_mip[4][:sense] == :(<=) -# @test alpine.bounding_constr_mip[4][:cnt] == 3 -# @test alpine.bounding_constr_mip[5][:rhs] == 0.0 -# @test alpine.bounding_constr_mip[5][:vars] == -# Any[:(x[20]), :(x[21]), :(x[4]), :(x[5])] -# @test alpine.bounding_constr_mip[5][:coefs] == Any[1.0, -1.0, -1250.0, 1250.0] -# @test alpine.bounding_constr_mip[5][:sense] == :(<=) -# @test alpine.bounding_constr_mip[5][:cnt] == 4 -# @test alpine.bounding_constr_mip[6][:rhs] == -1.25e6 -# @test alpine.bounding_constr_mip[6][:vars] == Any[:(x[24]), :(x[26]), :(x[28])] -# @test alpine.bounding_constr_mip[6][:coefs] == Any[1.0, -1.0, -2500.0] -# @test alpine.bounding_constr_mip[6][:sense] == :(<=) -# @test alpine.bounding_constr_mip[6][:cnt] == 3 -# @test alpine.bounding_constr_mip[7][:rhs] == 0.0 -# @test alpine.bounding_constr_mip[7][:vars] == Any[:(x[29])] -# @test alpine.bounding_constr_mip[7][:coefs] == Any[1.0] -# @test alpine.bounding_constr_mip[7][:sense] == :(<=) -# @test alpine.bounding_constr_mip[7][:cnt] == 1 -# @test alpine.bounding_constr_mip[8][:rhs] == 0.0 -# @test alpine.bounding_constr_mip[8][:vars] == Any[:(x[30]), :(x[31])] -# @test alpine.bounding_constr_mip[8][:coefs] == Any[1.0, -1.0] -# @test alpine.bounding_constr_mip[8][:sense] == :(>=) -# @test alpine.bounding_constr_mip[8][:cnt] == 2 -# @test alpine.bounding_constr_mip[9][:rhs] == 0.0 -# @test alpine.bounding_constr_mip[9][:vars] == Any[:(x[32]), :(x[33])] -# @test alpine.bounding_constr_mip[9][:coefs] == Any[1.0, -1.0] -# @test alpine.bounding_constr_mip[9][:sense] == :(<=) -# @test alpine.bounding_constr_mip[9][:cnt] == 2 -# end - -# @testset "TESTS for closing the optimality gap in OBBT" begin -# test_solver = JuMP.optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => PAVITO, -# "presolve_bt" => true, -# "presolve_bt_max_iter" => 2, -# "log_level" => 1, -# ) -# m = JuMP.Model(test_solver) - -# # From issue #108 -# @variable(m, -2 <= x[1:2] <= 2) -# @variable(m, -10 <= y[1:3] <= 10) -# @NLobjective(m, Min, y[2] + y[1] * y[2] * y[3]) -# @constraint(m, y[1] == x[1]) -# @constraint(m, y[2] == x[2]) -# @NLconstraint(m, y[3] == x[2]^2) - -# JuMP.optimize!(m) -# alp = JuMP.backend(m).optimizer.model -# @test isapprox(JuMP.objective_value(m), -18, atol = 1E-6) -# @test isapprox(value.(m[:x]), [2, -2], atol = 1E-6) -# @test alp.logs[:n_iter] == 0 -# @test MOI.get(m, Alpine.NumberOfIterations()) == 0 -# end +@testset " Validation Test || AMP-TMC || basic solve || examples/nlp3.jl (2 iterations)" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + # "bilinear_convexhull" => false, + # "monomial_convexhull" => false, + "presolve_bp" => true, + "max_iter" => 2, + "presolve_bt_width_tol" => 1e-3, + "presolve_bt" => false, + "partition_scaling_factor" => 10, + "disc_var_pick" => 0, + ) + m = nlp3(solver = test_solver) + JuMP.optimize!(m) + + @test termination_status(m) == MOI.OTHER_LIMIT + + @test isapprox(objective_value(m), 7049.247897696512; atol = 1e-4) + @test MOI.get(m, Alpine.NumberOfIterations()) == 2 +end + +@testset " Validation Test || AMP-TMC || minimum-vertex solving || examples/nlp3.jl (3 iterations)" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + # "bilinear_convexhull" => false, + # "monomial_convexhull" => false, + "presolve_bp" => true, + "disc_var_pick" => 1, + "max_iter" => 2, + "partition_scaling_factor" => 10, + "presolve_bt_width_tol" => 1e-3, + "presolve_bt" => false, + ) + m = nlp3(solver = test_solver) + JuMP.optimize!(m) + + @test termination_status(m) == MOI.OTHER_LIMIT + @test isapprox(objective_value(m), 7049.247897696512; atol = 1e-4) + @test MOI.get(m, Alpine.NumberOfIterations()) == 2 +end + +@testset " Validation Test || BT-AMP-TMC || basic solve || examples/nlp3.jl" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + # "bilinear_convexhull" => false, + "log_level" => 100, + "max_iter" => 2, + "partition_scaling_factor" => 10, + "presolve_bt_width_tol" => 1e-3, + "presolve_bt_bound_tol" => 1e-1, + "presolve_bt" => true, + "presolve_bt_algo" => 1, + "presolve_bp" => true, + "presolve_bt_max_iter" => 2, + "presolve_track_time" => true, + "disc_var_pick" => max_cover_var_picker, + ) + m = nlp3(solver = test_solver) + + JuMP.optimize!(m) + + @test termination_status(m) == MOI.OTHER_LIMIT + @test MOI.get(m, Alpine.NumberOfIterations()) == 2 + @test MOI.get(m, Alpine.NumberOfPresolveIterations()) == 2 + + vars = all_variables(m) + LB = [100, 1000, 1000, 10, 150.2, 10, 35.4, 168] + UB = [4573.6, 5547.8, 5913.3, 332.4, 551, 390, 571.1, 638.7] + @test isapprox(MOI.get.(m, Alpine.TightenedLowerBound(), vars), LB, atol = 1E-6) + @test isapprox(MOI.get.(m, Alpine.TightenedUpperBound(), vars), UB, atol = 1E-6) +end + +# FIXME Pavito terminates with `NUMERICAL_ERROR` on Julia v1.0: +@testset " Validation Test || PBT-AMP-TMC || basic solve || examples/nlp3.jl" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + # "bilinear_convexhull" => false, + "log_level" => 100, + "max_iter" => 2, + "partition_scaling_factor" => 10, + "presolve_bt" => true, + "presolve_bt_width_tol" => 1e-3, + "presolve_bt_bound_tol" => 1e-1, + "presolve_bt_algo" => 2, + "presolve_bp" => true, + "presolve_bt_max_iter" => 2, + "disc_var_pick" => max_cover_var_picker, + ) + + m = nlp3(solver = test_solver) + JuMP.optimize!(m) + @test termination_status(m) == MOI.OTHER_LIMIT + @test MOI.get(m, Alpine.NumberOfIterations()) == 2 +end + +@testset " Validation Test || AMP-CONV || basic solve || examples/nlp1.jl" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => PAVITO, + # "bilinear_convexhull" => true, + # "monomial_convexhull" => true, + "presolve_bt" => false, + "presolve_bp" => true, + "partition_scaling_factor" => 12, + "max_iter" => 1, + ) + m = nlp1(solver = test_solver) + JuMP.optimize!(m) + + @test termination_status(m) == MOI.OTHER_LIMIT + @test isapprox(objective_value(m), 58.38367169858795; atol = 1e-5) + @test MOI.get(m, Alpine.NumberOfIterations()) == 1 +end + +@testset " Validation Test || AMP-CONV || basic solve || examples/nlp3.jl" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + # "bilinear_convexhull" => true, + # "monomial_convexhull" => true, + "presolve_bt" => false, + "presolve_bp" => false, + "partition_scaling_factor" => 14, + "max_iter" => 4, + "log_level" => 100, + ) + m = nlp3(solver = test_solver) + JuMP.optimize!(m) + + @test termination_status(m) == MOI.OTHER_LIMIT + @test isapprox(objective_value(m), 7049.24789; atol = 1e-4) + @test isapprox(objective_bound(m), 6839.487709940, atol = 1E-4) + @test MOI.get(m, Alpine.NumberOfIterations()) == 4 +end + +@testset " Validation Test || AMP || basic solve || examples/circle.jl" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => PAVITO, + "disc_abs_width_tol" => 1e-3, + "partition_scaling_factor" => 8, + "max_iter" => 6, + "presolve_bt" => false, + "log_level" => 100, + ) + + m = circle(solver = test_solver) + # This is fixed in Alpine - TODO (odow): cycling detected in Pavito when disc_abs_width_tol = 1E-2 + JuMP.optimize!(m) + @test isapprox(objective_value(m), 1.4142135534556992; atol = 1e-3) +end + +@testset " Validation Test || AMP || basic solve || examples/circle_MINLPLib.jl" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => PAVITO, + "presolve_bt" => false, + "partition_scaling_factor" => 15, + "max_iter" => 2, + ) + + m = circle_MINLPLib(solver = test_solver) + + JuMP.optimize!(m) + @test termination_status(m) == MOI.OPTIMAL + @test isapprox(objective_value(m), 4.45670663096; atol = 1E-6) +end + +@testset " Validation Test || AMP-CONV-FACET || basic solve || examples/nlp3.jl" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + # "bilinear_convexhull" => true, + # "monomial_convexhull" => true, + "presolve_bt" => false, + "presolve_bp" => true, + "convhull_formulation" => "facet", + "max_iter" => 3, + "log_level" => 100, + ) + m = nlp3(solver = test_solver) + JuMP.optimize!(m) + + @test isapprox(objective_value(m), 7049.247897696188; atol = 1e-4) + @test isapprox(objective_bound(m), 6654.6983279983; atol = 1e-4) + @test MOI.get(m, Alpine.NumberOfIterations()) == 3 +end + +@testset " Validation Test || AMP || multi4N || N = 2 || exprmode=1:11" begin + n_instances = 5 + objValVec = 2.0 * ones(n_instances) + + for i in 1:n_instances + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "disc_abs_width_tol" => 1e-2, + "max_iter" => 4, + "partition_scaling_factor" => 4, + "presolve_bp" => false, + "presolve_bt" => false, + "log_level" => 1, + ) + + m = multi4N(solver = test_solver, N = 2, exprmode = i) + JuMP.optimize!(m) + + @test termination_status(m) == MOI.OTHER_LIMIT + @test isapprox(objective_value(m), objValVec[i]; atol = 1e-3) + end +end + +@testset " Validation Test || AMP || multi2 || exprmode=1:11" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "disc_abs_width_tol" => 1e-2, + "max_iter" => 5, + "presolve_bt" => false, + "log_level" => 1, + ) + + m = multi2(solver = test_solver) + JuMP.optimize!(m) + @test termination_status(m) == MOI.OPTIMAL + @test isapprox(objective_value(m), 0.92906489; atol = 1e-3) +end + +@testset " Validation Test || AMP || multi3N || N = 2 || exprmode=1:11" begin + n_instances = 3 + objValVec = 2.0 * ones(n_instances) + + objBoundVec = Any[2.97186, 3.85492, 4.23375] + + for i in 1:n_instances + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "disc_abs_width_tol" => 1e-2, + "max_iter" => 4, + "partition_scaling_factor" => 4, + "presolve_bp" => false, + "presolve_bt" => false, + "log_level" => 1, + ) + + m = multi3N(solver = test_solver, N = 2, exprmode = i) + JuMP.optimize!(m) + + @test termination_status(m) == MOI.OTHER_LIMIT + @test isapprox(objective_value(m), objValVec[i]; atol = 1e-3) + @test objective_bound(m) <= objBoundVec[i] + 1e-3 + end +end + +@testset " Validation Test || AMP || multiKND || K = 3, N = 3, D = 0 " begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "disc_abs_width_tol" => 1e-2, + "max_iter" => 3, + "partition_scaling_factor" => 4, + "presolve_bp" => false, + "presolve_bt" => false, + "log_level" => 1, + ) + + m = multiKND(solver = test_solver, randomub = 50, K = 3, N = 3, D = 0) + JuMP.optimize!(m) + + @test termination_status(m) == MOI.OTHER_LIMIT + @test isapprox(objective_value(m), 3.0000000824779454; atol = 1e-3) + @test isapprox(objective_bound(m), 12.054604248046875; atol = 1e-3) +end + +@testset " Validation Test || AMP-CONV-FACET || basic solve || examples/nlp3.jl" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + # "bilinear_convexhull" => true, + # "monomial_convexhull" => true, + "presolve_bt" => false, + "presolve_bp" => false, + "max_iter" => 3, + "partition_scaling_factor" => 4, + "convhull_formulation" => "facet", + "log_level" => 100, + ) + m = nlp3(solver = test_solver) + JuMP.optimize!(m) + + @test termination_status(m) == MOI.OTHER_LIMIT + @test isapprox(objective_value(m), 7049.247897696188; atol = 1e-4) + @test isapprox(objective_bound(m), 5871.530692199214; atol = 1E-5) + @test MOI.get(m, Alpine.NumberOfIterations()) == 3 +end + +@testset " Validation Test || AMP || PARTITION-SCALING-FACTOR || examples/nlp3.jl " begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "disc_abs_width_tol" => 1e-2, + "partition_scaling_factor_branch" => false, + "partition_scaling_factor" => 18, + "max_iter" => 1, + "presolve_bp" => true, + "presolve_bt" => false, + "log_level" => 100, + ) + + m = nlp3(solver = test_solver) + JuMP.optimize!(m) + + @test MOI.get(m, Alpine.NumberOfIterations()) == 1 + @test MOI.get(m, MOI.RawOptimizerAttribute("partition_scaling_factor")) == 18 +end + +@testset " Validation Test || AMP || PARTITION-SCALING-FACTOR-BRANCH || examples/nlp3.jl " begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "disc_abs_width_tol" => 1e-2, + "partition_scaling_factor_branch" => true, + "max_iter" => 1, + "presolve_bp" => true, + "presolve_bt" => false, + "log_level" => 100, + ) + + m = nlp3(solver = test_solver) + JuMP.optimize!(m) + + @test MOI.get(m, Alpine.NumberOfIterations()) == 1 + @test MOI.get(m, MOI.RawOptimizerAttribute("partition_scaling_factor")) == 14 +end + +@testset " Validation Test || AMP || PARTITION-SCALING-FACTOR-BRANCH || examples/castro2m2.jl " begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "disc_abs_width_tol" => 1e-2, + "partition_scaling_factor_branch" => true, + "max_iter" => 1, + "presolve_bp" => true, + "presolve_bt" => false, + "log_level" => 100, + ) + + m = castro2m2(solver = test_solver) + JuMP.optimize!(m) + + @test MOI.get(m, Alpine.NumberOfIterations()) == 1 + @test MOI.get(m, MOI.RawOptimizerAttribute("partition_scaling_factor")) == 8 +end + +@testset " Validation Test || AMP || PARTITION-SCALING-FACTOR-BRANCH || examples/multi3N.jl exprmode=2" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "disc_abs_width_tol" => 1e-2, + "partition_scaling_factor_branch" => true, + "max_iter" => 1, + "presolve_bp" => true, + "presolve_bt" => false, + "log_level" => 100, + ) + + m = multi3N(solver = test_solver, N = 3, exprmode = 1) + JuMP.optimize!(m) + + @test MOI.get(m, Alpine.NumberOfIterations()) == 1 + @test MOI.get(m, MOI.RawOptimizerAttribute("partition_scaling_factor")) == 16 +end + +@testset " Validation Test || AMP || PARTITION-SCALING-FACTOR-BRANCH || examples/multi3N.jl exprmode=2" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "disc_abs_width_tol" => 1e-2, + "partition_scaling_factor_branch" => true, + "max_iter" => 1, + "presolve_bp" => false, + "presolve_bt" => false, + "log_level" => 100, + ) + + m = multi3N(solver = test_solver, N = 3, exprmode = 1) + JuMP.optimize!(m) + + @test MOI.get(m, Alpine.NumberOfIterations()) == 1 + @test MOI.get(m, MOI.RawOptimizerAttribute("partition_scaling_factor")) == 20 +end + +@testset " Validation Test || AMP || PARTITION-SCALING-FACTOR-BRANCH || examples/multi4N.jl exprmode=1" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "disc_abs_width_tol" => 1e-2, + "partition_scaling_factor_branch" => true, + "max_iter" => 1, + "presolve_bp" => true, + "presolve_bt" => false, + "log_level" => 100, + ) + + m = multi4N(solver = test_solver, N = 2, exprmode = 1) + JuMP.optimize!(m) + + @test MOI.get(m, Alpine.NumberOfIterations()) == 1 + @test MOI.get(m, MOI.RawOptimizerAttribute("partition_scaling_factor")) == 12 +end + +@testset " Validation Test || AMP || PARTITION-SCALING-FACTOR-BRANCH || examples/multi4N.jl exprmode=2" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "disc_abs_width_tol" => 1e-2, + "partition_scaling_factor_branch" => true, + "max_iter" => 1, + "presolve_bp" => false, + "presolve_bt" => false, + "log_level" => 100, + ) + + m = multi4N(solver = test_solver, N = 2, exprmode = 1) + JuMP.optimize!(m) + + @test MOI.get(m, Alpine.NumberOfIterations()) == 1 + @test MOI.get(m, MOI.RawOptimizerAttribute("partition_scaling_factor")) == 20 +end + +@testset " Validation Test || AMP || PARTITION-SCALING-FACTOR-BRANCH || examples/multi4N.jl exprmode=2" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "disc_abs_width_tol" => 1e-2, + "partition_scaling_factor_branch" => true, + "max_iter" => 1, + "presolve_bp" => true, + "presolve_bt" => false, + "log_level" => 100, + ) + + m = multi4N(solver = test_solver, N = 2, exprmode = 2) + JuMP.optimize!(m) + + @test MOI.get(m, Alpine.NumberOfIterations()) == 1 + @test MOI.get(m, MOI.RawOptimizerAttribute("partition_scaling_factor")) == 20 +end + +@testset "Operator :: bmpl && binlin && binprod solve test I" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "minlp_solver" => PAVITO, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "presolve_bt" => false, + "log_level" => 100, + ) + + m = bpml_lnl(solver = test_solver) + JuMP.optimize!(m) + @test isapprox(objective_value(m), 0.3; atol = 1e-6) + alpine = JuMP.backend(m).optimizer.model + @test haskey(alpine.nonconvex_terms, Expr[:(x[1]), :(x[6])]) + @test haskey(alpine.nonconvex_terms, Expr[:(x[2]), :(x[7])]) + @test haskey(alpine.nonconvex_terms, Expr[:(x[3]), :(x[8])]) + @test haskey(alpine.nonconvex_terms, Expr[:(x[4]), :(x[9])]) + @test haskey(alpine.nonconvex_terms, Expr[:(x[5]), :(x[10])]) + + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[6])]][:nonlinear_type] == :BINLIN + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[7])]][:nonlinear_type] == :BINLIN + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[8])]][:nonlinear_type] == :BINLIN + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[9])]][:nonlinear_type] == :BINLIN + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[10])]][:nonlinear_type] == :BINLIN +end + +@testset "Operator :: bmpl && binlin && binprod solve test II" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "minlp_solver" => JUNIPER, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "presolve_bt" => false, + "partition_scaling_factor" => 4, + "log_level" => 100, + ) + + m = bpml_binl(solver = test_solver) + + # FIXME: Deactivating this until Juniper v0.9.0's numerical issues are fixed. + # JuMP.optimize!(m) + # @test isapprox(JuMP.objective_value(m), 22812.76415926; atol=1e-6) + # alpine = JuMP.backend(m).optimizer.model + + alpine = _build(m) + @test haskey(alpine.nonconvex_terms, Expr[:(x[6]), :(x[7])]) + @test haskey(alpine.nonconvex_terms, Expr[:(x[7]), :(x[8])]) + @test haskey(alpine.nonconvex_terms, Expr[:(x[8]), :(x[9])]) + @test haskey(alpine.nonconvex_terms, Expr[:(x[9]), :(x[10])]) + @test haskey(alpine.nonconvex_terms, Expr[:(x[10]), :(x[6])]) + @test haskey(alpine.nonconvex_terms, Expr[:(x[1]), :(x[11])]) + @test haskey(alpine.nonconvex_terms, Expr[:(x[2]), :(x[13])]) + @test haskey(alpine.nonconvex_terms, Expr[:(x[3]), :(x[15])]) + @test haskey(alpine.nonconvex_terms, Expr[:(x[4]), :(x[17])]) + @test haskey(alpine.nonconvex_terms, Expr[:(x[5]), :(x[19])]) + + @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[7])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[7]), :(x[8])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[8]), :(x[9])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[6])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[11])]][:nonlinear_type] == :BINLIN + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[13])]][:nonlinear_type] == :BINLIN + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[15])]][:nonlinear_type] == :BINLIN + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[17])]][:nonlinear_type] == :BINLIN + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[19])]][:nonlinear_type] == :BINLIN +end + +@testset "Embedding Test || AMP-CONV || basic solve || examples/nlp1.jl" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => PAVITO, + # "bilinear_convexhull" => true, + # "monomial_convexhull" => true, + "presolve_bt" => false, + "presolve_bp" => true, + "convhull_ebd" => true, + "max_iter" => 1, + "partition_scaling_factor" => 4, + "log_level" => 100, + ) + + m = nlp1(solver = test_solver) + JuMP.optimize!(m) + alp = JuMP.backend(m).optimizer.model + + @test termination_status(m) == MOI.OTHER_LIMIT + @test isapprox(objective_value(m), 58.38367169858795; atol = 1e-4) + @test isapprox(alp.best_bound, 52.9702, atol = 1E-4) + @test MOI.get(m, Alpine.NumberOfIterations()) == 1 +end + +@testset "Embedding IBS Test || AMP-CONV || basic solve || examples/nlp1.jl" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => PAVITO, + # "bilinear_convexhull" => true, + # "monomial_convexhull" => true, + "presolve_bt" => false, + "presolve_bp" => true, + "convhull_ebd" => true, + "convhull_ebd_ibs" => true, + "partition_scaling_factor" => 8, + "max_iter" => 1, + "log_level" => 100, + ) + m = nlp1(solver = test_solver) + JuMP.optimize!(m) + alp = JuMP.backend(m).optimizer.model + + @test termination_status(m) == MOI.OTHER_LIMIT + @test isapprox(objective_value(m), 58.38367169858795; atol = 1e-5) + @test isapprox(alp.best_bound, 57.012, atol = 1E-4) + + @test MOI.get(m, Alpine.NumberOfIterations()) == 1 +end + +@testset "Embedding IBS Test || AMP-CONV || basic solve || examples/nlp3.jl" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + # "bilinear_convexhull" => true, + # "monomial_convexhull" => true, + "presolve_bt" => false, + "presolve_bp" => false, + "convhull_ebd" => true, + "convhull_ebd_ibs" => true, + "max_iter" => 3, + ) + m = nlp3(solver = test_solver) + JuMP.optimize!(m) + alp = JuMP.backend(m).optimizer.model + + @test termination_status(m) == MOI.OTHER_LIMIT + @test isapprox(objective_value(m), 7049.247897696188; atol = 1e-5) + @test MOI.get(m, Alpine.NumberOfIterations()) == 3 + @test isapprox(alp.best_bound, 6893.2067, atol = 1E-4) +end + +@testset "Embedding IBS Test || AMP || special problem || ... " begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => PAVITO, + "disc_abs_width_tol" => 1e-3, + "partition_scaling_factor" => 8, + "max_iter" => 6, + "presolve_bt" => false, + "presolve_bp" => true, + "presolve_bt_algo" => 1, + "presolve_bt_bound_tol" => 1e-1, + "convhull_ebd" => true, + "convhull_ebd_ibs" => true, + "log_level" => 100, + ) + + m = circle(solver = test_solver) + # This is fixed in Alpine - TODO(odow): mixed-integer cycling detected, terminating Pavito + JuMP.optimize!(m) + @test isapprox(objective_value(m), 1.41421355; atol = 1e-3) +end + +@testset "Embedding LINK Test || AMP-CONV || basic solve || examples/nlp3.jl" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + # "bilinear_convexhull" => true, + # "monomial_convexhull" => true, + "presolve_bt" => false, + "presolve_bp" => false, + "convhull_ebd" => true, + "convhull_ebd_link" => true, + "partition_scaling_factor" => 10, + "max_iter" => 3, + "log_level" => 100, + ) + m = nlp3(solver = test_solver) + JuMP.optimize!(m) + + @test termination_status(m) == MOI.OTHER_LIMIT + @test isapprox(objective_value(m), 7049.247897696188; atol = 1e-4) + @test MOI.get(m, Alpine.NumberOfIterations()) == 3 +end + +@testset "Algorithm Logic Test || castro4m2 || 1 iteration || Error case" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "max_iter" => 1, + "presolve_bt" => false, + "partition_scaling_factor" => 10, + "log_level" => 100, + ) + + m = castro4m2(solver = test_solver) + JuMP.optimize!(m) + @test termination_status(m) == MOI.OTHER_LIMIT +end + +@testset " Algorithm Logic Test || blend029_gl || 3 iterations || Infeasible Case" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "minlp_solver" => PAVITO, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "presolve_bp" => true, + "disc_var_pick" => 1, + "log_level" => 100, + "max_iter" => 3, + "partition_scaling_factor" => 10, + "presolve_bt_width_tol" => 1e-3, + "presolve_bt" => false, + ) + m = blend029_gl(solver = test_solver) + JuMP.optimize!(m) + + @test termination_status(m) == MOI.OTHER_LIMIT + @test MOI.get(m, Alpine.NumberOfIterations()) == 3 + @test objective_bound(m) <= 14.0074 +end + +@testset "Convex Model Solve" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => PAVITO, + "max_iter" => 1, + "presolve_bt" => false, + "log_level" => 100, + ) + m = convex_solve(solver = test_solver) + JuMP.optimize!(m) + @test termination_status(m) == MOI.OPTIMAL +end + +@testset "Uniform partitioning" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "disc_add_partition_method" => "uniform", + "disc_uniform_rate" => 10, + "max_iter" => 1, + "presolve_bt" => false, + "time_limit" => 100000, + "log_level" => 100, + ) + m = nlp3(solver = test_solver) + JuMP.optimize!(m) + @test isapprox(objective_bound(m), 6561.7841; atol = 1e-3) +end + +@testset "Algorithm Test with binprod terms" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "minlp_solver" => PAVITO, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + # "bilinear_convexhull" => true, + # "monomial_convexhull" => true, + "presolve_bp" => true, + "presolve_bt" => false, + "partition_scaling_factor" => 10, + "log_level" => 100, + ) + m = binprod_nlp3(solver = test_solver) + JuMP.optimize!(m) + + @test termination_status(m) == MOI.OPTIMAL + @test isapprox(objective_value(m), 3651.020370626844; atol = 1e-4) + @test isapprox(objective_bound(m), 3650.786358471944; atol = 1e-4) + + alpine = JuMP.backend(m).optimizer.model + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4])]][:y_idx] == 19 + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4])]][:id] == 6 + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4])]][:lifted_constr_ref] == + :(x[19] == x[2] * x[4]) + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[8])]][:y_idx] == 25 + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[8])]][:id] == 12 + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[8])]][:lifted_constr_ref] == + :(x[25] == x[3] * x[8]) + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[8])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5])]][:y_idx] == 22 + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5])]][:id] == 9 + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5])]][:lifted_constr_ref] == + :(x[22] == x[3] * x[5]) + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[19])]][:y_idx] == 20 + @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[19])]][:id] == 7 + @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[19])]][:lifted_constr_ref] == + :(x[20] == x[12] * x[19]) + @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[19])]][:nonlinear_type] == :BINLIN + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[4])]][:y_idx] == 14 + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[4])]][:id] == 1 + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[4])]][:lifted_constr_ref] == + :(x[14] == x[9] * x[4]) + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[4])]][:nonlinear_type] == :BINLIN + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[6])]][:y_idx] == 17 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[6])]][:id] == 4 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[6])]][:lifted_constr_ref] == + :(x[17] == x[1] * x[6]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[6])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[11]), :(x[5])]][:y_idx] == 16 + @test alpine.nonconvex_terms[Expr[:(x[11]), :(x[5])]][:id] == 3 + @test alpine.nonconvex_terms[Expr[:(x[11]), :(x[5])]][:lifted_constr_ref] == + :(x[16] == x[11] * x[5]) + @test alpine.nonconvex_terms[Expr[:(x[11]), :(x[5])]][:nonlinear_type] == :BINLIN + @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[11])]][:y_idx] == 30 + @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[11])]][:id] == 17 + @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[11])]][:lifted_constr_ref] == + :(x[30] == x[10] * x[11]) + @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[11])]][:nonlinear_type] == :BINPROD + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[11])]][:y_idx] == 29 + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[11])]][:id] == 16 + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[11])]][:lifted_constr_ref] == + :(x[29] == x[9] * x[10] * x[11]) + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[11])]][:nonlinear_type] == + :BINPROD + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[7])]][:y_idx] == 21 + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[7])]][:id] == 8 + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[7])]][:lifted_constr_ref] == + :(x[21] == x[2] * x[7]) + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[7])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[13])]][:y_idx] == 32 + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[13])]][:id] == 19 + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[13])]][:lifted_constr_ref] == + :(x[32] == x[9] * x[13]) + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[13])]][:nonlinear_type] == :BINPROD + @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[6])]][:y_idx] == 15 + @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[6])]][:id] == 2 + @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[6])]][:lifted_constr_ref] == + :(x[15] == x[10] * x[6]) + @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[6])]][:nonlinear_type] == :BINLIN + @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[12])]][:y_idx] == 33 + @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[12])]][:id] == 20 + @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[12])]][:lifted_constr_ref] == + :(x[33] == x[10] * x[12]) + @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[12])]][:nonlinear_type] == :BINPROD + @test alpine.nonconvex_terms[Expr[:(x[27]), :(x[5])]][:y_idx] == 28 + @test alpine.nonconvex_terms[Expr[:(x[27]), :(x[5])]][:id] == 15 + @test alpine.nonconvex_terms[Expr[:(x[27]), :(x[5])]][:lifted_constr_ref] == + :(x[28] == x[27] * x[5]) + @test alpine.nonconvex_terms[Expr[:(x[27]), :(x[5])]][:nonlinear_type] == :BINLIN + @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[25])]][:y_idx] == 26 + @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[25])]][:id] == 13 + @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[25])]][:lifted_constr_ref] == + :(x[26] == x[13] * x[25]) + @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[25])]][:nonlinear_type] == :BINLIN + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[12])]][:y_idx] == 27 + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[12])]][:id] == 14 + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[12])]][:lifted_constr_ref] == + :(x[27] == x[9] * x[12]) + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[12])]][:nonlinear_type] == :BINPROD + @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[13])]][:y_idx] == 23 + @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[13])]][:id] == 10 + @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[13])]][:lifted_constr_ref] == + :(x[23] == x[10] * x[13]) + @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[13])]][:nonlinear_type] == :BINPROD + @test alpine.nonconvex_terms[Expr[:(x[23]), :(x[22])]][:y_idx] == 24 + @test alpine.nonconvex_terms[Expr[:(x[23]), :(x[22])]][:id] == 11 + @test alpine.nonconvex_terms[Expr[:(x[23]), :(x[22])]][:lifted_constr_ref] == + :(x[24] == x[23] * x[22]) + @test alpine.nonconvex_terms[Expr[:(x[23]), :(x[22])]][:nonlinear_type] == :BINLIN + @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[13])]][:y_idx] == 31 + @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[13])]][:id] == 18 + @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[13])]][:lifted_constr_ref] == + :(x[31] == x[12] * x[13]) + @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[13])]][:nonlinear_type] == :BINPROD + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[17])]][:y_idx] == 18 + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[17])]][:id] == 5 + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[17])]][:lifted_constr_ref] == + :(x[18] == x[9] * x[17]) + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[17])]][:nonlinear_type] == :BINLIN + @test alpine.bounding_constr_mip[1][:rhs] == 1.0 + @test alpine.bounding_constr_mip[1][:vars] == Any[:(x[14]), :(x[15])] + @test alpine.bounding_constr_mip[1][:coefs] == Any[0.0025, 0.0025] + @test alpine.bounding_constr_mip[1][:sense] == :(<=) + @test alpine.bounding_constr_mip[1][:cnt] == 2 + @test alpine.bounding_constr_mip[2][:rhs] == 1.0 + @test alpine.bounding_constr_mip[2][:vars] == Any[:(x[14]), :(x[5]), :(x[7])] + @test alpine.bounding_constr_mip[2][:coefs] == Any[-0.0025, 0.0025, 0.0025] + @test alpine.bounding_constr_mip[2][:sense] == :(<=) + @test alpine.bounding_constr_mip[2][:cnt] == 3 + @test alpine.bounding_constr_mip[3][:rhs] == 1.0 + @test alpine.bounding_constr_mip[3][:vars] == Any[:(x[16]), :(x[8])] + @test alpine.bounding_constr_mip[3][:coefs] == Any[-0.01, 0.01] + @test alpine.bounding_constr_mip[3][:sense] == :(<=) + @test alpine.bounding_constr_mip[3][:cnt] == 2 + @test alpine.bounding_constr_mip[4][:rhs] == 83333.333 + @test alpine.bounding_constr_mip[4][:vars] == Any[:(x[1]), :(x[18]), :(x[14])] + @test alpine.bounding_constr_mip[4][:sense] == :(<=) + @test alpine.bounding_constr_mip[4][:cnt] == 3 + @test alpine.bounding_constr_mip[5][:rhs] == 0.0 + @test alpine.bounding_constr_mip[5][:vars] == + Any[:(x[20]), :(x[21]), :(x[4]), :(x[5])] + @test alpine.bounding_constr_mip[5][:coefs] == Any[1.0, -1.0, -1250.0, 1250.0] + @test alpine.bounding_constr_mip[5][:sense] == :(<=) + @test alpine.bounding_constr_mip[5][:cnt] == 4 + @test alpine.bounding_constr_mip[6][:rhs] == -1.25e6 + @test alpine.bounding_constr_mip[6][:vars] == Any[:(x[24]), :(x[26]), :(x[28])] + @test alpine.bounding_constr_mip[6][:coefs] == Any[1.0, -1.0, -2500.0] + @test alpine.bounding_constr_mip[6][:sense] == :(<=) + @test alpine.bounding_constr_mip[6][:cnt] == 3 + @test alpine.bounding_constr_mip[7][:rhs] == 0.0 + @test alpine.bounding_constr_mip[7][:vars] == Any[:(x[29])] + @test alpine.bounding_constr_mip[7][:coefs] == Any[1.0] + @test alpine.bounding_constr_mip[7][:sense] == :(<=) + @test alpine.bounding_constr_mip[7][:cnt] == 1 + @test alpine.bounding_constr_mip[8][:rhs] == 0.0 + @test alpine.bounding_constr_mip[8][:vars] == Any[:(x[30]), :(x[31])] + @test alpine.bounding_constr_mip[8][:coefs] == Any[1.0, -1.0] + @test alpine.bounding_constr_mip[8][:sense] == :(>=) + @test alpine.bounding_constr_mip[8][:cnt] == 2 + @test alpine.bounding_constr_mip[9][:rhs] == 0.0 + @test alpine.bounding_constr_mip[9][:vars] == Any[:(x[32]), :(x[33])] + @test alpine.bounding_constr_mip[9][:coefs] == Any[1.0, -1.0] + @test alpine.bounding_constr_mip[9][:sense] == :(<=) + @test alpine.bounding_constr_mip[9][:cnt] == 2 +end + +@testset "TESTS for closing the optimality gap in OBBT" begin + test_solver = JuMP.optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => PAVITO, + "presolve_bt" => true, + "presolve_bt_max_iter" => 2, + "log_level" => 1, + ) + m = JuMP.Model(test_solver) + + # From issue #108 + @variable(m, -2 <= x[1:2] <= 2) + @variable(m, -10 <= y[1:3] <= 10) + @NLobjective(m, Min, y[2] + y[1] * y[2] * y[3]) + @constraint(m, y[1] == x[1]) + @constraint(m, y[2] == x[2]) + @NLconstraint(m, y[3] == x[2]^2) + + JuMP.optimize!(m) + alp = JuMP.backend(m).optimizer.model + @test isapprox(JuMP.objective_value(m), -18, atol = 1E-6) + @test isapprox(value.(m[:x]), [2, -2], atol = 1E-6) + @test alp.logs[:n_iter] == 0 + @test MOI.get(m, Alpine.NumberOfIterations()) == 0 +end @testset "Linking constraints for multilinear terms" begin diff --git a/test/test_expression.jl b/test/test_expression.jl index 7ece0cd4..3d419a98 100644 --- a/test/test_expression.jl +++ b/test/test_expression.jl @@ -1,3643 +1,3643 @@ -# @testset "Expression Parsing || bilinear || Affine || exprs.jl" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "log_level" => 100, -# ) - -# m = exprstest(solver = test_solver) - -# alpine = _build(m) - -# ex = alpine.bounding_constr_expr_mip[1] -# affdict = Alpine.expr_linear_to_affine(ex) -# @test affdict[:coefs] == [-1.0] -# @test affdict[:coefs] == alpine.bounding_constr_mip[1][:coefs] -# @test affdict[:vars] == [:(x[1])] -# @test affdict[:vars] == alpine.bounding_constr_mip[1][:vars] -# @test isapprox(affdict[:rhs], 109.0; atol = 1e-3) -# @test affdict[:rhs] == alpine.bounding_constr_mip[1][:rhs] -# @test affdict[:sense] == :(<=) -# @test affdict[:sense] == alpine.bounding_constr_mip[1][:sense] - -# ex = alpine.bounding_constr_expr_mip[2] -# affdict = Alpine.expr_linear_to_affine(ex) -# @test affdict[:coefs] == [3.0, 3.0, 3.0, 3.0] -# @test affdict[:coefs] == alpine.bounding_constr_mip[2][:coefs] -# @test affdict[:vars] == [:(x[8]), :(x[9]), :(x[10]), :(x[11])] -# @test affdict[:vars] == alpine.bounding_constr_mip[2][:vars] -# @test isapprox(affdict[:rhs], 111.0; atol = 1e-3) -# @test affdict[:rhs] == alpine.bounding_constr_mip[2][:rhs] -# @test affdict[:sense] == :(>=) -# @test affdict[:sense] == alpine.bounding_constr_mip[2][:sense] - -# ex = alpine.bounding_constr_expr_mip[3] -# affdict = Alpine.expr_linear_to_affine(ex) -# @test affdict[:coefs] == [-1.0, 20.0] -# @test affdict[:coefs] == alpine.bounding_constr_mip[3][:coefs] -# @test affdict[:vars] == [:(x[12]), :(x[13])] -# @test affdict[:vars] == alpine.bounding_constr_mip[3][:vars] -# @test isapprox(affdict[:rhs], 222.0; atol = 1e-3) -# @test affdict[:rhs] == alpine.bounding_constr_mip[3][:rhs] -# @test affdict[:sense] == :(>=) -# @test affdict[:sense] == alpine.bounding_constr_mip[3][:sense] - -# # 1.0 * x[12] - 115.0 >= 0.0 -# ex = alpine.bounding_constr_expr_mip[4] -# affdict = Alpine.expr_linear_to_affine(ex) -# @test affdict[:coefs] == [-1.0] -# @test affdict[:coefs] == alpine.bounding_constr_mip[4][:coefs] -# @test affdict[:vars] == [:(x[12])] -# @test affdict[:vars] == alpine.bounding_constr_mip[4][:vars] -# @test isapprox(affdict[:rhs], 115.0; atol = 1e-3) -# @test affdict[:rhs] == alpine.bounding_constr_mip[4][:rhs] -# @test affdict[:sense] == :(<=) -# @test affdict[:sense] == alpine.bounding_constr_mip[4][:sense] - -# # 1.0 * x[12] - 115.0 <= 0.0 -# ex = alpine.bounding_constr_expr_mip[5] -# affdict = Alpine.expr_linear_to_affine(ex) -# @test affdict[:coefs] == [1.0] -# @test affdict[:coefs] == alpine.bounding_constr_mip[5][:coefs] -# @test affdict[:vars] == [:(x[12])] -# @test affdict[:vars] == alpine.bounding_constr_mip[5][:vars] -# @test isapprox(affdict[:rhs], 115.0; atol = 1e-3) -# @test affdict[:rhs] == alpine.bounding_constr_mip[5][:rhs] -# @test affdict[:sense] == :(>=) -# @test affdict[:sense] == alpine.bounding_constr_mip[5][:sense] - -# # -1.0 * x[12] - 115.0 >= 0.0 -# ex = alpine.bounding_constr_expr_mip[6] -# affdict = Alpine.expr_linear_to_affine(ex) -# @test affdict[:coefs] == [-1.0] -# @test affdict[:coefs] == alpine.bounding_constr_mip[6][:coefs] -# @test affdict[:vars] == [:(x[12])] -# @test affdict[:vars] == alpine.bounding_constr_mip[6][:vars] -# @test isapprox(affdict[:rhs], 115.0; atol = 1e-3) -# @test affdict[:rhs] == alpine.bounding_constr_mip[6][:rhs] -# @test affdict[:sense] == :(<=) -# @test affdict[:sense] == alpine.bounding_constr_mip[6][:sense] - -# # (x[1] + 1.0 * x[14]) - 555.0 >= 0.0 -# ex = alpine.bounding_constr_expr_mip[7] -# affdict = Alpine.expr_linear_to_affine(ex) -# @test affdict[:coefs] == [1.0, 1.0] -# @test affdict[:coefs] == alpine.bounding_constr_mip[7][:coefs] -# @test affdict[:vars] == [:(x[1]), :(x[14])] -# @test affdict[:vars] == alpine.bounding_constr_mip[7][:vars] -# @test isapprox(affdict[:rhs], 555.0; atol = 1e-3) -# @test affdict[:rhs] == alpine.bounding_constr_mip[7][:rhs] -# @test affdict[:sense] == :(>=) -# @test affdict[:sense] == alpine.bounding_constr_mip[7][:sense] - -# # ((x[8] - 7.0 * x[9]) + x[10] + x[4]) - 6666.0 <= 0.0 -# ex = alpine.bounding_constr_expr_mip[8] -# affdict = Alpine.expr_linear_to_affine(ex) -# @test affdict[:coefs] == [1.0, -7.0, 1.0, 1.0] -# @test affdict[:coefs] == alpine.bounding_constr_mip[8][:coefs] -# @test affdict[:vars] == [:(x[8]), :(x[9]), :(x[10]), :(x[4])] -# @test affdict[:vars] == alpine.bounding_constr_mip[8][:vars] -# @test isapprox(affdict[:rhs], 6666.0; atol = 1e-3) -# @test affdict[:rhs] == alpine.bounding_constr_mip[8][:rhs] -# @test affdict[:sense] == :(<=) -# @test affdict[:sense] == alpine.bounding_constr_mip[8][:sense] - -# # ((13.0 * x[1] - x[2]) + 30.0 * x[3] + x[4]) - 77.0 >= 0.0 -# ex = alpine.bounding_constr_expr_mip[9] -# affdict = Alpine.expr_linear_to_affine(ex) -# @test affdict[:coefs] == [13.0, -1.0, 30.0, 1.0] -# @test affdict[:coefs] == alpine.bounding_constr_mip[9][:coefs] -# @test affdict[:vars] == [:(x[1]), :(x[2]), :(x[3]), :(x[4])] -# @test affdict[:vars] == alpine.bounding_constr_mip[9][:vars] -# @test isapprox(affdict[:rhs], 77.0; atol = 1e-3) -# @test affdict[:rhs] == alpine.bounding_constr_mip[9][:rhs] -# @test affdict[:sense] == :(>=) -# @test affdict[:sense] == alpine.bounding_constr_mip[9][:sense] -# end - -# @testset "Expression Parsing || bilinear || Affine || nlp1.jl" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "log_level" => 100, -# ) -# m = nlp1(solver = test_solver) - -# alpine = _build(m) - -# ex = alpine.bounding_constr_expr_mip[1] -# affdict = Alpine.expr_linear_to_affine(ex) -# @test affdict[:coefs] == [1.0] -# @test affdict[:coefs] == alpine.bounding_constr_mip[1][:coefs] -# @test affdict[:vars] == [:(x[5])] -# @test affdict[:vars] == alpine.bounding_constr_mip[1][:vars] -# @test isapprox(affdict[:rhs], 8.0; atol = 1e-3) -# @test affdict[:rhs] == alpine.bounding_constr_mip[1][:rhs] -# @test affdict[:sense] == :(>=) -# @test affdict[:sense] == alpine.bounding_constr_mip[1][:sense] -# end - -# @testset "Expression Parsing || bilinear || Affine || nlp3.jl" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "log_level" => 100, -# ) - -# m = nlp3(solver = test_solver) - -# alpine = _build(m) - -# ex = alpine.bounding_constr_expr_mip[1] -# affdict = Alpine.expr_linear_to_affine(ex) -# @test affdict[:coefs] == [0.0025, 0.0025] -# @test affdict[:coefs] == alpine.bounding_constr_mip[1][:coefs] -# @test affdict[:vars] == [:(x[4]), :(x[6])] -# @test affdict[:vars] == alpine.bounding_constr_mip[1][:vars] -# @test isapprox(affdict[:rhs], 1.0; atol = 1e-3) -# @test affdict[:rhs] == alpine.bounding_constr_mip[1][:rhs] -# @test affdict[:sense] == :(<=) -# @test affdict[:sense] == alpine.bounding_constr_mip[1][:sense] - -# ex = alpine.bounding_constr_expr_mip[2] -# affdict = Alpine.expr_linear_to_affine(ex) -# @test affdict[:coefs] == [-0.0025, 0.0025, 0.0025] -# @test affdict[:coefs] == alpine.bounding_constr_mip[2][:coefs] -# @test affdict[:vars] == [:(x[4]), :(x[5]), :(x[7])] -# @test affdict[:vars] == alpine.bounding_constr_mip[2][:vars] -# @test isapprox(affdict[:rhs], 1.0; atol = 1e-3) -# @test affdict[:rhs] == alpine.bounding_constr_mip[2][:rhs] -# @test affdict[:sense] == :(<=) -# @test affdict[:sense] == alpine.bounding_constr_mip[2][:sense] - -# ex = alpine.bounding_constr_expr_mip[3] -# affdict = Alpine.expr_linear_to_affine(ex) -# @test affdict[:coefs] == [-0.01, 0.01] -# @test affdict[:coefs] == alpine.bounding_constr_mip[3][:coefs] -# @test affdict[:vars] == [:(x[5]), :(x[8])] -# @test affdict[:vars] == alpine.bounding_constr_mip[3][:vars] -# @test isapprox(affdict[:rhs], 1.0; atol = 1e-3) -# @test affdict[:rhs] == alpine.bounding_constr_mip[3][:rhs] -# @test affdict[:sense] == :(<=) -# @test affdict[:sense] == alpine.bounding_constr_mip[3][:sense] - -# ex = alpine.bounding_constr_expr_mip[4] -# affdict = Alpine.expr_linear_to_affine(ex) -# @test (affdict[:coefs] .== [100.0, -1.0, 833.33252]) == [true, true, true] -# @test affdict[:coefs] == alpine.bounding_constr_mip[4][:coefs] -# @test affdict[:vars] == [:(x[1]), :(x[9]), :(x[4])] -# @test affdict[:vars] == alpine.bounding_constr_mip[4][:vars] -# @test isapprox(affdict[:rhs], 83333.333; atol = 1e-3) -# @test affdict[:rhs] == alpine.bounding_constr_mip[4][:rhs] -# @test affdict[:sense] == :(<=) -# @test affdict[:sense] == alpine.bounding_constr_mip[4][:sense] - -# ex = alpine.bounding_constr_expr_mip[5] -# affdict = Alpine.expr_linear_to_affine(ex) -# @test affdict[:coefs] == [1.0, -1.0, -1250.0, 1250.0] -# @test affdict[:coefs] == alpine.bounding_constr_mip[5][:coefs] -# @test affdict[:vars] == [:(x[10]), :(x[11]), :(x[4]), :(x[5])] -# @test affdict[:vars] == alpine.bounding_constr_mip[5][:vars] -# @test isapprox(affdict[:rhs], 0.0; atol = 1e-3) -# @test affdict[:rhs] == alpine.bounding_constr_mip[5][:rhs] -# @test affdict[:sense] == :(<=) -# @test affdict[:sense] == alpine.bounding_constr_mip[5][:sense] - -# ex = alpine.bounding_constr_expr_mip[6] -# affdict = Alpine.expr_linear_to_affine(ex) -# @test affdict[:coefs] == [1.0, -1.0, -2500.0] -# @test affdict[:coefs] == alpine.bounding_constr_mip[6][:coefs] -# @test affdict[:vars] == [:(x[12]), :(x[13]), :(x[5])] -# @test affdict[:vars] == alpine.bounding_constr_mip[6][:vars] -# @test isapprox(affdict[:rhs], -1.25e6; atol = 1e-3) -# @test affdict[:rhs] == alpine.bounding_constr_mip[6][:rhs] -# @test affdict[:sense] == :(<=) -# @test affdict[:sense] == alpine.bounding_constr_mip[6][:sense] -# end - -# @testset "Expression Parsing || bilinear || Simple || bi1.jl " begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "log_level" => 100, -# ) - -# m = operator_c(solver = test_solver) - -# alpine = _build(m) # Setup internal model - -# @test length(keys(alpine.nonconvex_terms)) == 8 -# @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 1), Expr(:ref, :x, 1)]) -# @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 2), Expr(:ref, :x, 2)]) -# @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 3), Expr(:ref, :x, 3)]) -# @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 4), Expr(:ref, :x, 4)]) -# @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 2), Expr(:ref, :x, 3)]) -# @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 3), Expr(:ref, :x, 4)]) - -# # TODO setup detailed check on this problem -# end -# @testset "Expression Parsing || bilinear || Complex || blend029.jl " begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "minlp_solver" => JUNIPER, -# "mip_solver" => HIGHS, -# "log_level" => 100, -# ) - -# m = blend029(solver = test_solver) - -# alpine = _build(m) # Setup internal model - -# @test length(keys(alpine.nonconvex_terms)) == 28 -# @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 37), Expr(:ref, :x, 55)]) -# @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 38), Expr(:ref, :x, 56)]) -# @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 37), Expr(:ref, :x, 26)]) -# @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 43), Expr(:ref, :x, 26)]) -# @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 47), Expr(:ref, :x, 59)]) -# @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 48), Expr(:ref, :x, 60)]) -# @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 47), Expr(:ref, :x, 36)]) - -# @test alpine.bounding_constr_mip[1][:rhs] == 1.0 -# @test alpine.bounding_constr_mip[1][:vars] == -# Any[:(x[1]), :(x[4]), :(x[7]), :(x[10]), :(x[49])] -# @test alpine.bounding_constr_mip[1][:sense] == :(==) -# @test alpine.bounding_constr_mip[1][:coefs] == Any[1.0, 1.0, 1.0, 1.0, 1.0] -# @test alpine.bounding_constr_mip[1][:cnt] == 5 - -# @test alpine.bounding_constr_mip[4][:rhs] == 0.1 -# @test alpine.bounding_constr_mip[4][:vars] == -# Any[:(x[4]), :(x[16]), :(x[25]), :(x[34]), :(x[58])] -# @test alpine.bounding_constr_mip[4][:sense] == :(==) -# @test alpine.bounding_constr_mip[4][:coefs] == Any[-1.0, -1.0, -1.0, 1.0, 1.0] -# @test alpine.bounding_constr_mip[4][:cnt] == 5 - -# @test alpine.bounding_constr_mip[17][:rhs] == -0.14 -# @test alpine.bounding_constr_mip[17][:vars] == -# Any[:(x[11]), :(x[23]), :(x[32]), :(x[64]), :(x[65])] -# @test alpine.bounding_constr_mip[17][:sense] == :(==) -# @test alpine.bounding_constr_mip[17][:coefs] == Any[-1.0, -1.0, -1.0, -1.0, 1.0] -# @test alpine.bounding_constr_mip[17][:cnt] == 5 - -# @test alpine.bounding_constr_mip[31][:rhs] == 0.0 -# @test alpine.bounding_constr_mip[31][:vars] == Any[:(x[13])] -# @test alpine.bounding_constr_mip[31][:sense] == :(>=) -# @test alpine.bounding_constr_mip[31][:coefs] == Any[1.0] -# @test alpine.bounding_constr_mip[31][:cnt] == 1 - -# @test alpine.bounding_constr_mip[145][:rhs] == 1.0 -# @test alpine.bounding_constr_mip[145][:vars] == Any[:(x[73])] -# @test alpine.bounding_constr_mip[145][:sense] == :(<=) -# @test alpine.bounding_constr_mip[145][:coefs] == Any[1.0] -# @test alpine.bounding_constr_mip[145][:cnt] == 1 - -# @test alpine.bounding_constr_mip[67][:rhs] == -1.0 -# @test alpine.bounding_constr_mip[67][:vars] == Any[:(x[73])] -# @test alpine.bounding_constr_mip[67][:sense] == :(>=) -# @test alpine.bounding_constr_mip[67][:coefs] == Any[-1.0] -# @test alpine.bounding_constr_mip[67][:cnt] == 1 - -# @test alpine.bounding_constr_mip[187][:rhs] == 1.0 -# @test alpine.bounding_constr_mip[187][:vars] == Any[:(x[79]), :(x[94])] -# @test alpine.bounding_constr_mip[187][:sense] == :(<=) -# @test alpine.bounding_constr_mip[187][:coefs] == Any[1.0, 1.0] -# @test alpine.bounding_constr_mip[187][:cnt] == 2 - -# @test alpine.bounding_constr_mip[202][:rhs] == 0.04 -# @test alpine.bounding_constr_mip[202][:vars] == -# Any[:(x[103]), :(x[1]), :(x[13]), :(x[25]), :(x[28]), :(x[31])] -# @test alpine.bounding_constr_mip[202][:sense] == :(==) -# @test alpine.bounding_constr_mip[202][:coefs] == Any[1.0, -0.6, -0.2, 0.2, 0.2, 0.2] -# @test alpine.bounding_constr_mip[202][:cnt] == 6 - -# @test alpine.nonconvex_terms[[:(x[37]), :(x[55])]][:id] == 1 -# @test alpine.nonconvex_terms[[:(x[37]), :(x[55])]][:lifted_var_ref] == :(x[103]) -# @test alpine.nonconvex_terms[[:(x[37]), :(x[55])]][:convexified] == false -# @test alpine.nonconvex_terms[[:(x[37]), :(x[55])]][:nonlinear_type] == :BILINEAR - -# @test alpine.bounding_constr_mip[206][:rhs] == 0.0 -# @test alpine.bounding_constr_mip[206][:vars] == -# Any[:(x[107]), :(x[103]), :(x[108]), :(x[109]), :(x[110]), :(x[2]), :(x[14])] -# @test alpine.bounding_constr_mip[206][:sense] == :(==) -# @test alpine.bounding_constr_mip[206][:coefs] == -# Any[1.0, -1.0, 1.0, 1.0, 1.0, -0.6, -0.2] -# @test alpine.bounding_constr_mip[206][:cnt] == 7 - -# @test alpine.nonconvex_terms[[:(x[38]), :(x[56])]][:id] == 5 -# @test alpine.nonconvex_terms[[:(x[38]), :(x[56])]][:lifted_var_ref] == :(x[107]) -# @test alpine.nonconvex_terms[[:(x[38]), :(x[56])]][:convexified] == false -# @test alpine.nonconvex_terms[[:(x[38]), :(x[56])]][:nonlinear_type] == :BILINEAR - -# @test alpine.nonconvex_terms[[:(x[37]), :(x[26])]][:id] == 6 -# @test alpine.nonconvex_terms[[:(x[37]), :(x[26])]][:lifted_var_ref] == :(x[108]) -# @test alpine.nonconvex_terms[[:(x[37]), :(x[26])]][:convexified] == false -# @test alpine.nonconvex_terms[[:(x[37]), :(x[26])]][:nonlinear_type] == :BILINEAR - -# @test alpine.nonconvex_terms[[:(x[37]), :(x[32])]][:id] == 8 -# @test alpine.nonconvex_terms[[:(x[37]), :(x[32])]][:lifted_var_ref] == :(x[110]) -# @test alpine.nonconvex_terms[[:(x[37]), :(x[32])]][:convexified] == false -# @test alpine.nonconvex_terms[[:(x[37]), :(x[32])]][:nonlinear_type] == :BILINEAR - -# @test alpine.bounding_constr_mip[213][:rhs] == 0.0 -# @test alpine.bounding_constr_mip[213][:vars] == -# Any[:(x[129]), :(x[127]), :(x[124]), :(x[130]), :(x[6]), :(x[18])] -# @test alpine.bounding_constr_mip[213][:sense] == :(==) -# @test alpine.bounding_constr_mip[213][:coefs] == Any[1.0, -1.0, -1.0, 1.0, -0.4, -0.4] -# @test alpine.bounding_constr_mip[213][:cnt] == 6 - -# @test alpine.nonconvex_terms[[:(x[48]), :(x[60])]][:id] == 27 -# @test alpine.nonconvex_terms[[:(x[48]), :(x[60])]][:lifted_var_ref] == :(x[129]) -# @test alpine.nonconvex_terms[[:(x[48]), :(x[60])]][:convexified] == false -# @test alpine.nonconvex_terms[[:(x[48]), :(x[60])]][:nonlinear_type] == :BILINEAR - -# @test alpine.nonconvex_terms[[:(x[47]), :(x[59])]][:id] == 25 -# @test alpine.nonconvex_terms[[:(x[47]), :(x[59])]][:lifted_var_ref] == :(x[127]) -# @test alpine.nonconvex_terms[[:(x[47]), :(x[59])]][:convexified] == false -# @test alpine.nonconvex_terms[[:(x[47]), :(x[59])]][:nonlinear_type] == :BILINEAR - -# @test alpine.nonconvex_terms[[:(x[47]), :(x[36])]][:id] == 28 -# @test alpine.nonconvex_terms[[:(x[47]), :(x[36])]][:lifted_var_ref] == :(x[130]) -# @test alpine.nonconvex_terms[[:(x[47]), :(x[36])]][:convexified] == false -# @test alpine.nonconvex_terms[[:(x[47]), :(x[36])]][:nonlinear_type] == :BILINEAR -# end - -# @testset "Expression Parsing || multilinear || Simple || multi.jl " begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "log_level" => 100, -# ) - -# m = multi3(solver = test_solver, exprmode = 1) - -# alpine = _build(m) # Setup internal model - -# @test length(keys(alpine.nonconvex_terms)) == 1 -# @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3])]][:id] == 1 -# @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3])]][:lifted_var_ref] == :(x[4]) -# @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3])]][:nonlinear_type] == -# :MULTILINEAR - -# @test alpine.bounding_obj_mip[:rhs] == 0 -# @test alpine.bounding_obj_mip[:vars] == Expr[:(x[4])] -# @test alpine.bounding_obj_mip[:coefs] == [1.0] -# @test alpine.bounding_obj_mip[:cnt] == 1 -# @test alpine.bounding_obj_mip[:sense] === nothing - -# @test alpine.bounding_constr_mip[1][:rhs] == 3.0 -# @test alpine.bounding_constr_mip[1][:vars] == Any[:(x[1]), :(x[2]), :(x[3])] -# @test alpine.bounding_constr_mip[1][:sense] == :(<=) -# @test alpine.bounding_constr_mip[1][:coefs] == Any[1.0, 1.0, 1.0] -# @test alpine.bounding_constr_mip[1][:cnt] == 3 - -# m = multi3(solver = test_solver, exprmode = 2) - -# alpine = _build(m) - -# @test length(keys(alpine.nonconvex_terms)) == 2 -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:id] == 1 -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:lifted_var_ref] == -# :(x[4]) -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 4), Expr(:ref, :x, 3)]][:id] == 2 -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 4), Expr(:ref, :x, 3)]][:lifted_var_ref] == -# :(x[5]) -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 4), Expr(:ref, :x, 3)]][:nonlinear_type] == -# :BILINEAR - -# @test alpine.bounding_obj_mip[:rhs] == 0 -# @test alpine.bounding_obj_mip[:vars] == Expr[:(x[5])] -# @test alpine.bounding_obj_mip[:coefs] == [1.0] -# @test alpine.bounding_obj_mip[:cnt] == 1 -# @test alpine.bounding_obj_mip[:sense] === nothing - -# m = multi3(solver = test_solver, exprmode = 3) - -# alpine = _build(m) - -# @test length(keys(alpine.nonconvex_terms)) == 2 -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:id] == 1 -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:lifted_var_ref] == -# :(x[4]) -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 4)]][:id] == 2 -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 4)]][:lifted_var_ref] == -# :(x[5]) -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 4)]][:nonlinear_type] == -# :BILINEAR - -# @test alpine.bounding_obj_mip[:rhs] == 0 -# @test alpine.bounding_obj_mip[:vars] == Expr[:(x[5])] -# @test alpine.bounding_obj_mip[:coefs] == [1.0] -# @test alpine.bounding_obj_mip[:cnt] == 1 -# @test alpine.bounding_obj_mip[:sense] === nothing - -# m = multi4(solver = test_solver, exprmode = 1) - -# alpine = _build(m) - -# @test length(keys(alpine.nonconvex_terms)) == 1 - -# @test alpine.bounding_obj_mip[:rhs] == 0 -# @test alpine.bounding_obj_mip[:vars] == Expr[:(x[5])] -# @test alpine.bounding_obj_mip[:coefs] == [1.0] -# @test alpine.bounding_obj_mip[:cnt] == 1 -# @test alpine.bounding_obj_mip[:sense] === nothing - -# @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:id] == 1 -# @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:lifted_var_ref] == -# :(x[5]) -# @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:nonlinear_type] == -# :MULTILINEAR - -# @test alpine.bounding_constr_mip[1][:rhs] == 4.0 -# @test alpine.bounding_constr_mip[1][:vars] == Any[:(x[1]), :(x[2]), :(x[3]), :(x[4])] -# @test alpine.bounding_constr_mip[1][:sense] == :(<=) -# @test alpine.bounding_constr_mip[1][:coefs] == Any[1.0, 1.0, 1.0, 1.0] -# @test alpine.bounding_constr_mip[1][:cnt] == 4 - -# m = multi4(solver = test_solver, exprmode = 2) - -# alpine = _build(m) - -# @test length(keys(alpine.nonconvex_terms)) == 3 - -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:id] == 1 -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:lifted_var_ref] == -# :(x[5]) -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:id] == 2 -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:lifted_var_ref] == -# :(x[6]) -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 5), Expr(:ref, :x, 6)]][:id] == 3 -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 5), Expr(:ref, :x, 6)]][:lifted_var_ref] == -# :(x[7]) -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 5), Expr(:ref, :x, 6)]][:nonlinear_type] == -# :BILINEAR - -# @test alpine.bounding_obj_mip[:rhs] == 0 -# @test alpine.bounding_obj_mip[:vars] == Expr[:(x[7])] -# @test alpine.bounding_obj_mip[:coefs] == [1.0] -# @test alpine.bounding_obj_mip[:cnt] == 1 -# @test alpine.bounding_obj_mip[:sense] === nothing - -# m = multi4(solver = test_solver, exprmode = 3) - -# alpine = _build(m) - -# @test length(keys(alpine.nonconvex_terms)) == 2 - -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:id] == 1 -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:lifted_var_ref] == -# :(x[5]) -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[[:(x[5]), :(x[3]), :(x[4])]][:id] == 2 -# @test alpine.nonconvex_terms[[:(x[5]), :(x[3]), :(x[4])]][:lifted_var_ref] == :(x[6]) -# @test alpine.nonconvex_terms[[:(x[5]), :(x[3]), :(x[4])]][:nonlinear_type] == -# :MULTILINEAR - -# @test alpine.bounding_obj_mip[:rhs] == 0 -# @test alpine.bounding_obj_mip[:vars] == Expr[:(x[6])] -# @test alpine.bounding_obj_mip[:coefs] == [1.0] -# @test alpine.bounding_obj_mip[:cnt] == 1 -# @test alpine.bounding_obj_mip[:sense] === nothing - -# m = multi4(solver = test_solver, exprmode = 4) - -# alpine = _build(m) - -# @test length(keys(alpine.nonconvex_terms)) == 2 - -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:id] == 1 -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:lifted_var_ref] == -# :(x[5]) -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[5])]][:id] == 2 -# @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[5])]][:lifted_var_ref] == :(x[6]) -# @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[5])]][:nonlinear_type] == -# :MULTILINEAR - -# @test alpine.bounding_obj_mip[:rhs] == 0 -# @test alpine.bounding_obj_mip[:vars] == Expr[:(x[6])] -# @test alpine.bounding_obj_mip[:coefs] == [1.0] -# @test alpine.bounding_obj_mip[:cnt] == 1 -# @test alpine.bounding_obj_mip[:sense] === nothing - -# @test alpine.bounding_obj_mip[:rhs] == 0 -# @test alpine.bounding_obj_mip[:vars] == Expr[:(x[6])] -# @test alpine.bounding_obj_mip[:coefs] == [1.0] -# @test alpine.bounding_obj_mip[:cnt] == 1 -# @test alpine.bounding_obj_mip[:sense] === nothing - -# m = multi4(solver = test_solver, exprmode = 5) - -# alpine = _build(m) - -# @test length(keys(alpine.nonconvex_terms)) == 3 - -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:id] == 1 -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:lifted_var_ref] == -# :(x[5]) -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 5)]][:id] == 2 -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 5)]][:lifted_var_ref] == -# :(x[6]) -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 5)]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 6), Expr(:ref, :x, 4)]][:id] == 3 -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 6), Expr(:ref, :x, 4)]][:lifted_var_ref] == -# :(x[7]) -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 6), Expr(:ref, :x, 4)]][:nonlinear_type] == -# :BILINEAR - -# @test alpine.bounding_obj_mip[:rhs] == 0 -# @test alpine.bounding_obj_mip[:vars] == Expr[:(x[7])] -# @test alpine.bounding_obj_mip[:coefs] == [1.0] -# @test alpine.bounding_obj_mip[:cnt] == 1 -# @test alpine.bounding_obj_mip[:sense] === nothing - -# @test alpine.bounding_obj_mip[:rhs] == 0 -# @test alpine.bounding_obj_mip[:vars] == Expr[:(x[7])] -# @test alpine.bounding_obj_mip[:coefs] == [1.0] -# @test alpine.bounding_obj_mip[:cnt] == 1 -# @test alpine.bounding_obj_mip[:sense] === nothing - -# m = multi4(solver = test_solver, exprmode = 6) - -# alpine = _build(m) - -# @test length(keys(alpine.nonconvex_terms)) == 2 - -# @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3])]][:id] == 1 -# @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3])]][:lifted_var_ref] == :(x[5]) -# @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 5), Expr(:ref, :x, 4)]][:id] == 2 -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 5), Expr(:ref, :x, 4)]][:lifted_var_ref] == -# :(x[6]) -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 5), Expr(:ref, :x, 4)]][:nonlinear_type] == -# :BILINEAR - -# @test alpine.bounding_obj_mip[:rhs] == 0 -# @test alpine.bounding_obj_mip[:vars] == Expr[:(x[6])] -# @test alpine.bounding_obj_mip[:coefs] == [1.0] -# @test alpine.bounding_obj_mip[:cnt] == 1 -# @test alpine.bounding_obj_mip[:sense] === nothing - -# m = multi4(solver = test_solver, exprmode = 7) - -# alpine = _build(m) - -# @test length(keys(alpine.nonconvex_terms)) == 3 - -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:id] == 1 -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:lifted_var_ref] == -# :(x[5]) -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 5)]][:id] == 2 -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 5)]][:lifted_var_ref] == -# :(x[6]) -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 5)]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 6)]][:id] == 3 -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 6)]][:lifted_var_ref] == -# :(x[7]) -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 6)]][:nonlinear_type] == -# :BILINEAR - -# @test alpine.bounding_obj_mip[:rhs] == 0 -# @test alpine.bounding_obj_mip[:vars] == Expr[:(x[7])] -# @test alpine.bounding_obj_mip[:coefs] == [1.0] -# @test alpine.bounding_obj_mip[:cnt] == 1 -# @test alpine.bounding_obj_mip[:sense] === nothing - -# m = multi4(solver = test_solver, exprmode = 8) - -# alpine = _build(m) - -# @test length(keys(alpine.nonconvex_terms)) == 2 - -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:id] == 1 -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:lifted_var_ref] == -# :(x[5]) -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[[:(x[1]), :(x[5]), :(x[4])]][:id] == 2 -# @test alpine.nonconvex_terms[[:(x[1]), :(x[5]), :(x[4])]][:lifted_var_ref] == :(x[6]) -# @test alpine.nonconvex_terms[[:(x[1]), :(x[5]), :(x[4])]][:nonlinear_type] == -# :MULTILINEAR - -# @test alpine.bounding_obj_mip[:rhs] == 0 -# @test alpine.bounding_obj_mip[:vars] == Expr[:(x[6])] -# @test alpine.bounding_obj_mip[:coefs] == [1.0] -# @test alpine.bounding_obj_mip[:cnt] == 1 -# @test alpine.bounding_obj_mip[:sense] === nothing - -# m = multi4(solver = test_solver, exprmode = 9) - -# alpine = _build(m) - -# @test length(keys(alpine.nonconvex_terms)) == 2 - -# @test alpine.nonconvex_terms[[:(x[2]), :(x[3]), :(x[4])]][:id] == 1 -# @test alpine.nonconvex_terms[[:(x[2]), :(x[3]), :(x[4])]][:lifted_var_ref] == :(x[5]) -# @test alpine.nonconvex_terms[[:(x[2]), :(x[3]), :(x[4])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 5)]][:id] == 2 -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 5)]][:lifted_var_ref] == -# :(x[6]) -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 5)]][:nonlinear_type] == -# :BILINEAR - -# @test alpine.bounding_obj_mip[:rhs] == 0 -# @test alpine.bounding_obj_mip[:vars] == Expr[:(x[6])] -# @test alpine.bounding_obj_mip[:coefs] == [1.0] -# @test alpine.bounding_obj_mip[:cnt] == 1 -# @test alpine.bounding_obj_mip[:sense] === nothing - -# m = multi4(solver = test_solver, exprmode = 10) - -# alpine = _build(m) -# @test length(keys(alpine.nonconvex_terms)) == 3 - -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:id] == 1 -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:lifted_var_ref] == -# :(x[5]) -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 4), Expr(:ref, :x, 5)]][:id] == 2 -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 4), Expr(:ref, :x, 5)]][:lifted_var_ref] == -# :(x[6]) -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 4), Expr(:ref, :x, 5)]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 6)]][:id] == 3 -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 6)]][:lifted_var_ref] == -# :(x[7]) -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 6)]][:nonlinear_type] == -# :BILINEAR - -# @test alpine.bounding_obj_mip[:rhs] == 0 -# @test alpine.bounding_obj_mip[:vars] == Expr[:(x[7])] -# @test alpine.bounding_obj_mip[:coefs] == [1.0] -# @test alpine.bounding_obj_mip[:cnt] == 1 -# @test alpine.bounding_obj_mip[:sense] === nothing - -# m = multi4(solver = test_solver, exprmode = 11) - -# alpine = _build(m) - -# @test length(keys(alpine.nonconvex_terms)) == 3 - -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:id] == 1 -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:lifted_var_ref] == -# :(x[5]) -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 5)]][:id] == 2 -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 5)]][:lifted_var_ref] == -# :(x[6]) -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 5)]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 6), Expr(:ref, :x, 4)]][:id] == 3 -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 6), Expr(:ref, :x, 4)]][:lifted_var_ref] == -# :(x[7]) -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 6), Expr(:ref, :x, 4)]][:nonlinear_type] == -# :BILINEAR - -# @test alpine.bounding_obj_mip[:rhs] == 0 -# @test alpine.bounding_obj_mip[:vars] == Expr[:(x[7])] -# @test alpine.bounding_obj_mip[:coefs] == [1.0] -# @test alpine.bounding_obj_mip[:cnt] == 1 -# @test alpine.bounding_obj_mip[:sense] === nothing -# end - -# @testset "Expression Parsing || bilinear || Complex-div || div.jl" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "log_level" => 100, -# ) - -# m = div(solver = test_solver) - -# alpine = _build(m) # Setup internal model - -# @test length(keys(alpine.nonconvex_terms)) == 3 -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 1)]][:id] == 1 -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 1)]][:lifted_var_ref] == -# :(x[3]) -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 1)]][:nonlinear_type] == -# :MONOMIAL - -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 2)]][:id] == 2 -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 2)]][:lifted_var_ref] == -# :(x[4]) -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 2)]][:nonlinear_type] == -# :MONOMIAL - -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:id] == 3 -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:lifted_var_ref] == -# :(x[5]) -# @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:nonlinear_type] == -# :BILINEAR - -# aff_mip = alpine.bounding_constr_mip - -# @test aff_mip[1][:rhs] == 0.0 -# @test aff_mip[1][:vars] == Any[:(x[1])] -# @test aff_mip[1][:sense] == :(>=) -# @test round(aff_mip[1][:coefs][1]; digits = 1) == -3.0 -# @test aff_mip[1][:cnt] == 1 - -# @test aff_mip[2][:rhs] == 0.0 -# @test aff_mip[2][:vars] == Any[:(x[2])] -# @test aff_mip[2][:sense] == :(>=) -# @test aff_mip[2][:coefs] == Any[0.25] -# @test aff_mip[2][:cnt] == 1 - -# @test aff_mip[3][:rhs] == 0.0 -# @test aff_mip[3][:vars] == Any[:(x[2])] -# @test aff_mip[3][:sense] == :(>=) -# @test aff_mip[3][:coefs] == Any[5.0] -# @test aff_mip[3][:cnt] == 1 - -# @test aff_mip[4][:rhs] == 0.0 -# @test aff_mip[4][:vars] == Any[:(x[2])] -# @test aff_mip[4][:sense] == :(>=) -# @test aff_mip[4][:coefs] == Any[-120.0] -# @test aff_mip[4][:cnt] == 1 - -# @test aff_mip[5][:rhs] == 0.0 -# @test aff_mip[5][:vars] == Any[:(x[2])] -# @test aff_mip[5][:sense] == :(>=) -# @test aff_mip[5][:coefs] == Any[72000.0] -# @test aff_mip[5][:cnt] == 1 - -# @test aff_mip[6][:rhs] == 0.0 -# @test aff_mip[6][:vars] == Any[:(x[1])] -# @test aff_mip[6][:sense] == :(>=) -# @test aff_mip[6][:coefs] == Any[72000.0] -# @test aff_mip[6][:cnt] == 1 - -# @test aff_mip[7][:rhs] == 8.0 -# @test aff_mip[7][:vars] == Any[:(x[5])] -# @test aff_mip[7][:sense] == :(>=) -# @test aff_mip[7][:coefs] == Any[0.6] -# @test aff_mip[7][:cnt] == 1 - -# @test aff_mip[8][:rhs] == 0.0 -# @test aff_mip[8][:vars] == Any[:(x[2]), :(x[5])] -# @test aff_mip[8][:sense] == :(>=) -# @test aff_mip[8][:coefs] == Any[5.6, -72000.0] -# @test aff_mip[8][:cnt] == 2 - -# @test aff_mip[9][:rhs] == 0.0 -# @test aff_mip[9][:vars] == Any[:(x[2]), :(x[5])] -# @test aff_mip[9][:sense] == :(>=) -# @test aff_mip[9][:coefs] == Any[5.6, -36000.0] -# @test aff_mip[9][:cnt] == 2 - -# @test aff_mip[10][:rhs] == 0.0 -# @test aff_mip[10][:vars] == Any[:(x[2]), :(x[5]), :(x[2])] -# @test aff_mip[10][:sense] == :(>=) -# @test aff_mip[10][:coefs] == Any[5.6, -300.0, -1.75] -# @test aff_mip[10][:cnt] == 3 - -# @test aff_mip[11][:rhs] == 0.0 -# @test aff_mip[11][:vars] == Any[:(x[2]), :(x[1]), :(x[5])] -# @test aff_mip[11][:sense] == :(>=) -# @test aff_mip[11][:coefs] == Any[5.6, -0.5, 0.5] -# @test aff_mip[11][:cnt] == 3 -# end - -# @testset "Expression Parsing || part1 " begin -# m = Model( -# optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "log_level" => 100, -# ), -# ) -# @variable(m, x[1:4] >= 0) -# @NLconstraint(m, x[1]^2 >= 1) # Basic monomial x[5]=x[1]^2 -# @NLconstraint(m, x[1] * x[2] <= 1) # x[6] <= 1 : x[6] = x[1]*x[2] -# @NLconstraint(m, x[1]^2 * x[2]^2 <= 1) # x[5] + x[7] <= 1 : x[7] = x[2]^2 -# @NLconstraint(m, x[1] * (x[2] * x[3]) >= 1) # x[9] >= 1 : x[8] = x[2] * x[3] && x[9] = x[1]*x[8] -# @NLconstraint(m, x[1]^2 * (x[2]^2 * x[3]^2) <= 1) # x[12] <= 1 : x[10] = x[3] ^ 2 && x[11] = x[7] * x[10] && x[12] = x[11]*[5] - -# alpine = _build(m) - -# @test alpine.bounding_constr_expr_mip[1] == :(x[5] - 1.0 >= 0.0) -# @test alpine.bounding_constr_expr_mip[2] == :(x[6] - 1.0 <= 0.0) -# @test alpine.bounding_constr_expr_mip[3] == :(x[8] - 1.0 <= 0.0) -# @test alpine.bounding_constr_expr_mip[4] == :(x[10] - 1.0 >= 0.0) -# @test alpine.bounding_constr_expr_mip[5] == :(x[13] - 1.0 <= 0.0) -# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[1])]) -# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2])]) -# @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[2])]) -# @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[3])]) -# @test haskey(alpine.nonconvex_terms, [:(x[5]), :(x[7])]) -# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[9])]) -# @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[3])]) -# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2])]) -# @test haskey(alpine.nonconvex_terms, [:(x[5]), :(x[12])]) - -# @test alpine.nonconvex_terms[[:(x[1]), :(x[1])]][:id] == 1 -# @test alpine.nonconvex_terms[[:(x[1]), :(x[2])]][:id] == 2 -# @test alpine.nonconvex_terms[[:(x[2]), :(x[2])]][:id] == 3 -# @test alpine.nonconvex_terms[[:(x[5]), :(x[7])]][:id] == 4 -# @test alpine.nonconvex_terms[[:(x[2]), :(x[3])]][:id] == 5 -# @test alpine.nonconvex_terms[[:(x[1]), :(x[9])]][:id] == 6 -# @test alpine.nonconvex_terms[[:(x[3]), :(x[3])]][:id] == 7 -# @test alpine.nonconvex_terms[[:(x[7]), :(x[11])]][:id] == 8 -# @test alpine.nonconvex_terms[[:(x[5]), :(x[12])]][:id] == 9 -# end - -# @testset "Expression Parsing || part2" begin -# m = Model( -# optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "log_level" => 100, -# ), -# ) - -# @variable(m, x[1:4] >= 0) -# @NLconstraint(m, (x[1] * x[2]) * x[3] >= 1) -# @NLconstraint(m, (x[1]^2 * x[2]^2) * x[3]^2 <= 1) - -# @NLconstraint(m, x[1] * (x[2]^2 * x[3]^2) >= 1) -# @NLconstraint(m, (x[1]^2 * x[2]) * x[3]^2 <= 1) -# @NLconstraint(m, x[1]^2 * (x[2] * x[3]) >= 1) -# @NLconstraint(m, (x[1] * x[2]^2) * x[3] <= 1) - -# alpine = _build(m) - -# @test alpine.bounding_constr_expr_mip[1] == :(x[6] - 1.0 >= 0.0) -# @test alpine.bounding_constr_expr_mip[2] == :(x[11] - 1.0 <= 0.0) -# @test alpine.bounding_constr_expr_mip[3] == :(x[13] - 1.0 >= 0.0) -# @test alpine.bounding_constr_expr_mip[4] == :(x[15] - 1.0 <= 0.0) -# @test alpine.bounding_constr_expr_mip[5] == :(x[17] - 1.0 >= 0.0) -# @test alpine.bounding_constr_expr_mip[6] == :(x[19] - 1.0 <= 0.0) - -# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2])]) #5 -# @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[5])]) #6 -# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[1])]) #7 -# @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[2])]) #8 -# @test haskey(alpine.nonconvex_terms, [:(x[7]), :(x[8])]) #9 -# @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[3])]) #10 -# @test haskey(alpine.nonconvex_terms, [:(x[9]), :(x[10])]) #11 -# @test haskey(alpine.nonconvex_terms, [:(x[8]), :(x[10])]) #12 -# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[12])]) #13 -# @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[7])]) #14 -# @test haskey(alpine.nonconvex_terms, [:(x[14]), :(x[10])]) #15 -# @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[3])]) #16 -# @test haskey(alpine.nonconvex_terms, [:(x[7]), :(x[16])]) #17 -# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[8])]) #18 -# @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[18])]) #19 - -# @test alpine.nonconvex_terms[[:(x[1]), :(x[2])]][:id] == 1 -# @test alpine.nonconvex_terms[[:(x[3]), :(x[5])]][:id] == 2 -# @test alpine.nonconvex_terms[[:(x[1]), :(x[1])]][:id] == 3 -# @test alpine.nonconvex_terms[[:(x[2]), :(x[2])]][:id] == 4 -# @test alpine.nonconvex_terms[[:(x[7]), :(x[8])]][:id] == 5 -# @test alpine.nonconvex_terms[[:(x[3]), :(x[3])]][:id] == 6 -# @test alpine.nonconvex_terms[[:(x[9]), :(x[10])]][:id] == 7 -# @test alpine.nonconvex_terms[[:(x[8]), :(x[10])]][:id] == 8 -# @test alpine.nonconvex_terms[[:(x[1]), :(x[12])]][:id] == 9 -# @test alpine.nonconvex_terms[[:(x[2]), :(x[7])]][:id] == 10 -# @test alpine.nonconvex_terms[[:(x[14]), :(x[10])]][:id] == 11 -# @test alpine.nonconvex_terms[[:(x[2]), :(x[3])]][:id] == 12 -# @test alpine.nonconvex_terms[[:(x[7]), :(x[16])]][:id] == 13 -# @test alpine.nonconvex_terms[[:(x[1]), :(x[8])]][:id] == 14 -# @test alpine.nonconvex_terms[[:(x[3]), :(x[18])]][:id] == 15 -# end - -# @testset "Expression Parsing || part3" begin -# m = Model( -# optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "log_level" => 100, -# ), -# ) - -# @variable(m, x[1:4] >= 0) -# @NLconstraint(m, ((x[1] * x[2]) * x[3]) * x[4] >= 1) -# @NLconstraint(m, ((x[1]^2 * x[2]) * x[3]) * x[4] <= 1) -# @NLconstraint(m, ((x[1] * x[2]^2) * x[3]) * x[4] >= 1) -# @NLconstraint(m, ((x[1] * x[2]) * x[3]^2) * x[4] <= 1) -# @NLconstraint(m, ((x[1] * x[2]) * x[3]) * x[4]^2 >= 1) -# @NLconstraint(m, ((x[1]^2 * x[2]^2) * x[3]^2) * x[4]^2 <= 1) - -# alpine = _build(m) - -# @test alpine.bounding_constr_expr_mip[1] == :(x[7] - 1.0 >= 0.0) -# @test alpine.bounding_constr_expr_mip[2] == :(x[11] - 1.0 <= 0.0) -# @test alpine.bounding_constr_expr_mip[3] == :(x[15] - 1.0 >= 0.0) -# @test alpine.bounding_constr_expr_mip[4] == :(x[18] - 1.0 <= 0.0) -# @test alpine.bounding_constr_expr_mip[5] == :(x[20] - 1.0 >= 0.0) -# @test alpine.bounding_constr_expr_mip[6] == :(x[23] - 1.0 <= 0.0) - -# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2])]) #5 -# @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[5])]) #6 -# @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[6])]) #7 -# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[1])]) #8 -# @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[8])]) #9 -# @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[9])]) #10 -# @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[10])]) #11 -# @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[2])]) #12 -# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[12])]) #13 -# @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[13])]) #14 -# @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[14])]) #15 -# @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[3])]) #16 -# @test haskey(alpine.nonconvex_terms, [:(x[5]), :(x[16])]) #17 -# @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[17])]) #18 -# @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[4])]) #19 -# @test haskey(alpine.nonconvex_terms, [:(x[6]), :(x[19])]) #20 -# @test haskey(alpine.nonconvex_terms, [:(x[8]), :(x[12])]) #21 -# @test haskey(alpine.nonconvex_terms, [:(x[21]), :(x[16])]) #22 -# @test haskey(alpine.nonconvex_terms, [:(x[22]), :(x[19])]) #23 - -# @test alpine.nonconvex_terms[[:(x[1]), :(x[2])]][:id] == 1 -# @test alpine.nonconvex_terms[[:(x[3]), :(x[5])]][:id] == 2 -# @test alpine.nonconvex_terms[[:(x[4]), :(x[6])]][:id] == 3 -# @test alpine.nonconvex_terms[[:(x[1]), :(x[1])]][:id] == 4 -# @test alpine.nonconvex_terms[[:(x[2]), :(x[8])]][:id] == 5 -# @test alpine.nonconvex_terms[[:(x[3]), :(x[9])]][:id] == 6 -# @test alpine.nonconvex_terms[[:(x[4]), :(x[10])]][:id] == 7 -# @test alpine.nonconvex_terms[[:(x[2]), :(x[2])]][:id] == 8 -# @test alpine.nonconvex_terms[[:(x[1]), :(x[12])]][:id] == 9 -# @test alpine.nonconvex_terms[[:(x[3]), :(x[13])]][:id] == 10 -# @test alpine.nonconvex_terms[[:(x[4]), :(x[14])]][:id] == 11 -# @test alpine.nonconvex_terms[[:(x[3]), :(x[3])]][:id] == 12 -# @test alpine.nonconvex_terms[[:(x[5]), :(x[16])]][:id] == 13 -# @test alpine.nonconvex_terms[[:(x[4]), :(x[17])]][:id] == 14 -# @test alpine.nonconvex_terms[[:(x[4]), :(x[4])]][:id] == 15 -# @test alpine.nonconvex_terms[[:(x[6]), :(x[19])]][:id] == 16 -# @test alpine.nonconvex_terms[[:(x[8]), :(x[12])]][:id] == 17 -# @test alpine.nonconvex_terms[[:(x[21]), :(x[16])]][:id] == 18 -# @test alpine.nonconvex_terms[[:(x[22]), :(x[19])]][:id] == 19 -# end - -# @testset "Expression Parsing || part7" begin -# m = Model( -# optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "log_level" => 100, -# ), -# ) -# @variable(m, x[1:4] >= 0) - -# @NLconstraint(m, x[1] * x[2] * x[3] * x[4] >= 1) -# @NLconstraint(m, x[1]^2 * x[2] * x[3] * x[4] >= 1) -# @NLconstraint(m, x[1] * x[2]^2 * x[3] * x[4] >= 1) -# @NLconstraint(m, x[1] * x[2] * x[3]^2 * x[4]^2 >= 1) -# @NLconstraint(m, x[1] * x[2]^2 * x[3]^2 * x[4] >= 1) -# @NLconstraint(m, x[1]^2 * x[2] * x[3] * x[4]^2 >= 1) -# @NLconstraint(m, x[1]^2 * x[2]^2 * x[3]^2 * x[4]^2 >= 1) - -# alpine = _build(m) - -# @test alpine.bounding_constr_expr_mip[1] == :(x[5] - 1.0 >= 0.0) -# @test alpine.bounding_constr_expr_mip[2] == :(x[7] - 1.0 >= 0.0) -# @test alpine.bounding_constr_expr_mip[3] == :(x[9] - 1.0 >= 0.0) -# @test alpine.bounding_constr_expr_mip[4] == :(x[12] - 1.0 >= 0.0) -# @test alpine.bounding_constr_expr_mip[5] == :(x[13] - 1.0 >= 0.0) -# @test alpine.bounding_constr_expr_mip[6] == :(x[14] - 1.0 >= 0.0) -# @test alpine.bounding_constr_expr_mip[7] == :(x[15] - 1.0 >= 0.0) - -# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2]), :(x[3]), :(x[4])]) #5 -# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[1])]) #6 -# @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[3]), :(x[4]), :(x[6])]) #7 -# @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[2])]) #8 -# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[3]), :(x[4]), :(x[8])]) #9 -# @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[3])]) #10 -# @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[4])]) #11 -# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2]), :(x[10]), :(x[11])]) #12 -# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[4]), :(x[8]), :(x[10])]) #13 -# @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[3]), :(x[6]), :(x[11])]) #14 -# @test haskey(alpine.nonconvex_terms, [:(x[6]), :(x[8]), :(x[10]), :(x[11])]) #15 - -# @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:id] == 1 #5 -# @test alpine.nonconvex_terms[[:(x[1]), :(x[1])]][:id] == 2 #6 -# @test alpine.nonconvex_terms[[:(x[2]), :(x[3]), :(x[4]), :(x[6])]][:id] == 3 #7 -# @test alpine.nonconvex_terms[[:(x[2]), :(x[2])]][:id] == 4 #8 -# @test alpine.nonconvex_terms[[:(x[1]), :(x[3]), :(x[4]), :(x[8])]][:id] == 5 #9 -# @test alpine.nonconvex_terms[[:(x[3]), :(x[3])]][:id] == 6 #10 -# @test alpine.nonconvex_terms[[:(x[4]), :(x[4])]][:id] == 7 #11 -# @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[10]), :(x[11])]][:id] == 8 #12 -# @test alpine.nonconvex_terms[[:(x[1]), :(x[4]), :(x[8]), :(x[10])]][:id] == 9 #13 -# @test alpine.nonconvex_terms[[:(x[2]), :(x[3]), :(x[6]), :(x[11])]][:id] == 10 #14 -# @test alpine.nonconvex_terms[[:(x[6]), :(x[8]), :(x[10]), :(x[11])]][:id] == 11 #15 -# end - -# @testset "Expression Parsing || part8" begin -# m = Model( -# optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "log_level" => 100, -# ), -# ) -# @variable(m, x[1:4] >= 0) - -# @NLconstraint(m, (x[1] * x[2] * x[3]) * x[4] >= 1) -# @NLconstraint(m, (x[1]^2 * x[2] * x[3]) * x[4] >= 1) -# @NLconstraint(m, x[1] * (x[2]^2 * x[3]) * x[4] >= 1) -# @NLconstraint(m, x[1] * (x[2] * x[3]^2) * x[4] >= 1) -# @NLconstraint(m, (x[1] * x[2]^2) * x[3] * x[4] >= 1) -# @NLconstraint(m, (x[1] * x[2]) * x[3]^2 * x[4] >= 1) -# @NLconstraint(m, (x[1] * x[2]) * x[3] * x[4]^2 >= 1) -# @NLconstraint(m, (x[1] * x[2]) * x[3]^2 * x[4]^2 >= 1) -# @NLconstraint(m, (x[1]^2 * x[2]^2 * x[3]^2) * x[4]^2 >= 1) - -# alpine = _build(m) - -# @test alpine.bounding_constr_expr_mip[1] == :(x[6] - 1.0 >= 0.0) -# @test alpine.bounding_constr_expr_mip[2] == :(x[9] - 1.0 >= 0.0) -# @test alpine.bounding_constr_expr_mip[3] == :(x[12] - 1.0 >= 0.0) -# @test alpine.bounding_constr_expr_mip[4] == :(x[15] - 1.0 >= 0.0) -# @test alpine.bounding_constr_expr_mip[5] == :(x[17] - 1.0 >= 0.0) -# @test alpine.bounding_constr_expr_mip[6] == :(x[19] - 1.0 >= 0.0) -# @test alpine.bounding_constr_expr_mip[7] == :(x[21] - 1.0 >= 0.0) -# @test alpine.bounding_constr_expr_mip[8] == :(x[22] - 1.0 >= 0.0) -# @test alpine.bounding_constr_expr_mip[9] == :(x[24] - 1.0 >= 0.0) - -# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2]), :(x[3])]) #5 -# @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[5])]) #6 -# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[1])]) #7 -# @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[3]), :(x[7])]) #8 -# @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[8])]) #9 -# @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[2])]) #10 -# @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[10])]) #11 -# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[4]), :(x[11])]) #12 -# @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[3])]) #13 -# @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[13])]) #14 -# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[4]), :(x[14])]) #15 -# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[10])]) #16 -# @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[4]), :(x[16])]) #17 -# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2])]) #18 -# @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[18]), :(x[13])]) #19 -# @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[4])]) #20 -# @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[18]), :(x[20])]) #21 -# @test haskey(alpine.nonconvex_terms, [:(x[18]), :(x[13]), :(x[20])]) #22 -# @test haskey(alpine.nonconvex_terms, [:(x[7]), :(x[10]), :(x[13])]) #23 -# @test haskey(alpine.nonconvex_terms, [:(x[23]), :(x[20])]) #24 -# end - -# @testset "Expression Parsing || Convex" begin -# @testset "Convex Parsing :: PART I" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "log_level" => 100, -# ) -# m = convex_test(solver = test_solver) - -# alpine = _build(m) - -# @test alpine.num_constr_convex == 21 - -# # 0 : OBJ -# @test alpine.obj_structure == :convex -# @test alpine.nonlinear_constrs[0][:expr_orig] == :objective -# @test alpine.nonlinear_constrs[0][:convex_type] == :convexA -# @test alpine.nonlinear_constrs[0][:convexified] == false - -# @test alpine.bounding_obj_mip[:sense] === nothing -# @test alpine.bounding_obj_mip[:coefs] == [1.0, 1.0] -# @test alpine.bounding_obj_mip[:vars] == [:(x[1]), :(x[3])] -# @test alpine.bounding_obj_mip[:rhs] == 0.0 -# @test alpine.bounding_obj_mip[:powers] == [2, 2] -# @test alpine.bounding_obj_mip[:cnt] == 2 - -# # 1 -# @test alpine.constr_structure[1] == :convex -# @test alpine.nonlinear_constrs[1][:expr_orig] == :constraints -# @test alpine.nonlinear_constrs[1][:convex_type] == :convexA -# @test alpine.nonlinear_constrs[1][:convexified] == false -# @test alpine.bounding_constr_mip[1][:sense] == :(<=) -# @test alpine.bounding_constr_mip[1][:coefs] == [3.0, 4.0] -# @test alpine.bounding_constr_mip[1][:vars] == [:(x[1]), :(x[2])] -# @test alpine.bounding_constr_mip[1][:rhs] == 25.0 -# @test alpine.bounding_constr_mip[1][:powers] == [2, 2] -# @test alpine.bounding_constr_mip[1][:cnt] == 2 - -# # 2 -# @test alpine.constr_structure[2] == :convex -# @test alpine.nonlinear_constrs[2][:expr_orig] == :constraints -# @test alpine.nonlinear_constrs[2][:convex_type] == :convexA -# @test alpine.nonlinear_constrs[2][:convexified] == false -# @test alpine.bounding_constr_mip[2][:sense] == :(<=) -# @test alpine.bounding_constr_mip[2][:coefs] == [3.0, 4.0] -# @test alpine.bounding_constr_mip[2][:vars] == [:(x[1]), :(x[2])] -# @test alpine.bounding_constr_mip[2][:rhs] == 25.0 -# @test alpine.bounding_constr_mip[2][:powers] == [2, 2] -# @test alpine.bounding_constr_mip[2][:cnt] == 2 - -# # 4 -# @test alpine.constr_structure[4] == :convex -# @test alpine.nonlinear_constrs[4][:expr_orig] == :constraints -# @test alpine.nonlinear_constrs[4][:convex_type] == :convexA -# @test alpine.nonlinear_constrs[4][:convexified] == false -# @test alpine.bounding_constr_mip[4][:sense] == :(<=) -# @test alpine.bounding_constr_mip[4][:coefs] == [3.0, 4.0] -# @test alpine.bounding_constr_mip[4][:vars] == [:(x[1]), :(x[2])] -# @test alpine.bounding_constr_mip[4][:rhs] == 10.0 -# @test alpine.bounding_constr_mip[4][:powers] == [2, 2] -# @test alpine.bounding_constr_mip[4][:cnt] == 2 - -# # 5 -# @test alpine.constr_structure[5] == :convex -# @test alpine.nonlinear_constrs[5][:expr_orig] == :constraints -# @test alpine.nonlinear_constrs[5][:convex_type] == :convexA -# @test alpine.nonlinear_constrs[5][:convexified] == :false -# @test alpine.bounding_constr_mip[5][:sense] == :(<=) -# @test alpine.bounding_constr_mip[5][:coefs] == [3.0, 4.0, 6.0] -# @test alpine.bounding_constr_mip[5][:vars] == [:(x[1]), :(x[2]), :(x[3])] -# @test alpine.bounding_constr_mip[5][:rhs] == 10.0 -# @test alpine.bounding_constr_mip[5][:powers] == [2, 2, 2] -# @test alpine.bounding_constr_mip[5][:cnt] == 3 - -# # 6 -# @test alpine.constr_structure[6] == :convex -# @test alpine.nonlinear_constrs[6][:expr_orig] == :constraints -# @test alpine.nonlinear_constrs[6][:convex_type] == :convexC -# @test alpine.nonlinear_constrs[6][:convexified] == :false -# @test alpine.bounding_constr_mip[6][:sense] == :(<=) -# @test alpine.bounding_constr_mip[6][:coefs] == [3.0, 4.0, 5.0] -# @test alpine.bounding_constr_mip[6][:vars] == [:(x[1]), :(x[2]), :(x[5])] -# @test alpine.bounding_constr_mip[6][:rhs] == 100.0 -# @test alpine.bounding_constr_mip[6][:powers] == [0.5, 0.5, 0.5] -# @test alpine.bounding_constr_mip[6][:cnt] == 3 - -# # 7 -# @test alpine.constr_structure[7] == :convex -# @test alpine.nonlinear_constrs[7][:expr_orig] == :constraints -# @test alpine.nonlinear_constrs[7][:convex_type] == :convexC -# @test alpine.nonlinear_constrs[7][:convexified] == :false -# @test alpine.bounding_constr_mip[7][:sense] == :(>=) -# @test alpine.bounding_constr_mip[7][:coefs] == [-3.0, -4.0] -# @test alpine.bounding_constr_mip[7][:vars] == [:(x[1]), :(x[2])] -# @test alpine.bounding_constr_mip[7][:rhs] == -100.0 -# @test alpine.bounding_constr_mip[7][:powers] == [0.5, 0.5] -# @test alpine.bounding_constr_mip[7][:cnt] == 2 - -# # 8 -# @test alpine.constr_structure[8] == :convex -# @test alpine.nonlinear_constrs[8][:expr_orig] == :constraints -# @test alpine.nonlinear_constrs[8][:convex_type] == :convexB -# @test alpine.nonlinear_constrs[8][:convexified] == :false -# @test alpine.bounding_constr_mip[8][:sense] == :(<=) -# @test alpine.bounding_constr_mip[8][:coefs] == [3.0, 1.0, 5.0] -# @test alpine.bounding_constr_mip[8][:vars] == [:(x[1]), :(x[2]), :(x[3])] -# @test alpine.bounding_constr_mip[8][:rhs] == 200.0 -# @test alpine.bounding_constr_mip[8][:powers] == [3.0, 3.0, 3.0] -# @test alpine.bounding_constr_mip[8][:cnt] == 3 - -# # 9 -# @test alpine.constr_structure[9] == :convex -# @test alpine.nonlinear_constrs[9][:expr_orig] == :constraints -# @test alpine.nonlinear_constrs[9][:convex_type] == :convexB -# @test alpine.nonlinear_constrs[9][:convexified] == :false -# @test alpine.bounding_constr_mip[9][:sense] == :(<=) -# @test alpine.bounding_constr_mip[9][:coefs] == [1.0, 1.0, 1.0, 100.0] -# @test alpine.bounding_constr_mip[9][:vars] == [:(x[1]), :(x[2]), :(x[3]), :(x[4])] -# @test alpine.bounding_constr_mip[9][:rhs] == 200.0 -# @test alpine.bounding_constr_mip[9][:powers] == [3, 3, 3, 3] -# @test alpine.bounding_constr_mip[9][:cnt] == 4 - -# # 11 -# @test alpine.constr_structure[11] == :convex -# @test alpine.nonlinear_constrs[11][:expr_orig] == :constraints -# @test alpine.nonlinear_constrs[11][:convex_type] == :convexA -# @test alpine.nonlinear_constrs[11][:convexified] == :false -# @test alpine.bounding_constr_mip[11][:sense] == :(<=) -# @test alpine.bounding_constr_mip[11][:coefs] == [3.0, 4.0] -# @test alpine.bounding_constr_mip[11][:vars] == [:(x[1]), :(x[2])] -# @test alpine.bounding_constr_mip[11][:rhs] == 25.0 -# @test alpine.bounding_constr_mip[11][:powers] == [2, 2] -# @test alpine.bounding_constr_mip[11][:cnt] == 2 - -# # 14 -# @test alpine.constr_structure[14] == :convex -# @test alpine.nonlinear_constrs[14][:expr_orig] == :constraints -# @test alpine.nonlinear_constrs[14][:convex_type] == :convexA -# @test alpine.nonlinear_constrs[14][:convexified] == :false -# @test alpine.bounding_constr_mip[14][:sense] == :(<=) -# @test alpine.bounding_constr_mip[14][:coefs] == [3.0, 5.0] -# @test alpine.bounding_constr_mip[14][:vars] == [:(x[1]), :(x[2])] -# @test alpine.bounding_constr_mip[14][:rhs] == 25.0 -# @test alpine.bounding_constr_mip[14][:powers] == [2, 2] -# @test alpine.bounding_constr_mip[14][:cnt] == 2 - -# # 15 -# @test alpine.constr_structure[15] == :convex -# @test alpine.nonlinear_constrs[15][:expr_orig] == :constraints -# @test alpine.nonlinear_constrs[15][:convex_type] == :convexA -# @test alpine.nonlinear_constrs[15][:convexified] == :false -# @test alpine.bounding_constr_mip[15][:sense] == :(<=) -# @test alpine.bounding_constr_mip[15][:coefs] == [3.0, 5.0, 1.0] -# @test alpine.bounding_constr_mip[15][:vars] == [:(x[1]), :(x[2]), :(x[4])] -# @test alpine.bounding_constr_mip[15][:rhs] == 25.0 -# @test alpine.bounding_constr_mip[15][:powers] == [2, 2, 2] -# @test alpine.bounding_constr_mip[15][:cnt] == 3 - -# # 19 -# @test alpine.constr_structure[19] == :convex -# @test alpine.nonlinear_constrs[19][:expr_orig] == :constraints -# @test alpine.nonlinear_constrs[19][:convex_type] == :convexA -# @test alpine.nonlinear_constrs[19][:convexified] == :false -# @test alpine.bounding_constr_mip[19][:sense] == :(<=) -# @test alpine.bounding_constr_mip[19][:coefs] == [3.0, 16.0] -# @test alpine.bounding_constr_mip[19][:vars] == [:(x[1]), :(x[2])] -# @test alpine.bounding_constr_mip[19][:rhs] == 40.0 -# @test alpine.bounding_constr_mip[19][:powers] == [2, 2] -# @test alpine.bounding_constr_mip[19][:cnt] == 2 - -# # 22 -# @test alpine.constr_structure[22] == :convex -# @test alpine.nonlinear_constrs[22][:expr_orig] == :constraints -# @test alpine.nonlinear_constrs[22][:convex_type] == :convexA -# @test alpine.nonlinear_constrs[22][:convexified] == :false -# @test alpine.bounding_constr_mip[22][:sense] == :(<=) -# @test alpine.bounding_constr_mip[22][:coefs] == [3.0, 4.0, 5.0, 6.0] -# @test alpine.bounding_constr_mip[22][:vars] == -# [:(x[1]), :(x[2]), :(x[3]), :(x[4])] -# @test alpine.bounding_constr_mip[22][:rhs] == 15.0 -# @test alpine.bounding_constr_mip[22][:powers] == [2, 2, 2, 2] -# @test alpine.bounding_constr_mip[22][:cnt] == 4 - -# # 25 -# @test alpine.constr_structure[25] == :convex -# @test alpine.nonlinear_constrs[25][:expr_orig] == :constraints -# @test alpine.nonlinear_constrs[25][:convex_type] == :convexA -# @test alpine.nonlinear_constrs[25][:convexified] == :false -# @test alpine.bounding_constr_mip[25][:sense] == :(<=) -# @test alpine.bounding_constr_mip[25][:coefs] == [1.0, 1.0, 1.0, 1.0, 1.0] -# @test alpine.bounding_constr_mip[25][:vars] == -# [:(x[1]), :(x[2]), :(x[3]), :(x[4]), :(x[5])] -# @test alpine.bounding_constr_mip[25][:rhs] == 99999.0 -# @test alpine.bounding_constr_mip[25][:powers] == [2, 2, 2, 2, 2] -# @test alpine.bounding_constr_mip[25][:cnt] == 5 - -# # 26 -# @test alpine.constr_structure[26] == :convex -# @test alpine.nonlinear_constrs[26][:expr_orig] == :constraints -# @test alpine.nonlinear_constrs[26][:convex_type] == :convexA -# @test alpine.nonlinear_constrs[26][:convexified] == :false -# @test alpine.bounding_constr_mip[26][:sense] == :(<=) -# @test alpine.bounding_constr_mip[26][:coefs] == [3.0, 4.0] -# @test alpine.bounding_constr_mip[26][:vars] == [:(x[1]), :(x[2])] -# @test alpine.bounding_constr_mip[26][:rhs] == 200.0 -# @test alpine.bounding_constr_mip[26][:powers] == [4, 4] -# @test alpine.bounding_constr_mip[26][:cnt] == 2 -# end -# end - -# @testset "Expression Prasing || Linear Lifting" begin -# @testset "Expression Parsing || Linear Lifting || nlp2" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "partition_scaling_factor" => 8, -# "log_level" => 100, -# ) - -# m = nlp2(solver = test_solver) - -# alpine = _build(m) - -# @test length(alpine.linear_terms) == 2 -# @test length(alpine.nonconvex_terms) == 4 - -# lk = Vector{Any}(undef, 2) -# lk[1] = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, -1.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3)])), -# ) -# lk[2] = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, -2.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6)])), -# ) - -# @test length(keys(alpine.linear_terms)) == 2 -# yids = [4, 7] -# for i in 1:length(keys(alpine.linear_terms)) -# for j in keys(alpine.linear_terms) -# if alpine.linear_terms[j][:id] == i -# @test j == lk[i] -# @test j[:sign] == :+ -# @test j[:scalar] == lk[i][:scalar] -# @test j[:coef_var] == lk[i][:coef_var] -# @test alpine.linear_terms[j][:y_idx] == yids[i] -# end -# end -# end - -# @test haskey(alpine.linear_terms, lk[1]) -# @test haskey(alpine.linear_terms, lk[2]) - -# @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[2])]) -# @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[4])]) -# @test haskey(alpine.nonconvex_terms, [:(x[7]), :(x[7])]) -# @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[1])]) -# @test alpine.nonconvex_terms[[:(x[1]), :(x[1])]][:id] == 1 -# @test alpine.nonconvex_terms[[:(x[2]), :(x[2])]][:id] == 3 -# @test alpine.nonconvex_terms[[:(x[4]), :(x[4])]][:id] == 2 -# @test alpine.nonconvex_terms[[:(x[7]), :(x[7])]][:id] == 4 -# @test alpine.nonconvex_terms[[:(x[1]), :(x[1])]][:lifted_var_ref].args[2] == 3 -# @test alpine.nonconvex_terms[[:(x[2]), :(x[2])]][:lifted_var_ref].args[2] == 6 -# @test alpine.nonconvex_terms[[:(x[4]), :(x[4])]][:lifted_var_ref].args[2] == 5 -# @test alpine.nonconvex_terms[[:(x[7]), :(x[7])]][:lifted_var_ref].args[2] == 8 -# end - -# @testset "Expression Parsing || Linear Lifting || general" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "log_level" => 100, -# ) - -# m = basic_linear_lift(solver = test_solver) - -# alpine = _build(m) # Setup internal model - -# lk = Vector{Any}(undef, 5) -# lk[1] = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1), (-1.0, 2)])), -# ) -# lk[2] = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(3.0, 2), (-1.0, 3)])), -# ) -# lk[3] = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1), (1.0, 3)])), -# ) -# lk[4] = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 2), (1.0, 1)])), -# ) -# lk[5] = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 3.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 2), (1.0, 1), (1.0, 3)])), -# ) - -# @test length(keys(alpine.linear_terms)) == 5 -# yids = [8, 9, 12, 14, 16] -# for i in 1:length(keys(alpine.linear_terms)) -# for j in keys(alpine.linear_terms) -# if alpine.linear_terms[j][:id] == i -# @test j == lk[i] -# @test j[:sign] == :+ -# @test j[:scalar] == lk[i][:scalar] -# @test j[:coef_var] == lk[i][:coef_var] -# @test alpine.linear_terms[j][:y_idx] == yids[i] -# end -# end -# end - -# nlk1 = [:(x[8]), :(x[9]), :(x[12])] -# nlk2 = [:(x[2]), :(x[2])] -# nlk3 = [:(x[2]), :(x[3])] -# nlk4 = [:(x[8]), :(x[8])] -# nlk5 = [:(x[1]), :(x[3])] -# nlk6 = [:(x[8]), :(x[9])] -# nlk7 = [:(x[1]), :(x[2])] -# nlk8 = [:(x[16]), :(x[15])] -# nlk9 = [:(x[14]), :(x[14])] - -# @test alpine.nonconvex_terms[nlk1][:id] == 7 -# @test alpine.nonconvex_terms[nlk2][:id] == 3 -# @test alpine.nonconvex_terms[nlk3][:id] == 4 -# @test alpine.nonconvex_terms[nlk4][:id] == 6 -# @test alpine.nonconvex_terms[nlk5][:id] == 2 -# @test alpine.nonconvex_terms[nlk6][:id] == 5 -# @test alpine.nonconvex_terms[nlk7][:id] == 1 -# @test alpine.nonconvex_terms[nlk8][:id] == 9 -# @test alpine.nonconvex_terms[nlk9][:id] == 8 - -# @test alpine.nonconvex_terms[nlk1][:lifted_var_ref].args[2] == 13 -# @test alpine.nonconvex_terms[nlk2][:lifted_var_ref].args[2] == 6 -# @test alpine.nonconvex_terms[nlk3][:lifted_var_ref].args[2] == 7 -# @test alpine.nonconvex_terms[nlk4][:lifted_var_ref].args[2] == 11 -# @test alpine.nonconvex_terms[nlk5][:lifted_var_ref].args[2] == 5 -# @test alpine.nonconvex_terms[nlk6][:lifted_var_ref].args[2] == 10 -# @test alpine.nonconvex_terms[nlk7][:lifted_var_ref].args[2] == 4 -# @test alpine.nonconvex_terms[nlk8][:lifted_var_ref].args[2] == 17 -# @test alpine.nonconvex_terms[nlk9][:lifted_var_ref].args[2] == 15 - -# @test alpine.nonconvex_terms[nlk1][:nonlinear_type] == :MULTILINEAR -# @test alpine.nonconvex_terms[nlk2][:nonlinear_type] == :MONOMIAL -# @test alpine.nonconvex_terms[nlk3][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[nlk4][:nonlinear_type] == :MONOMIAL -# @test alpine.nonconvex_terms[nlk5][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[nlk6][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[nlk7][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[nlk8][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[nlk9][:nonlinear_type] == :MONOMIAL - -# @test alpine.nonconvex_terms[nlk1][:var_idxs] == [8, 9, 12] -# @test alpine.nonconvex_terms[nlk2][:var_idxs] == [2, 2] -# @test alpine.nonconvex_terms[nlk3][:var_idxs] == [2, 3] -# @test alpine.nonconvex_terms[nlk4][:var_idxs] == [8] -# @test alpine.nonconvex_terms[nlk5][:var_idxs] == [1, 3] -# @test alpine.nonconvex_terms[nlk6][:var_idxs] == [8, 9] -# @test alpine.nonconvex_terms[nlk7][:var_idxs] == [1, 2] -# @test alpine.nonconvex_terms[nlk8][:var_idxs] == [16, 15] -# @test alpine.nonconvex_terms[nlk9][:var_idxs] == [14] -# end - -# @testset "Expression Parsing || Linear Lifting || brainpc3" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "partition_scaling_factor" => 8, -# "log_level" => 100, -# ) - -# m = brainpc3(solver = test_solver) - -# alpine = _build(m) - -# @test alpine.nonconvex_terms[Expr[:(x[6912]), :(x[6912])]][:y_idx] == 6913 -# @test alpine.nonconvex_terms[Expr[:(x[6912]), :(x[6912])]][:id] == 2 -# @test alpine.nonconvex_terms[Expr[:(x[6912]), :(x[6912])]][:lifted_constr_ref] == -# :(x[6913] == (*)(x[6912])) -# @test alpine.nonconvex_terms[Expr[:(x[6912]), :(x[6912])]][:nonlinear_type] == -# :MONOMIAL -# @test alpine.nonconvex_terms[Expr[:(x[6912]), :(x[6912])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6912]), :(x[6912])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6969])]][:y_idx] == 6970 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6969])]][:id] == 25 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6969])]][:lifted_constr_ref] == -# :(x[6970] == x[6903] * x[6969]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6969])]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6969])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6969])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6914])]][:y_idx] == 6915 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6914])]][:id] == 3 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6914])]][:lifted_constr_ref] == -# :(x[6915] == x[6903] * x[6914]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6914])]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6914])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6914])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6919])]][:y_idx] == 6920 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6919])]][:id] == 5 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6919])]][:lifted_constr_ref] == -# :(x[6920] == x[6903] * x[6919]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6919])]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6919])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6919])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6927]), :(x[6927])]][:y_idx] == 6928 -# @test alpine.nonconvex_terms[Expr[:(x[6927]), :(x[6927])]][:id] == 8 -# @test alpine.nonconvex_terms[Expr[:(x[6927]), :(x[6927])]][:lifted_constr_ref] == -# :(x[6928] == (*)(x[6927])) -# @test alpine.nonconvex_terms[Expr[:(x[6927]), :(x[6927])]][:nonlinear_type] == -# :MONOMIAL -# @test alpine.nonconvex_terms[Expr[:(x[6927]), :(x[6927])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6927]), :(x[6927])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6952]), :(x[6952])]][:y_idx] == 6953 -# @test alpine.nonconvex_terms[Expr[:(x[6952]), :(x[6952])]][:id] == 18 -# @test alpine.nonconvex_terms[Expr[:(x[6952]), :(x[6952])]][:lifted_constr_ref] == -# :(x[6953] == (*)(x[6952])) -# @test alpine.nonconvex_terms[Expr[:(x[6952]), :(x[6952])]][:nonlinear_type] == -# :MONOMIAL -# @test alpine.nonconvex_terms[Expr[:(x[6952]), :(x[6952])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6952]), :(x[6952])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6962]), :(x[6962])]][:y_idx] == 6963 -# @test alpine.nonconvex_terms[Expr[:(x[6962]), :(x[6962])]][:id] == 22 -# @test alpine.nonconvex_terms[Expr[:(x[6962]), :(x[6962])]][:lifted_constr_ref] == -# :(x[6963] == (*)(x[6962])) -# @test alpine.nonconvex_terms[Expr[:(x[6962]), :(x[6962])]][:nonlinear_type] == -# :MONOMIAL -# @test alpine.nonconvex_terms[Expr[:(x[6962]), :(x[6962])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6962]), :(x[6962])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6974])]][:y_idx] == 6975 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6974])]][:id] == 27 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6974])]][:lifted_constr_ref] == -# :(x[6975] == x[6903] * x[6974]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6974])]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6974])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6974])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6934])]][:y_idx] == 6935 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6934])]][:id] == 11 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6934])]][:lifted_constr_ref] == -# :(x[6935] == x[6903] * x[6934]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6934])]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6934])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6934])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6959])]][:y_idx] == 6960 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6959])]][:id] == 21 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6959])]][:lifted_constr_ref] == -# :(x[6960] == x[6903] * x[6959]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6959])]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6959])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6959])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7014])]][:y_idx] == 7015 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7014])]][:id] == 43 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7014])]][:lifted_constr_ref] == -# :(x[7015] == x[6903] * x[7014]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7014])]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7014])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7014])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6939])]][:y_idx] == 6940 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6939])]][:id] == 13 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6939])]][:lifted_constr_ref] == -# :(x[6940] == x[6903] * x[6939]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6939])]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6939])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6939])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[7017]), :(x[7017])]][:y_idx] == 7018 -# @test alpine.nonconvex_terms[Expr[:(x[7017]), :(x[7017])]][:id] == 44 -# @test alpine.nonconvex_terms[Expr[:(x[7017]), :(x[7017])]][:lifted_constr_ref] == -# :(x[7018] == (*)(x[7017])) -# @test alpine.nonconvex_terms[Expr[:(x[7017]), :(x[7017])]][:nonlinear_type] == -# :MONOMIAL -# @test alpine.nonconvex_terms[Expr[:(x[7017]), :(x[7017])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[7017]), :(x[7017])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6929])]][:y_idx] == 6930 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6929])]][:id] == 9 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6929])]][:lifted_constr_ref] == -# :(x[6930] == x[6903] * x[6929]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6929])]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6929])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6929])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[7012]), :(x[7012])]][:y_idx] == 7013 -# @test alpine.nonconvex_terms[Expr[:(x[7012]), :(x[7012])]][:id] == 42 -# @test alpine.nonconvex_terms[Expr[:(x[7012]), :(x[7012])]][:lifted_constr_ref] == -# :(x[7013] == (*)(x[7012])) -# @test alpine.nonconvex_terms[Expr[:(x[7012]), :(x[7012])]][:nonlinear_type] == -# :MONOMIAL -# @test alpine.nonconvex_terms[Expr[:(x[7012]), :(x[7012])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[7012]), :(x[7012])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6947]), :(x[6947])]][:y_idx] == 6948 -# @test alpine.nonconvex_terms[Expr[:(x[6947]), :(x[6947])]][:id] == 16 -# @test alpine.nonconvex_terms[Expr[:(x[6947]), :(x[6947])]][:lifted_constr_ref] == -# :(x[6948] == (*)(x[6947])) -# @test alpine.nonconvex_terms[Expr[:(x[6947]), :(x[6947])]][:nonlinear_type] == -# :MONOMIAL -# @test alpine.nonconvex_terms[Expr[:(x[6947]), :(x[6947])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6947]), :(x[6947])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[7032]), :(x[7032])]][:y_idx] == 7033 -# @test alpine.nonconvex_terms[Expr[:(x[7032]), :(x[7032])]][:id] == 50 -# @test alpine.nonconvex_terms[Expr[:(x[7032]), :(x[7032])]][:lifted_constr_ref] == -# :(x[7033] == (*)(x[7032])) -# @test alpine.nonconvex_terms[Expr[:(x[7032]), :(x[7032])]][:nonlinear_type] == -# :MONOMIAL -# @test alpine.nonconvex_terms[Expr[:(x[7032]), :(x[7032])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[7032]), :(x[7032])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6997]), :(x[6997])]][:y_idx] == 6998 -# @test alpine.nonconvex_terms[Expr[:(x[6997]), :(x[6997])]][:id] == 36 -# @test alpine.nonconvex_terms[Expr[:(x[6997]), :(x[6997])]][:lifted_constr_ref] == -# :(x[6998] == (*)(x[6997])) -# @test alpine.nonconvex_terms[Expr[:(x[6997]), :(x[6997])]][:nonlinear_type] == -# :MONOMIAL -# @test alpine.nonconvex_terms[Expr[:(x[6997]), :(x[6997])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6997]), :(x[6997])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[7027]), :(x[7027])]][:y_idx] == 7028 -# @test alpine.nonconvex_terms[Expr[:(x[7027]), :(x[7027])]][:id] == 48 -# @test alpine.nonconvex_terms[Expr[:(x[7027]), :(x[7027])]][:lifted_constr_ref] == -# :(x[7028] == (*)(x[7027])) -# @test alpine.nonconvex_terms[Expr[:(x[7027]), :(x[7027])]][:nonlinear_type] == -# :MONOMIAL -# @test alpine.nonconvex_terms[Expr[:(x[7027]), :(x[7027])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[7027]), :(x[7027])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[7037]), :(x[7037])]][:y_idx] == 7038 -# @test alpine.nonconvex_terms[Expr[:(x[7037]), :(x[7037])]][:id] == 52 -# @test alpine.nonconvex_terms[Expr[:(x[7037]), :(x[7037])]][:lifted_constr_ref] == -# :(x[7038] == (*)(x[7037])) -# @test alpine.nonconvex_terms[Expr[:(x[7037]), :(x[7037])]][:nonlinear_type] == -# :MONOMIAL -# @test alpine.nonconvex_terms[Expr[:(x[7037]), :(x[7037])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[7037]), :(x[7037])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[7007]), :(x[7007])]][:y_idx] == 7008 -# @test alpine.nonconvex_terms[Expr[:(x[7007]), :(x[7007])]][:id] == 40 -# @test alpine.nonconvex_terms[Expr[:(x[7007]), :(x[7007])]][:lifted_constr_ref] == -# :(x[7008] == (*)(x[7007])) -# @test alpine.nonconvex_terms[Expr[:(x[7007]), :(x[7007])]][:nonlinear_type] == -# :MONOMIAL -# @test alpine.nonconvex_terms[Expr[:(x[7007]), :(x[7007])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[7007]), :(x[7007])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6964])]][:y_idx] == 6965 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6964])]][:id] == 23 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6964])]][:lifted_constr_ref] == -# :(x[6965] == x[6903] * x[6964]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6964])]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6964])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6964])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6924])]][:y_idx] == 6925 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6924])]][:id] == 7 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6924])]][:lifted_constr_ref] == -# :(x[6925] == x[6903] * x[6924]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6924])]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6924])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6924])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6979])]][:y_idx] == 6980 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6979])]][:id] == 29 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6979])]][:lifted_constr_ref] == -# :(x[6980] == x[6903] * x[6979]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6979])]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6979])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6979])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6994])]][:y_idx] == 6995 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6994])]][:id] == 35 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6994])]][:lifted_constr_ref] == -# :(x[6995] == x[6903] * x[6994]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6994])]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6994])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6994])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6972]), :(x[6972])]][:y_idx] == 6973 -# @test alpine.nonconvex_terms[Expr[:(x[6972]), :(x[6972])]][:id] == 26 -# @test alpine.nonconvex_terms[Expr[:(x[6972]), :(x[6972])]][:lifted_constr_ref] == -# :(x[6973] == (*)(x[6972])) -# @test alpine.nonconvex_terms[Expr[:(x[6972]), :(x[6972])]][:nonlinear_type] == -# :MONOMIAL -# @test alpine.nonconvex_terms[Expr[:(x[6972]), :(x[6972])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6972]), :(x[6972])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7019])]][:y_idx] == 7020 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7019])]][:id] == 45 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7019])]][:lifted_constr_ref] == -# :(x[7020] == x[6903] * x[7019]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7019])]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7019])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7019])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6992]), :(x[6992])]][:y_idx] == 6993 -# @test alpine.nonconvex_terms[Expr[:(x[6992]), :(x[6992])]][:id] == 34 -# @test alpine.nonconvex_terms[Expr[:(x[6992]), :(x[6992])]][:lifted_constr_ref] == -# :(x[6993] == (*)(x[6992])) -# @test alpine.nonconvex_terms[Expr[:(x[6992]), :(x[6992])]][:nonlinear_type] == -# :MONOMIAL -# @test alpine.nonconvex_terms[Expr[:(x[6992]), :(x[6992])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6992]), :(x[6992])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[7002]), :(x[7002])]][:y_idx] == 7003 -# @test alpine.nonconvex_terms[Expr[:(x[7002]), :(x[7002])]][:id] == 38 -# @test alpine.nonconvex_terms[Expr[:(x[7002]), :(x[7002])]][:lifted_constr_ref] == -# :(x[7003] == (*)(x[7002])) -# @test alpine.nonconvex_terms[Expr[:(x[7002]), :(x[7002])]][:nonlinear_type] == -# :MONOMIAL -# @test alpine.nonconvex_terms[Expr[:(x[7002]), :(x[7002])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[7002]), :(x[7002])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[7022]), :(x[7022])]][:y_idx] == 7023 -# @test alpine.nonconvex_terms[Expr[:(x[7022]), :(x[7022])]][:id] == 46 -# @test alpine.nonconvex_terms[Expr[:(x[7022]), :(x[7022])]][:lifted_constr_ref] == -# :(x[7023] == (*)(x[7022])) -# @test alpine.nonconvex_terms[Expr[:(x[7022]), :(x[7022])]][:nonlinear_type] == -# :MONOMIAL -# @test alpine.nonconvex_terms[Expr[:(x[7022]), :(x[7022])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[7022]), :(x[7022])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6908])]][:y_idx] == 6909 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6908])]][:id] == 1 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6908])]][:lifted_constr_ref] == -# :(x[6909] == x[6903] * x[6908]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6908])]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6908])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6908])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6949])]][:y_idx] == 6950 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6949])]][:id] == 17 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6949])]][:lifted_constr_ref] == -# :(x[6950] == x[6903] * x[6949]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6949])]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6949])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6949])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7004])]][:y_idx] == 7005 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7004])]][:id] == 39 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7004])]][:lifted_constr_ref] == -# :(x[7005] == x[6903] * x[7004]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7004])]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7004])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7004])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6917]), :(x[6917])]][:y_idx] == 6918 -# @test alpine.nonconvex_terms[Expr[:(x[6917]), :(x[6917])]][:id] == 4 -# @test alpine.nonconvex_terms[Expr[:(x[6917]), :(x[6917])]][:lifted_constr_ref] == -# :(x[6918] == (*)(x[6917])) -# @test alpine.nonconvex_terms[Expr[:(x[6917]), :(x[6917])]][:nonlinear_type] == -# :MONOMIAL -# @test alpine.nonconvex_terms[Expr[:(x[6917]), :(x[6917])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6917]), :(x[6917])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6937]), :(x[6937])]][:y_idx] == 6938 -# @test alpine.nonconvex_terms[Expr[:(x[6937]), :(x[6937])]][:id] == 12 -# @test alpine.nonconvex_terms[Expr[:(x[6937]), :(x[6937])]][:lifted_constr_ref] == -# :(x[6938] == (*)(x[6937])) -# @test alpine.nonconvex_terms[Expr[:(x[6937]), :(x[6937])]][:nonlinear_type] == -# :MONOMIAL -# @test alpine.nonconvex_terms[Expr[:(x[6937]), :(x[6937])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6937]), :(x[6937])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6932]), :(x[6932])]][:y_idx] == 6933 -# @test alpine.nonconvex_terms[Expr[:(x[6932]), :(x[6932])]][:id] == 10 -# @test alpine.nonconvex_terms[Expr[:(x[6932]), :(x[6932])]][:lifted_constr_ref] == -# :(x[6933] == (*)(x[6932])) -# @test alpine.nonconvex_terms[Expr[:(x[6932]), :(x[6932])]][:nonlinear_type] == -# :MONOMIAL -# @test alpine.nonconvex_terms[Expr[:(x[6932]), :(x[6932])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6932]), :(x[6932])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6989])]][:y_idx] == 6990 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6989])]][:id] == 33 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6989])]][:lifted_constr_ref] == -# :(x[6990] == x[6903] * x[6989]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6989])]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6989])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6989])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6977]), :(x[6977])]][:y_idx] == 6978 -# @test alpine.nonconvex_terms[Expr[:(x[6977]), :(x[6977])]][:id] == 28 -# @test alpine.nonconvex_terms[Expr[:(x[6977]), :(x[6977])]][:lifted_constr_ref] == -# :(x[6978] == (*)(x[6977])) -# @test alpine.nonconvex_terms[Expr[:(x[6977]), :(x[6977])]][:nonlinear_type] == -# :MONOMIAL -# @test alpine.nonconvex_terms[Expr[:(x[6977]), :(x[6977])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6977]), :(x[6977])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6987]), :(x[6987])]][:y_idx] == 6988 -# @test alpine.nonconvex_terms[Expr[:(x[6987]), :(x[6987])]][:id] == 32 -# @test alpine.nonconvex_terms[Expr[:(x[6987]), :(x[6987])]][:lifted_constr_ref] == -# :(x[6988] == (*)(x[6987])) -# @test alpine.nonconvex_terms[Expr[:(x[6987]), :(x[6987])]][:nonlinear_type] == -# :MONOMIAL -# @test alpine.nonconvex_terms[Expr[:(x[6987]), :(x[6987])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6987]), :(x[6987])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7034])]][:y_idx] == 7035 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7034])]][:id] == 51 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7034])]][:lifted_constr_ref] == -# :(x[7035] == x[6903] * x[7034]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7034])]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7034])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7034])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6967]), :(x[6967])]][:y_idx] == 6968 -# @test alpine.nonconvex_terms[Expr[:(x[6967]), :(x[6967])]][:id] == 24 -# @test alpine.nonconvex_terms[Expr[:(x[6967]), :(x[6967])]][:lifted_constr_ref] == -# :(x[6968] == (*)(x[6967])) -# @test alpine.nonconvex_terms[Expr[:(x[6967]), :(x[6967])]][:nonlinear_type] == -# :MONOMIAL -# @test alpine.nonconvex_terms[Expr[:(x[6967]), :(x[6967])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6967]), :(x[6967])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6957]), :(x[6957])]][:y_idx] == 6958 -# @test alpine.nonconvex_terms[Expr[:(x[6957]), :(x[6957])]][:id] == 20 -# @test alpine.nonconvex_terms[Expr[:(x[6957]), :(x[6957])]][:lifted_constr_ref] == -# :(x[6958] == (*)(x[6957])) -# @test alpine.nonconvex_terms[Expr[:(x[6957]), :(x[6957])]][:nonlinear_type] == -# :MONOMIAL -# @test alpine.nonconvex_terms[Expr[:(x[6957]), :(x[6957])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6957]), :(x[6957])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7009])]][:y_idx] == 7010 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7009])]][:id] == 41 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7009])]][:lifted_constr_ref] == -# :(x[7010] == x[6903] * x[7009]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7009])]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7009])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7009])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6942]), :(x[6942])]][:y_idx] == 6943 -# @test alpine.nonconvex_terms[Expr[:(x[6942]), :(x[6942])]][:id] == 14 -# @test alpine.nonconvex_terms[Expr[:(x[6942]), :(x[6942])]][:lifted_constr_ref] == -# :(x[6943] == (*)(x[6942])) -# @test alpine.nonconvex_terms[Expr[:(x[6942]), :(x[6942])]][:nonlinear_type] == -# :MONOMIAL -# @test alpine.nonconvex_terms[Expr[:(x[6942]), :(x[6942])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6942]), :(x[6942])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6982]), :(x[6982])]][:y_idx] == 6983 -# @test alpine.nonconvex_terms[Expr[:(x[6982]), :(x[6982])]][:id] == 30 -# @test alpine.nonconvex_terms[Expr[:(x[6982]), :(x[6982])]][:lifted_constr_ref] == -# :(x[6983] == (*)(x[6982])) -# @test alpine.nonconvex_terms[Expr[:(x[6982]), :(x[6982])]][:nonlinear_type] == -# :MONOMIAL -# @test alpine.nonconvex_terms[Expr[:(x[6982]), :(x[6982])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6982]), :(x[6982])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6999])]][:y_idx] == 7000 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6999])]][:id] == 37 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6999])]][:lifted_constr_ref] == -# :(x[7000] == x[6903] * x[6999]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6999])]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6999])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6999])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6944])]][:y_idx] == 6945 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6944])]][:id] == 15 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6944])]][:lifted_constr_ref] == -# :(x[6945] == x[6903] * x[6944]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6944])]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6944])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6944])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7024])]][:y_idx] == 7025 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7024])]][:id] == 47 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7024])]][:lifted_constr_ref] == -# :(x[7025] == x[6903] * x[7024]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7024])]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7024])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7024])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6954])]][:y_idx] == 6955 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6954])]][:id] == 19 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6954])]][:lifted_constr_ref] == -# :(x[6955] == x[6903] * x[6954]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6954])]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6954])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6954])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6922]), :(x[6922])]][:y_idx] == 6923 -# @test alpine.nonconvex_terms[Expr[:(x[6922]), :(x[6922])]][:id] == 6 -# @test alpine.nonconvex_terms[Expr[:(x[6922]), :(x[6922])]][:lifted_constr_ref] == -# :(x[6923] == (*)(x[6922])) -# @test alpine.nonconvex_terms[Expr[:(x[6922]), :(x[6922])]][:nonlinear_type] == -# :MONOMIAL -# @test alpine.nonconvex_terms[Expr[:(x[6922]), :(x[6922])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6922]), :(x[6922])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6984])]][:y_idx] == 6985 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6984])]][:id] == 31 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6984])]][:lifted_constr_ref] == -# :(x[6985] == x[6903] * x[6984]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6984])]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6984])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6984])]][:constr_id] == -# Set(Any[0]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7029])]][:y_idx] == 7030 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7029])]][:id] == 49 -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7029])]][:lifted_constr_ref] == -# :(x[7030] == x[6903] * x[7029]) -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7029])]][:nonlinear_type] == -# :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7029])]][:y_type] == :Cont -# @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7029])]][:constr_id] == -# Set(Any[0]) -# lk1 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6910), (-1.0, 6909)])), -# ) -# @test alpine.linear_terms[lk1][:y_idx] == 6911 -# @test alpine.linear_terms[lk1][:id] == 3 -# @test alpine.linear_terms[lk1][:y_type] == :(Cont) -# lk2 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3467), (1.0, 16)])), -# ) -# @test alpine.linear_terms[lk2][:y_idx] == 6908 -# @test alpine.linear_terms[lk2][:id] == 1 -# @test alpine.linear_terms[lk2][:y_type] == :(Cont) -# lk3 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}( -# :coef_var, -# Set(Any[(0.001548, 6903), (1.0, 7016), (1.0, 5702)]), -# ), -# ) -# @test alpine.linear_terms[lk3][:y_idx] == 7017 -# @test alpine.linear_terms[lk3][:id] == 67 -# @test alpine.linear_terms[lk3][:y_type] == :(Cont) -# lk4 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 5162), (1.0, 1711)])), -# ) -# @test alpine.linear_terms[lk4][:y_idx] == 7004 -# @test alpine.linear_terms[lk4][:id] == 59 -# @test alpine.linear_terms[lk4][:y_type] == :(Cont) -# lk5 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}( -# :coef_var, -# Set(Any[(1.0, 7021), (0.001435, 6903), (1.0, 6002)]), -# ), -# ) -# @test alpine.linear_terms[lk5][:y_idx] == 7022 -# @test alpine.linear_terms[lk5][:id] == 70 -# @test alpine.linear_terms[lk5][:y_type] == :(Cont) -# lk6 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6935), (1.0, 166)])), -# ) -# @test alpine.linear_terms[lk6][:y_idx] == 6936 -# @test alpine.linear_terms[lk6][:id] == 18 -# @test alpine.linear_terms[lk6][:y_type] == :(Cont) -# lk7 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}( -# :coef_var, -# Set(Any[(1.0, 4262), (0.00247, 6903), (1.0, 6981)]), -# ), -# ) -# @test alpine.linear_terms[lk7][:y_idx] == 6982 -# @test alpine.linear_terms[lk7][:id] == 46 -# @test alpine.linear_terms[lk7][:y_type] == :(Cont) -# lk8 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 7005), (1.0, 1711)])), -# ) -# @test alpine.linear_terms[lk8][:y_idx] == 7006 -# @test alpine.linear_terms[lk8][:id] == 60 -# @test alpine.linear_terms[lk8][:y_type] == :(Cont) -# lk9 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1951), (1.0, 5402)])), -# ) -# @test alpine.linear_terms[lk9][:y_idx] == 7009 -# @test alpine.linear_terms[lk9][:id] == 62 -# @test alpine.linear_terms[lk9][:y_type] == :(Cont) -# lk10 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 226), (-1.0, 6945)])), -# ) -# @test alpine.linear_terms[lk10][:y_idx] == 6946 -# @test alpine.linear_terms[lk10][:id] == 24 -# @test alpine.linear_terms[lk10][:y_type] == :(Cont) -# lk11 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 7030), (1.0, 3151)])), -# ) -# @test alpine.linear_terms[lk11][:y_idx] == 7031 -# @test alpine.linear_terms[lk11][:id] == 75 -# @test alpine.linear_terms[lk11][:y_type] == :(Cont) -# lk12 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}( -# :coef_var, -# Set(Any[(1.0, 6991), (1.0, 4622), (0.002066, 6903)]), -# ), -# ) -# @test alpine.linear_terms[lk12][:y_idx] == 6992 -# @test alpine.linear_terms[lk12][:id] == 52 -# @test alpine.linear_terms[lk12][:y_type] == :(Cont) -# lk13 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}( -# :coef_var, -# Set(Any[(1.0, 7026), (1.0, 6302), (0.001323, 6903)]), -# ), -# ) -# @test alpine.linear_terms[lk13][:y_idx] == 7027 -# @test alpine.linear_terms[lk13][:id] == 73 -# @test alpine.linear_terms[lk13][:y_type] == :(Cont) -# lk14 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 46), (1.0, 3497)])), -# ) -# @test alpine.linear_terms[lk14][:y_idx] == 6914 -# @test alpine.linear_terms[lk14][:id] == 5 -# @test alpine.linear_terms[lk14][:y_type] == :(Cont) -# lk15 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6960), (1.0, 391)])), -# ) -# @test alpine.linear_terms[lk15][:y_idx] == 6961 -# @test alpine.linear_terms[lk15][:id] == 33 -# @test alpine.linear_terms[lk15][:y_type] == :(Cont) -# lk16 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 631), (-1.0, 6975)])), -# ) -# @test alpine.linear_terms[lk16][:y_idx] == 6976 -# @test alpine.linear_terms[lk16][:id] == 42 -# @test alpine.linear_terms[lk16][:y_type] == :(Cont) -# lk17 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1351), (-1.0, 6995)])), -# ) -# @test alpine.linear_terms[lk17][:y_idx] == 6996 -# @test alpine.linear_terms[lk17][:id] == 54 -# @test alpine.linear_terms[lk17][:y_type] == :(Cont) -# lk18 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3557), (1.0, 106)])), -# ) -# @test alpine.linear_terms[lk18][:y_idx] == 6924 -# @test alpine.linear_terms[lk18][:id] == 11 -# @test alpine.linear_terms[lk18][:y_type] == :(Cont) -# lk19 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}( -# :coef_var, -# Set(Any[(1.0, 3647), (1.0, 6941), (0.004795, 6903)]), -# ), -# ) -# @test alpine.linear_terms[lk19][:y_idx] == 6942 -# @test alpine.linear_terms[lk19][:id] == 22 -# @test alpine.linear_terms[lk19][:y_type] == :(Cont) -# lk20 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3722), (1.0, 271)])), -# ) -# @test alpine.linear_terms[lk20][:y_idx] == 6949 -# @test alpine.linear_terms[lk20][:id] == 26 -# @test alpine.linear_terms[lk20][:y_type] == :(Cont) -# lk21 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3647), (1.0, 196)])), -# ) -# @test alpine.linear_terms[lk21][:y_idx] == 6939 -# @test alpine.linear_terms[lk21][:id] == 20 -# @test alpine.linear_terms[lk21][:y_type] == :(Cont) -# lk22 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}( -# :coef_var, -# Set(Any[(1.0, 3467), (1.0, 6911), (6.34e-6, 6903)]), -# ), -# ) -# @test alpine.linear_terms[lk22][:y_idx] == 6912 -# @test alpine.linear_terms[lk22][:id] == 4 -# @test alpine.linear_terms[lk22][:y_type] == :(Cont) -# lk23 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1531), (1.0, 4982)])), -# ) -# @test alpine.linear_terms[lk23][:y_idx] == 6999 -# @test alpine.linear_terms[lk23][:id] == 56 -# @test alpine.linear_terms[lk23][:y_type] == :(Cont) -# lk24 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 106), (-1.0, 6925)])), -# ) -# @test alpine.linear_terms[lk24][:y_idx] == 6926 -# @test alpine.linear_terms[lk24][:id] == 12 -# @test alpine.linear_terms[lk24][:y_type] == :(Cont) -# lk25 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 2251), (-1.0, 7015)])), -# ) -# @test alpine.linear_terms[lk25][:y_idx] == 7016 -# @test alpine.linear_terms[lk25][:id] == 66 -# @test alpine.linear_terms[lk25][:y_type] == :(Cont) -# lk26 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}( -# :coef_var, -# Set(Any[(1.0, 6936), (0.004985, 6903), (1.0, 3617)]), -# ), -# ) -# @test alpine.linear_terms[lk26][:y_idx] == 6937 -# @test alpine.linear_terms[lk26][:id] == 19 -# @test alpine.linear_terms[lk26][:y_type] == :(Cont) -# lk27 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6915), (1.0, 46)])), -# ) -# @test alpine.linear_terms[lk27][:y_idx] == 6916 -# @test alpine.linear_terms[lk27][:id] == 6 -# @test alpine.linear_terms[lk27][:y_type] == :(Cont) -# lk28 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}( -# :coef_var, -# Set(Any[(1.0, 3557), (0.005968, 6903), (1.0, 6926)]), -# ), -# ) -# @test alpine.linear_terms[lk28][:y_idx] == 6927 -# @test alpine.linear_terms[lk28][:id] == 13 -# @test alpine.linear_terms[lk28][:y_type] == :(Cont) -# lk29 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 271), (-1.0, 6950)])), -# ) -# @test alpine.linear_terms[lk29][:y_idx] == 6951 -# @test alpine.linear_terms[lk29][:id] == 27 -# @test alpine.linear_terms[lk29][:y_type] == :(Cont) -# lk30 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}( -# :coef_var, -# Set(Any[(0.002971, 6903), (1.0, 6971), (1.0, 3962)]), -# ), -# ) -# @test alpine.linear_terms[lk30][:y_idx] == 6972 -# @test alpine.linear_terms[lk30][:id] == 40 -# @test alpine.linear_terms[lk30][:y_type] == :(Cont) -# lk31 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 511), (-1.0, 6970)])), -# ) -# @test alpine.linear_terms[lk31][:y_idx] == 6971 -# @test alpine.linear_terms[lk31][:id] == 39 -# @test alpine.linear_terms[lk31][:y_type] == :(Cont) -# lk32 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}( -# :coef_var, -# Set(Any[(1.0, 7031), (1.0, 6602), (0.00121, 6903)]), -# ), -# ) -# @test alpine.linear_terms[lk32][:y_idx] == 7032 -# @test alpine.linear_terms[lk32][:id] == 76 -# @test alpine.linear_terms[lk32][:y_type] == :(Cont) -# lk33 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}( -# :coef_var, -# Set(Any[(0.00166, 6903), (1.0, 7011), (1.0, 5402)]), -# ), -# ) -# @test alpine.linear_terms[lk33][:y_idx] == 7012 -# @test alpine.linear_terms[lk33][:id] == 64 -# @test alpine.linear_terms[lk33][:y_type] == :(Cont) -# lk34 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, -0.003214), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 16)])), -# ) -# @test alpine.linear_terms[lk34][:y_idx] == 6910 -# @test alpine.linear_terms[lk34][:id] == 2 -# @test alpine.linear_terms[lk34][:y_type] == :(Cont) -# lk35 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 7035), (1.0, 3451)])), -# ) -# @test alpine.linear_terms[lk35][:y_idx] == 7036 -# @test alpine.linear_terms[lk35][:id] == 78 -# @test alpine.linear_terms[lk35][:y_type] == :(Cont) -# lk36 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 2551), (1.0, 6002)])), -# ) -# @test alpine.linear_terms[lk36][:y_idx] == 7019 -# @test alpine.linear_terms[lk36][:id] == 68 -# @test alpine.linear_terms[lk36][:y_type] == :(Cont) -# lk37 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3842), (1.0, 391)])), -# ) -# @test alpine.linear_terms[lk37][:y_idx] == 6959 -# @test alpine.linear_terms[lk37][:id] == 32 -# @test alpine.linear_terms[lk37][:y_type] == :(Cont) -# lk38 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}( -# :coef_var, -# Set(Any[(1.0, 6966), (0.00307, 6903), (1.0, 3902)]), -# ), -# ) -# @test alpine.linear_terms[lk38][:y_idx] == 6967 -# @test alpine.linear_terms[lk38][:id] == 37 -# @test alpine.linear_terms[lk38][:y_type] == :(Cont) -# lk39 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}( -# :coef_var, -# Set(Any[(1.0, 3722), (0.003829, 6903), (1.0, 6951)]), -# ), -# ) -# @test alpine.linear_terms[lk39][:y_idx] == 6952 -# @test alpine.linear_terms[lk39][:id] == 28 -# @test alpine.linear_terms[lk39][:y_type] == :(Cont) -# lk40 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 451), (1.0, 3902)])), -# ) -# @test alpine.linear_terms[lk40][:y_idx] == 6964 -# @test alpine.linear_terms[lk40][:id] == 35 -# @test alpine.linear_terms[lk40][:y_type] == :(Cont) -# lk41 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}( -# :coef_var, -# Set(Any[(1.0, 7006), (1.0, 5162), (0.001713, 6903)]), -# ), -# ) -# @test alpine.linear_terms[lk41][:y_idx] == 7007 -# @test alpine.linear_terms[lk41][:id] == 61 -# @test alpine.linear_terms[lk41][:y_type] == :(Cont) -# lk42 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 811), (-1.0, 6980)])), -# ) -# @test alpine.linear_terms[lk42][:y_idx] == 6981 -# @test alpine.linear_terms[lk42][:id] == 45 -# @test alpine.linear_terms[lk42][:y_type] == :(Cont) -# lk43 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}( -# :coef_var, -# Set(Any[(1.0, 7001), (1.0, 4982), (0.00173, 6903)]), -# ), -# ) -# @test alpine.linear_terms[lk43][:y_idx] == 7002 -# @test alpine.linear_terms[lk43][:id] == 58 -# @test alpine.linear_terms[lk43][:y_type] == :(Cont) -# lk44 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6920), (1.0, 76)])), -# ) -# @test alpine.linear_terms[lk44][:y_idx] == 6921 -# @test alpine.linear_terms[lk44][:id] == 9 -# @test alpine.linear_terms[lk44][:y_type] == :(Cont) -# lk45 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 4622), (1.0, 1171)])), -# ) -# @test alpine.linear_terms[lk45][:y_idx] == 6989 -# @test alpine.linear_terms[lk45][:id] == 50 -# @test alpine.linear_terms[lk45][:y_type] == :(Cont) -# lk46 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 991), (1.0, 4442)])), -# ) -# @test alpine.linear_terms[lk46][:y_idx] == 6984 -# @test alpine.linear_terms[lk46][:id] == 47 -# @test alpine.linear_terms[lk46][:y_type] == :(Cont) -# lk47 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6930), (1.0, 136)])), -# ) -# @test alpine.linear_terms[lk47][:y_idx] == 6931 -# @test alpine.linear_terms[lk47][:id] == 15 -# @test alpine.linear_terms[lk47][:y_type] == :(Cont) -# lk48 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}( -# :coef_var, -# Set(Any[(1.0, 4802), (0.001891, 6903), (1.0, 6996)]), -# ), -# ) -# @test alpine.linear_terms[lk48][:y_idx] == 6997 -# @test alpine.linear_terms[lk48][:id] == 55 -# @test alpine.linear_terms[lk48][:y_type] == :(Cont) -# lk49 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 511), (1.0, 3962)])), -# ) -# @test alpine.linear_terms[lk49][:y_idx] == 6969 -# @test alpine.linear_terms[lk49][:id] == 38 -# @test alpine.linear_terms[lk49][:y_type] == :(Cont) -# lk50 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 811), (1.0, 4262)])), -# ) -# @test alpine.linear_terms[lk50][:y_idx] == 6979 -# @test alpine.linear_terms[lk50][:id] == 44 -# @test alpine.linear_terms[lk50][:y_type] == :(Cont) -# lk51 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}( -# :coef_var, -# Set(Any[(0.01551, 6903), (1.0, 6916), (1.0, 3497)]), -# ), -# ) -# @test alpine.linear_terms[lk51][:y_idx] == 6917 -# @test alpine.linear_terms[lk51][:id] == 7 -# @test alpine.linear_terms[lk51][:y_type] == :(Cont) -# lk52 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 451), (-1.0, 6965)])), -# ) -# @test alpine.linear_terms[lk52][:y_idx] == 6966 -# @test alpine.linear_terms[lk52][:id] == 36 -# @test alpine.linear_terms[lk52][:y_type] == :(Cont) -# lk53 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}( -# :coef_var, -# Set(Any[(0.005773, 6903), (1.0, 3587), (1.0, 6931)]), -# ), -# ) -# @test alpine.linear_terms[lk53][:y_idx] == 6932 -# @test alpine.linear_terms[lk53][:id] == 16 -# @test alpine.linear_terms[lk53][:y_type] == :(Cont) -# lk54 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 631), (1.0, 4082)])), -# ) -# @test alpine.linear_terms[lk54][:y_idx] == 6974 -# @test alpine.linear_terms[lk54][:id] == 41 -# @test alpine.linear_terms[lk54][:y_type] == :(Cont) -# lk55 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 991), (-1.0, 6985)])), -# ) -# @test alpine.linear_terms[lk55][:y_idx] == 6986 -# @test alpine.linear_terms[lk55][:id] == 48 -# @test alpine.linear_terms[lk55][:y_type] == :(Cont) -# lk56 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 4802), (1.0, 1351)])), -# ) -# @test alpine.linear_terms[lk56][:y_idx] == 6994 -# @test alpine.linear_terms[lk56][:id] == 53 -# @test alpine.linear_terms[lk56][:y_type] == :(Cont) -# lk57 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}( -# :coef_var, -# Set(Any[(1.0, 6946), (0.004409, 6903), (1.0, 3677)]), -# ), -# ) -# @test alpine.linear_terms[lk57][:y_idx] == 6947 -# @test alpine.linear_terms[lk57][:id] == 25 -# @test alpine.linear_terms[lk57][:y_type] == :(Cont) -# lk58 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 2251), (1.0, 5702)])), -# ) -# @test alpine.linear_terms[lk58][:y_idx] == 7014 -# @test alpine.linear_terms[lk58][:id] == 65 -# @test alpine.linear_terms[lk58][:y_type] == :(Cont) -# lk59 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 7020), (1.0, 2551)])), -# ) -# @test alpine.linear_terms[lk59][:y_idx] == 7021 -# @test alpine.linear_terms[lk59][:id] == 69 -# @test alpine.linear_terms[lk59][:y_type] == :(Cont) -# lk60 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6940), (1.0, 196)])), -# ) -# @test alpine.linear_terms[lk60][:y_idx] == 6941 -# @test alpine.linear_terms[lk60][:id] == 21 -# @test alpine.linear_terms[lk60][:y_type] == :(Cont) -# lk61 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}( -# :coef_var, -# Set(Any[(1.0, 3527), (1.0, 6921), (0.008919, 6903)]), -# ), -# ) -# @test alpine.linear_terms[lk61][:y_idx] == 6922 -# @test alpine.linear_terms[lk61][:id] == 10 -# @test alpine.linear_terms[lk61][:y_type] == :(Cont) -# lk62 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 7025), (1.0, 2851)])), -# ) -# @test alpine.linear_terms[lk62][:y_idx] == 7026 -# @test alpine.linear_terms[lk62][:id] == 72 -# @test alpine.linear_terms[lk62][:y_type] == :(Cont) -# lk63 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}( -# :coef_var, -# Set(Any[(1.0, 6986), (1.0, 4442), (0.002252, 6903)]), -# ), -# ) -# @test alpine.linear_terms[lk63][:y_idx] == 6987 -# @test alpine.linear_terms[lk63][:id] == 49 -# @test alpine.linear_terms[lk63][:y_type] == :(Cont) -# lk64 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}( -# :coef_var, -# Set(Any[(0.002765, 6903), (1.0, 6976), (1.0, 4082)]), -# ), -# ) -# @test alpine.linear_terms[lk64][:y_idx] == 6977 -# @test alpine.linear_terms[lk64][:id] == 43 -# @test alpine.linear_terms[lk64][:y_type] == :(Cont) -# lk65 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}( -# :coef_var, -# Set(Any[(1.0, 6956), (0.003269, 6903), (1.0, 3782)]), -# ), -# ) -# @test alpine.linear_terms[lk65][:y_idx] == 6957 -# @test alpine.linear_terms[lk65][:id] == 31 -# @test alpine.linear_terms[lk65][:y_type] == :(Cont) -# lk66 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3587), (1.0, 136)])), -# ) -# @test alpine.linear_terms[lk66][:y_idx] == 6929 -# @test alpine.linear_terms[lk66][:id] == 14 -# @test alpine.linear_terms[lk66][:y_type] == :(Cont) -# lk67 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 166), (1.0, 3617)])), -# ) -# @test alpine.linear_terms[lk67][:y_idx] == 6934 -# @test alpine.linear_terms[lk67][:id] == 17 -# @test alpine.linear_terms[lk67][:y_type] == :(Cont) -# lk68 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 7010), (1.0, 1951)])), -# ) -# @test alpine.linear_terms[lk68][:y_idx] == 7011 -# @test alpine.linear_terms[lk68][:id] == 63 -# @test alpine.linear_terms[lk68][:y_type] == :(Cont) -# lk69 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}( -# :coef_var, -# Set(Any[(1.0, 7036), (0.001098, 6903), (1.0, 6902)]), -# ), -# ) -# @test alpine.linear_terms[lk69][:y_idx] == 7037 -# @test alpine.linear_terms[lk69][:id] == 79 -# @test alpine.linear_terms[lk69][:y_type] == :(Cont) -# lk70 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3527), (1.0, 76)])), -# ) -# @test alpine.linear_terms[lk70][:y_idx] == 6919 -# @test alpine.linear_terms[lk70][:id] == 8 -# @test alpine.linear_terms[lk70][:y_type] == :(Cont) -# lk71 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}( -# :coef_var, -# Set(Any[(1.0, 6961), (1.0, 3842), (0.00317, 6903)]), -# ), -# ) -# @test alpine.linear_terms[lk71][:y_idx] == 6962 -# @test alpine.linear_terms[lk71][:id] == 34 -# @test alpine.linear_terms[lk71][:y_type] == :(Cont) -# lk72 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6990), (1.0, 1171)])), -# ) -# @test alpine.linear_terms[lk72][:y_idx] == 6991 -# @test alpine.linear_terms[lk72][:id] == 51 -# @test alpine.linear_terms[lk72][:y_type] == :(Cont) -# lk73 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3451), (1.0, 6902)])), -# ) -# @test alpine.linear_terms[lk73][:y_idx] == 7034 -# @test alpine.linear_terms[lk73][:id] == 77 -# @test alpine.linear_terms[lk73][:y_type] == :(Cont) -# lk74 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6302), (1.0, 2851)])), -# ) -# @test alpine.linear_terms[lk74][:y_idx] == 7024 -# @test alpine.linear_terms[lk74][:id] == 71 -# @test alpine.linear_terms[lk74][:y_type] == :(Cont) -# lk75 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1531), (-1.0, 7000)])), -# ) -# @test alpine.linear_terms[lk75][:y_idx] == 7001 -# @test alpine.linear_terms[lk75][:id] == 57 -# @test alpine.linear_terms[lk75][:y_type] == :(Cont) -# lk76 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3151), (1.0, 6602)])), -# ) -# @test alpine.linear_terms[lk76][:y_idx] == 7029 -# @test alpine.linear_terms[lk76][:id] == 74 -# @test alpine.linear_terms[lk76][:y_type] == :(Cont) -# lk77 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3782), (1.0, 331)])), -# ) -# @test alpine.linear_terms[lk77][:y_idx] == 6954 -# @test alpine.linear_terms[lk77][:id] == 29 -# @test alpine.linear_terms[lk77][:y_type] == :(Cont) -# lk78 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6955), (1.0, 331)])), -# ) -# @test alpine.linear_terms[lk78][:y_idx] == 6956 -# @test alpine.linear_terms[lk78][:id] == 30 -# @test alpine.linear_terms[lk78][:y_type] == :(Cont) -# lk79 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 226), (1.0, 3677)])), -# ) -# @test alpine.linear_terms[lk79][:y_idx] == 6944 -# @test alpine.linear_terms[lk79][:id] == 23 -# @test alpine.linear_terms[lk79][:y_type] == :(Cont) -# end -# end - -# @testset "Expression Parsing || Basic Multiplication Operators (Machine Generated for diffs)" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "minlp_solver" => JUNIPER, -# "mip_solver" => HIGHS, -# "log_level" => 100, -# ) - -# m = operator_basic(solver = test_solver) -# JuMP.set_optimize_hook(m, MOI.Utilities.attach_optimizer) -# JuMP.optimize!(m) -# JuMP.set_optimize_hook(m, nothing) -# alpine = JuMP.backend(m).optimizer.model -# Alpine.load!(alpine) - -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4])]][:y_idx] == 31 -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4])]][:id] == 27 -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4])]][:lifted_constr_ref] == -# :(x[31] == x[3] * x[4]) -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[76])]][:y_idx] == 83 -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[76])]][:id] == 79 -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[76])]][:lifted_constr_ref] == -# :(x[83] == x[4] * x[5] * x[76]) -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[76])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[2])]][:y_idx] == 9 -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[2])]][:id] == 5 -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[2])]][:lifted_constr_ref] == -# :(x[9] == (*)(x[2])) -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[2])]][:nonlinear_type] == :MONOMIAL -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7])]][:y_idx] == 19 -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7])]][:id] == 15 -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7])]][:lifted_constr_ref] == -# :(x[19] == x[5] * x[7]) -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[31])]][:y_idx] == 32 -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[31])]][:id] == 28 -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[31])]][:lifted_constr_ref] == -# :(x[32] == x[2] * x[31]) -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[31])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10])]][:y_idx] == 49 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10])]][:id] == 45 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10])]][:lifted_constr_ref] == -# :(x[49] == x[1] * x[2] * x[10]) -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5]), :(x[9])]][:y_idx] == 50 -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5]), :(x[9])]][:id] == 46 -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5]), :(x[9])]][:lifted_constr_ref] == -# :(x[50] == x[3] * x[5] * x[9]) -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5]), :(x[9])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[47])]][:y_idx] == 69 -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[47])]][:id] == 65 -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[47])]][:lifted_constr_ref] == -# :(x[69] == x[4] * x[47]) -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[47])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[4])]][:y_idx] == 28 -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[4])]][:id] == 24 -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[4])]][:lifted_constr_ref] == -# :(x[28] == (*)(x[4])) -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[4])]][:nonlinear_type] == :MONOMIAL -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[10])]][:y_idx] == 37 -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[10])]][:id] == 33 -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[10])]][:lifted_constr_ref] == -# :(x[37] == x[4] * x[10]) -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[10])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[1])]][:y_idx] == 5 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[1])]][:id] == 1 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[1])]][:lifted_constr_ref] == -# :(x[5] == (*)(x[1])) -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[1])]][:nonlinear_type] == :MONOMIAL -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[95])]][:y_idx] == 96 -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[95])]][:id] == 92 -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[95])]][:lifted_constr_ref] == -# :(x[96] == x[5] * x[95]) -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[95])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[40])]][:y_idx] == 41 -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[40])]][:id] == 37 -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[40])]][:lifted_constr_ref] == -# :(x[41] == x[2] * x[40]) -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[40])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10])]][:y_idx] == 26 -# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10])]][:id] == 22 -# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10])]][:lifted_constr_ref] == -# :(x[26] == x[6] * x[10]) -# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[78]), :(x[28])]][:y_idx] == 84 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[78]), :(x[28])]][:id] == 80 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[78]), :(x[28])]][:lifted_constr_ref] == -# :(x[84] == x[1] * x[78] * x[28]) -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[78]), :(x[28])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[43])]][:y_idx] == 58 -# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[43])]][:id] == 54 -# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[43])]][:lifted_constr_ref] == -# :(x[58] == x[6] * x[43]) -# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[43])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[6]), :(x[10])]][:y_idx] == 106 -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[6]), :(x[10])]][:id] == 102 -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[6]), :(x[10])]][:lifted_constr_ref] == -# :(x[106] == x[4] * x[6] * x[10]) -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[6]), :(x[10])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4]), :(x[10])]][:y_idx] == 90 -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4]), :(x[10])]][:id] == 86 -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4]), :(x[10])]][:lifted_constr_ref] == -# :(x[90] == x[2] * x[4] * x[10]) -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4]), :(x[10])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[41])]][:y_idx] == 42 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[41])]][:id] == 38 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[41])]][:lifted_constr_ref] == -# :(x[42] == x[1] * x[41]) -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[41])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[37])]][:y_idx] == 38 -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[37])]][:id] == 34 -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[37])]][:lifted_constr_ref] == -# :(x[38] == x[2] * x[37]) -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[37])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[85])]][:y_idx] == 87 -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[85])]][:id] == 83 -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[85])]][:lifted_constr_ref] == -# :(x[87] == x[5] * x[85]) -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[85])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5]), :(x[28])]][:y_idx] == 66 -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5]), :(x[28])]][:id] == 62 -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5]), :(x[28])]][:lifted_constr_ref] == -# :(x[66] == x[2] * x[3] * x[5] * x[28]) -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5]), :(x[28])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10])]][:y_idx] == 53 -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10])]][:id] == 49 -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10])]][:lifted_constr_ref] == -# :(x[53] == x[5] * x[9] * x[10]) -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6]), :(x[28])]][:y_idx] == 107 -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6]), :(x[28])]][:id] == 103 -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6]), :(x[28])]][:lifted_constr_ref] == -# :(x[107] == x[3] * x[6] * x[28]) -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6]), :(x[28])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5])]][:y_idx] == 17 -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5])]][:id] == 13 -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5])]][:lifted_constr_ref] == -# :(x[17] == x[2] * x[5]) -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[37])]][:y_idx] == 57 -# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[37])]][:id] == 53 -# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[37])]][:lifted_constr_ref] == -# :(x[57] == x[6] * x[37]) -# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[37])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7]), :(x[28])]][:y_idx] == 81 -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7]), :(x[28])]][:id] == 77 -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7]), :(x[28])]][:lifted_constr_ref] == -# :(x[81] == x[5] * x[7] * x[28]) -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7]), :(x[28])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[38])]][:y_idx] == 39 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[38])]][:id] == 35 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[38])]][:lifted_constr_ref] == -# :(x[39] == x[1] * x[38]) -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[38])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[9])]][:y_idx] == 48 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[9])]][:id] == 44 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[9])]][:lifted_constr_ref] == -# :(x[48] == x[1] * x[3] * x[9]) -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[9])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[23])]][:y_idx] == 24 -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[23])]][:id] == 20 -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[23])]][:lifted_constr_ref] == -# :(x[24] == x[4] * x[23]) -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[23])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[17])]][:y_idx] == 23 -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[17])]][:id] == 19 -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[17])]][:lifted_constr_ref] == -# :(x[23] == x[3] * x[17]) -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[17])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[10])]][:y_idx] == 51 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[10])]][:id] == 47 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[10])]][:lifted_constr_ref] == -# :(x[51] == x[1] * x[9] * x[10]) -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[10])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[7])]][:y_idx] == 75 -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[7])]][:id] == 71 -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[7])]][:lifted_constr_ref] == -# :(x[75] == x[4] * x[5] * x[7]) -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[7])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[28])]][:y_idx] == 95 -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[28])]][:id] == 91 -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[28])]][:lifted_constr_ref] == -# :(x[95] == x[9] * x[10] * x[28]) -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[28])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10])]][:y_idx] == 11 -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10])]][:id] == 7 -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10])]][:lifted_constr_ref] == -# :(x[11] == x[9] * x[10]) -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[37])]][:y_idx] == 100 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[37])]][:id] == 96 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[37])]][:lifted_constr_ref] == -# :(x[100] == x[1] * x[2] * x[37]) -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[37])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4]), :(x[5])]][:y_idx] == 62 -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4]), :(x[5])]][:id] == 58 -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4]), :(x[5])]][:lifted_constr_ref] == -# :(x[62] == x[2] * x[3] * x[4] * x[5]) -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4]), :(x[5])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[9]), :(x[10])]][:y_idx] == 65 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[9]), :(x[10])]][:id] == 61 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[9]), :(x[10])]][:lifted_constr_ref] == -# :(x[65] == x[1] * x[4] * x[9] * x[10]) -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[9]), :(x[10])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7]), :(x[28])]][:y_idx] == 80 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7]), :(x[28])]][:id] == 76 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7]), :(x[28])]][:lifted_constr_ref] == -# :(x[80] == x[1] * x[7] * x[28]) -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7]), :(x[28])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3])]][:y_idx] == 46 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3])]][:id] == 42 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3])]][:lifted_constr_ref] == -# :(x[46] == x[1] * x[2] * x[3]) -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[40])]][:y_idx] == 59 -# @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[40])]][:id] == 55 -# @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[40])]][:lifted_constr_ref] == -# :(x[59] == x[17] * x[40]) -# @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[40])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[85])]][:y_idx] == 86 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[85])]][:id] == 82 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[85])]][:lifted_constr_ref] == -# :(x[86] == x[1] * x[85]) -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[85])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[31])]][:y_idx] == 97 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[31])]][:id] == 93 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[31])]][:lifted_constr_ref] == -# :(x[97] == x[1] * x[2] * x[31]) -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[31])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[28])]][:y_idx] == 29 -# @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[28])]][:id] == 25 -# @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[28])]][:lifted_constr_ref] == -# :(x[29] == x[13] * x[28]) -# @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[28])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[28])]][:y_idx] == 92 -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[28])]][:id] == 88 -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[28])]][:lifted_constr_ref] == -# :(x[92] == x[2] * x[3] * x[28]) -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[28])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9])]][:y_idx] == 20 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9])]][:id] == 16 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9])]][:lifted_constr_ref] == -# :(x[20] == x[1] * x[9]) -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10]), :(x[28])]][:y_idx] == 109 -# @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10]), :(x[28])]][:id] == 105 -# @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10]), :(x[28])]][:lifted_constr_ref] == -# :(x[109] == x[14] * x[10] * x[28]) -# @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10]), :(x[28])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[92])]][:y_idx] == 93 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[92])]][:id] == 89 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[92])]][:lifted_constr_ref] == -# :(x[93] == x[1] * x[92]) -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[92])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4])]][:y_idx] == 85 -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4])]][:id] == 81 -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4])]][:lifted_constr_ref] == -# :(x[85] == x[2] * x[3] * x[4]) -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[11])]][:y_idx] == 16 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[11])]][:id] == 12 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[11])]][:lifted_constr_ref] == -# :(x[16] == x[1] * x[11]) -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[11])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[21])]][:y_idx] == 25 -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[21])]][:id] == 21 -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[21])]][:lifted_constr_ref] == -# :(x[25] == x[4] * x[21]) -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[21])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[53]), :(x[28])]][:y_idx] == 73 -# @test alpine.nonconvex_terms[Expr[:(x[53]), :(x[28])]][:id] == 69 -# @test alpine.nonconvex_terms[Expr[:(x[53]), :(x[28])]][:lifted_constr_ref] == -# :(x[73] == x[53] * x[28]) -# @test alpine.nonconvex_terms[Expr[:(x[53]), :(x[28])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[32])]][:y_idx] == 34 -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[32])]][:id] == 30 -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[32])]][:lifted_constr_ref] == -# :(x[34] == x[5] * x[32]) -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[32])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[28])]][:y_idx] == 40 -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[28])]][:id] == 36 -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[28])]][:lifted_constr_ref] == -# :(x[40] == x[3] * x[28]) -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[28])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10]), :(x[28])]][:y_idx] == 67 -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10]), :(x[28])]][:id] == 63 -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10]), :(x[28])]][:lifted_constr_ref] == -# :(x[67] == x[5] * x[9] * x[10] * x[28]) -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10]), :(x[28])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[43])]][:y_idx] == 102 -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[43])]][:id] == 98 -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[43])]][:lifted_constr_ref] == -# :(x[102] == x[5] * x[9] * x[43]) -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[43])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[26])]][:y_idx] == 27 -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[26])]][:id] == 23 -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[26])]][:lifted_constr_ref] == -# :(x[27] == x[4] * x[26]) -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[26])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[20]), :(x[31])]][:y_idx] == 56 -# @test alpine.nonconvex_terms[Expr[:(x[20]), :(x[31])]][:id] == 52 -# @test alpine.nonconvex_terms[Expr[:(x[20]), :(x[31])]][:lifted_constr_ref] == -# :(x[56] == x[20] * x[31]) -# @test alpine.nonconvex_terms[Expr[:(x[20]), :(x[31])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[4]), :(x[9])]][:y_idx] == 63 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[4]), :(x[9])]][:id] == 59 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[4]), :(x[9])]][:lifted_constr_ref] == -# :(x[63] == x[1] * x[3] * x[4] * x[9]) -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[4]), :(x[9])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10])]][:y_idx] == 15 -# @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10])]][:id] == 11 -# @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10])]][:lifted_constr_ref] == -# :(x[15] == x[14] * x[10]) -# @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[76])]][:y_idx] == 77 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[76])]][:id] == 73 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[76])]][:lifted_constr_ref] == -# :(x[77] == x[1] * x[4] * x[76]) -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[76])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[88])]][:y_idx] == 89 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[88])]][:id] == 85 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[88])]][:lifted_constr_ref] == -# :(x[89] == x[1] * x[88]) -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[88])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[90])]][:y_idx] == 94 -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[90])]][:id] == 90 -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[90])]][:lifted_constr_ref] == -# :(x[94] == x[5] * x[90]) -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[90])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10]), :(x[28])]][:y_idx] == 108 -# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10]), :(x[28])]][:id] == 104 -# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10]), :(x[28])]][:lifted_constr_ref] == -# :(x[108] == x[6] * x[10] * x[28]) -# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10]), :(x[28])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[48])]][:y_idx] == 70 -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[48])]][:id] == 66 -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[48])]][:lifted_constr_ref] == -# :(x[70] == x[4] * x[48]) -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[48])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[31])]][:y_idx] == 54 -# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[31])]][:id] == 50 -# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[31])]][:lifted_constr_ref] == -# :(x[54] == x[6] * x[31]) -# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[31])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[31])]][:y_idx] == 99 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[31])]][:id] == 95 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[31])]][:lifted_constr_ref] == -# :(x[99] == x[1] * x[9] * x[31]) -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[31])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[35])]][:y_idx] == 36 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[35])]][:id] == 32 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[35])]][:lifted_constr_ref] == -# :(x[36] == x[1] * x[35]) -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[35])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9])]][:y_idx] == 14 -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9])]][:id] == 10 -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9])]][:lifted_constr_ref] == -# :(x[14] == x[5] * x[9]) -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[13])]][:y_idx] == 22 -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[13])]][:id] == 18 -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[13])]][:lifted_constr_ref] == -# :(x[22] == x[4] * x[13]) -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[13])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10]), :(x[28])]][:y_idx] == 64 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10]), :(x[28])]][:id] == 60 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10]), :(x[28])]][:lifted_constr_ref] == -# :(x[64] == x[1] * x[2] * x[10] * x[28]) -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10]), :(x[28])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[46]), :(x[28])]][:y_idx] == 72 -# @test alpine.nonconvex_terms[Expr[:(x[46]), :(x[28])]][:id] == 68 -# @test alpine.nonconvex_terms[Expr[:(x[46]), :(x[28])]][:lifted_constr_ref] == -# :(x[72] == x[46] * x[28]) -# @test alpine.nonconvex_terms[Expr[:(x[46]), :(x[28])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[31])]][:y_idx] == 55 -# @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[31])]][:id] == 51 -# @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[31])]][:lifted_constr_ref] == -# :(x[55] == x[17] * x[31]) -# @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[31])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[31])]][:y_idx] == 98 -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[31])]][:id] == 94 -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[31])]][:lifted_constr_ref] == -# :(x[98] == x[2] * x[5] * x[31]) -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[31])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[28])]][:y_idx] == 43 -# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[28])]][:id] == 39 -# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[28])]][:lifted_constr_ref] == -# :(x[43] == x[10] * x[28]) -# @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[28])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[10])]][:y_idx] == 78 -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[10])]][:id] == 74 -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[10])]][:lifted_constr_ref] == -# :(x[78] == x[2] * x[10]) -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[10])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[10])]][:y_idx] == 52 -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[10])]][:id] == 48 -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[10])]][:lifted_constr_ref] == -# :(x[52] == x[2] * x[5] * x[10]) -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[10])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[90])]][:y_idx] == 91 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[90])]][:id] == 87 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[90])]][:lifted_constr_ref] == -# :(x[91] == x[1] * x[90]) -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[90])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[17])]][:y_idx] == 104 -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[17])]][:id] == 100 -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[17])]][:lifted_constr_ref] == -# :(x[104] == x[3] * x[4] * x[17]) -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[17])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[9])]][:y_idx] == 76 -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[9])]][:id] == 72 -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[9])]][:lifted_constr_ref] == -# :(x[76] == x[3] * x[9]) -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[9])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[78])]][:y_idx] == 79 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[78])]][:id] == 75 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[78])]][:lifted_constr_ref] == -# :(x[79] == x[1] * x[4] * x[78]) -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[78])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[3])]][:y_idx] == 10 -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[3])]][:id] == 6 -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[3])]][:lifted_constr_ref] == -# :(x[10] == (*)(x[3])) -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[3])]][:nonlinear_type] == :MONOMIAL -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[49])]][:y_idx] == 71 -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[49])]][:id] == 67 -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[49])]][:lifted_constr_ref] == -# :(x[71] == x[4] * x[49]) -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[49])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[9])]][:y_idx] == 88 -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[9])]][:id] == 84 -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[9])]][:lifted_constr_ref] == -# :(x[88] == x[3] * x[4] * x[9]) -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[9])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[15]), :(x[28])]][:y_idx] == 30 -# @test alpine.nonconvex_terms[Expr[:(x[15]), :(x[28])]][:id] == 26 -# @test alpine.nonconvex_terms[Expr[:(x[15]), :(x[28])]][:lifted_constr_ref] == -# :(x[30] == x[15] * x[28]) -# @test alpine.nonconvex_terms[Expr[:(x[15]), :(x[28])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[46])]][:y_idx] == 68 -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[46])]][:id] == 64 -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[46])]][:lifted_constr_ref] == -# :(x[68] == x[4] * x[46]) -# @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[46])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[11])]][:y_idx] == 12 -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[11])]][:id] == 8 -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[11])]][:lifted_constr_ref] == -# :(x[12] == x[5] * x[11]) -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[11])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[7])]][:y_idx] == 74 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[7])]][:id] == 70 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[7])]][:lifted_constr_ref] == -# :(x[74] == x[1] * x[4] * x[7]) -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[7])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[20])]][:y_idx] == 105 -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[20])]][:id] == 101 -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[20])]][:lifted_constr_ref] == -# :(x[105] == x[3] * x[4] * x[20]) -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[20])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[11])]][:y_idx] == 82 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[11])]][:id] == 78 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[11])]][:lifted_constr_ref] == -# :(x[82] == x[1] * x[4] * x[11]) -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[11])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[43])]][:y_idx] == 44 -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[43])]][:id] == 40 -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[43])]][:lifted_constr_ref] == -# :(x[44] == x[9] * x[43]) -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[43])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:y_idx] == 61 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:id] == 57 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:lifted_constr_ref] == -# :(x[61] == x[1] * x[2] * x[3] * x[4]) -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[10])]][:y_idx] == 18 -# @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[10])]][:id] == 14 -# @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[10])]][:lifted_constr_ref] == -# :(x[18] == x[17] * x[10]) -# @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[10])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7])]][:y_idx] == 8 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7])]][:id] == 4 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7])]][:lifted_constr_ref] == -# :(x[8] == x[1] * x[7]) -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2])]][:y_idx] == 6 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2])]][:id] == 2 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2])]][:lifted_constr_ref] == -# :(x[6] == x[1] * x[2]) -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[40])]][:y_idx] == 101 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[40])]][:id] == 97 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[40])]][:lifted_constr_ref] == -# :(x[101] == x[1] * x[2] * x[40]) -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[40])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[37])]][:y_idx] == 60 -# @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[37])]][:id] == 56 -# @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[37])]][:lifted_constr_ref] == -# :(x[60] == x[17] * x[37]) -# @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[37])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[6])]][:y_idx] == 103 -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[6])]][:id] == 99 -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[6])]][:lifted_constr_ref] == -# :(x[103] == x[3] * x[4] * x[6]) -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[6])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3])]][:y_idx] == 7 -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3])]][:id] == 3 -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3])]][:lifted_constr_ref] == -# :(x[7] == x[2] * x[3]) -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5])]][:y_idx] == 47 -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5])]][:id] == 43 -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5])]][:lifted_constr_ref] == -# :(x[47] == x[2] * x[3] * x[5]) -# @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6])]][:y_idx] == 13 -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6])]][:id] == 9 -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6])]][:lifted_constr_ref] == -# :(x[13] == x[3] * x[6]) -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[31])]][:y_idx] == 35 -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[31])]][:id] == 31 -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[31])]][:lifted_constr_ref] == -# :(x[35] == x[9] * x[31]) -# @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[31])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[32])]][:y_idx] == 33 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[32])]][:id] == 29 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[32])]][:lifted_constr_ref] == -# :(x[33] == x[1] * x[32]) -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[32])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[20])]][:y_idx] == 21 -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[20])]][:id] == 17 -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[20])]][:lifted_constr_ref] == -# :(x[21] == x[3] * x[20]) -# @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[20])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[44])]][:y_idx] == 45 -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[44])]][:id] == 41 -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[44])]][:lifted_constr_ref] == -# :(x[45] == x[5] * x[44]) -# @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[44])]][:nonlinear_type] == :BILINEAR - -# @test alpine.bounding_constr_mip[1][:rhs] == 1.0 -# @test alpine.bounding_constr_mip[1][:vars] == Any[:(x[5])] -# @test alpine.bounding_constr_mip[1][:coefs] == Any[1.0] -# @test alpine.bounding_constr_mip[1][:sense] == :(>=) -# @test alpine.bounding_constr_mip[1][:cnt] == 1 -# @test alpine.bounding_constr_mip[2][:rhs] == 1.0 -# @test alpine.bounding_constr_mip[2][:vars] == Any[:(x[6])] -# @test alpine.bounding_constr_mip[2][:coefs] == Any[1.0] -# @test alpine.bounding_constr_mip[2][:sense] == :(<=) -# @test alpine.bounding_constr_mip[2][:cnt] == 1 -# @test alpine.bounding_constr_mip[3][:rhs] == 1.0 -# @test alpine.bounding_constr_mip[3][:vars] == Any[:(x[5]), :(x[7])] -# @test alpine.bounding_constr_mip[3][:coefs] == Any[1.0, 1.0] -# @test alpine.bounding_constr_mip[3][:sense] == :(<=) -# @test alpine.bounding_constr_mip[3][:cnt] == 2 -# @test alpine.bounding_constr_mip[4][:rhs] == 1.0 -# @test alpine.bounding_constr_mip[4][:vars] == Any[:(x[8])] -# @test alpine.bounding_constr_mip[4][:coefs] == Any[1.0] -# @test alpine.bounding_constr_mip[4][:sense] == :(>=) -# @test alpine.bounding_constr_mip[4][:cnt] == 1 -# @test alpine.bounding_constr_mip[5][:rhs] == 1.0 -# @test alpine.bounding_constr_mip[5][:vars] == Any[:(x[12])] -# @test alpine.bounding_constr_mip[5][:coefs] == Any[1.0] -# @test alpine.bounding_constr_mip[5][:sense] == :(<=) -# @test alpine.bounding_constr_mip[5][:cnt] == 1 -# @test alpine.bounding_constr_mip[6][:rhs] == 1.0 -# @test alpine.bounding_constr_mip[6][:vars] == Any[:(x[13])] -# @test alpine.bounding_constr_mip[6][:coefs] == Any[1.0] -# @test alpine.bounding_constr_mip[6][:sense] == :(>=) -# @test alpine.bounding_constr_mip[6][:cnt] == 1 -# @test alpine.bounding_constr_mip[7][:rhs] == 1.0 -# @test alpine.bounding_constr_mip[7][:vars] == Any[:(x[15])] -# @test alpine.bounding_constr_mip[7][:coefs] == Any[1.0] -# @test alpine.bounding_constr_mip[7][:sense] == :(<=) -# @test alpine.bounding_constr_mip[7][:cnt] == 1 -# @test alpine.bounding_constr_mip[8][:rhs] == 1.0 -# @test alpine.bounding_constr_mip[8][:vars] == Any[:(x[16])] -# @test alpine.bounding_constr_mip[8][:coefs] == Any[1.0] -# @test alpine.bounding_constr_mip[8][:sense] == :(>=) -# @test alpine.bounding_constr_mip[8][:cnt] == 1 -# @test alpine.bounding_constr_mip[9][:rhs] == 1.0 -# @test alpine.bounding_constr_mip[9][:vars] == Any[:(x[18])] -# @test alpine.bounding_constr_mip[9][:coefs] == Any[1.0] -# @test alpine.bounding_constr_mip[9][:sense] == :(<=) -# @test alpine.bounding_constr_mip[9][:cnt] == 1 -# @test alpine.bounding_constr_mip[10][:rhs] == 1.0 -# @test alpine.bounding_constr_mip[10][:vars] == Any[:(x[19])] -# @test alpine.bounding_constr_mip[10][:coefs] == Any[1.0] -# @test alpine.bounding_constr_mip[10][:sense] == :(>=) -# @test alpine.bounding_constr_mip[10][:cnt] == 1 -# @test alpine.bounding_constr_mip[11][:rhs] == 1.0 -# @test alpine.bounding_constr_mip[11][:vars] == Any[:(x[21])] -# @test alpine.bounding_constr_mip[11][:coefs] == Any[1.0] -# @test alpine.bounding_constr_mip[11][:sense] == :(<=) -# @test alpine.bounding_constr_mip[11][:cnt] == 1 -# @test alpine.bounding_constr_mip[12][:rhs] == 1.0 -# @test alpine.bounding_constr_mip[12][:vars] == Any[:(x[22])] -# @test alpine.bounding_constr_mip[12][:coefs] == Any[1.0] -# @test alpine.bounding_constr_mip[12][:sense] == :(>=) -# @test alpine.bounding_constr_mip[12][:cnt] == 1 -# @test alpine.bounding_constr_mip[13][:rhs] == 1.0 -# @test alpine.bounding_constr_mip[13][:vars] == Any[:(x[24])] -# @test alpine.bounding_constr_mip[13][:coefs] == Any[1.0] -# @test alpine.bounding_constr_mip[13][:sense] == :(<=) -# @test alpine.bounding_constr_mip[13][:cnt] == 1 -# @test alpine.bounding_constr_mip[14][:rhs] == 1.0 -# @test alpine.bounding_constr_mip[14][:vars] == Any[:(x[25])] -# @test alpine.bounding_constr_mip[14][:coefs] == Any[1.0] -# @test alpine.bounding_constr_mip[14][:sense] == :(>=) -# @test alpine.bounding_constr_mip[14][:cnt] == 1 -# @test alpine.bounding_constr_mip[15][:rhs] == 1.0 -# @test alpine.bounding_constr_mip[15][:vars] == Any[:(x[27])] -# @test alpine.bounding_constr_mip[15][:coefs] == Any[1.0] -# @test alpine.bounding_constr_mip[15][:sense] == :(<=) -# @test alpine.bounding_constr_mip[15][:cnt] == 1 -# end - -# @testset "Expression Parsing || corner cases" begin -# @testset "Corner Cases - 1 : sign convertor special case" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "minlp_solver" => JUNIPER, -# "log_level" => 100, -# ) - -# m = Model(test_solver) -# @variable(m, 0 <= x[1:5] <= 1, Bin) -# @NLconstraint(m, x[1] + -x[2] >= 2) -# @objective(m, Min, x[1] + x[2]) -# alpine = _build(m) - -# @test alpine.bounding_constr_mip[1][:rhs] == 2.0 -# @test alpine.bounding_constr_mip[1][:vars] == Any[:(x[1]), :(x[2])] -# @test alpine.bounding_constr_mip[1][:coefs] == Any[1.0, -1.0] -# @test alpine.bounding_constr_mip[1][:sense] == :(>=) -# @test alpine.bounding_constr_mip[1][:cnt] == 2 -# end - -# @testset "Corner Cases - 2 : full sub-expression" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "log_level" => 100, -# ) - -# m = Model(test_solver) -# @variable(m, x[1:5] >= 0) -# @NLconstraint(m, (x[1] + 10 + 4 * x[2] + 200) * 5 >= 2 * 5) -# @constraint(m, x[1] + x[2] + 200 >= 2) -# @objective(m, Min, x[1] + x[2]) -# alpine = _build(m) - -# @test alpine.bounding_constr_mip[1][:rhs] == -198.0 -# @test alpine.bounding_constr_mip[1][:vars] == Any[:(x[1]), :(x[2])] -# @test alpine.bounding_constr_mip[1][:coefs] == Any[1.0, 1.0] -# @test alpine.bounding_constr_mip[1][:sense] == :(>=) -# @test alpine.bounding_constr_mip[1][:cnt] == 2 -# @test alpine.bounding_constr_mip[2][:rhs] == -1040.0 -# @test alpine.bounding_constr_mip[2][:vars] == Any[:(x[1]), :(x[2])] -# @test alpine.bounding_constr_mip[2][:coefs] == Any[5.0, 20.0] -# @test alpine.bounding_constr_mip[2][:sense] == :(>=) -# @test alpine.bounding_constr_mip[2][:cnt] == 2 -# end - -# @testset "Corner Cases - 2 : full sub-expression" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "log_level" => 100, -# ) - -# m = Model(test_solver) -# @variable(m, x[1:5] >= 0) -# @NLconstraint(m, (x[1] + 10 + 4 * x[2] + 200) * 5 >= 2 * 5) -# @constraint(m, x[1] + x[2] + 200 >= 2) -# @objective(m, Min, x[1] + x[2]) -# alpine = _build(m) - -# @test alpine.bounding_constr_mip[1][:rhs] == -198.0 -# @test alpine.bounding_constr_mip[1][:vars] == Any[:(x[1]), :(x[2])] -# @test alpine.bounding_constr_mip[1][:coefs] == Any[1.0, 1.0] -# @test alpine.bounding_constr_mip[1][:sense] == :(>=) -# @test alpine.bounding_constr_mip[1][:cnt] == 2 -# @test alpine.bounding_constr_mip[2][:rhs] == -1040.0 -# @test alpine.bounding_constr_mip[2][:vars] == Any[:(x[1]), :(x[2])] -# @test alpine.bounding_constr_mip[2][:coefs] == Any[5.0, 20.0] -# @test alpine.bounding_constr_mip[2][:sense] == :(>=) -# @test alpine.bounding_constr_mip[2][:cnt] == 2 -# end -# end - -# @testset "Expression Parsing || Discrete Multilinear" begin -# @testset "Expression Parsing || bmpl && binlin && binprod" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "minlp_solver" => JUNIPER, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "log_level" => 100, -# ) - -# m = bpml(solver = test_solver) - -# alpine = _build(m) # Setup internal model - -# @test length(keys(alpine.nonconvex_terms)) == 12 - -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[6])]][:y_idx] == 11 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2])]][:y_idx] == 12 -# @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[6])]][:y_idx] == 13 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3])]][:y_idx] == 14 -# @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[6])]][:y_idx] == 15 -# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[7])]][:y_idx] == 16 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[16])]][:y_idx] == 17 -# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[7]), :(x[8])]][:y_idx] == 18 -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[18])]][:y_idx] == 19 -# @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[18])]][:y_idx] == 20 -# @test alpine.nonconvex_terms[Expr[ -# :(x[1]), -# :(x[2]), -# :(x[3]), -# :(x[4]), -# :(x[5]), -# ]][:y_idx] == 21 -# @test alpine.nonconvex_terms[Expr[ -# :(x[6]), -# :(x[7]), -# :(x[9]), -# :(x[10]), -# :(x[6]), -# ]][:y_idx] == 22 - -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[6])]][:nonlinear_type] == :BINLIN -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2])]][:nonlinear_type] == :BINPROD -# @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[6])]][:nonlinear_type] == :BINLIN -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3])]][:nonlinear_type] == -# :BINPROD -# @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[6])]][:nonlinear_type] == :BINLIN -# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[7])]][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[16])]][:nonlinear_type] == :BINLIN -# @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[7]), :(x[8])]][:nonlinear_type] == -# :MULTILINEAR -# @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[18])]][:nonlinear_type] == :BINLIN -# @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[18])]][:nonlinear_type] == :BINLIN -# @test alpine.nonconvex_terms[Expr[ -# :(x[1]), -# :(x[2]), -# :(x[3]), -# :(x[4]), -# :(x[5]), -# ]][:nonlinear_type] == :BINPROD -# @test alpine.nonconvex_terms[Expr[ -# :(x[6]), -# :(x[7]), -# :(x[9]), -# :(x[10]), -# :(x[6]), -# ]][:nonlinear_type] == :MULTILINEAR - -# @test length(alpine.var_type) == 22 -# @test alpine.var_type[11] == :Cont -# @test alpine.var_type[12] == :Bin -# @test alpine.var_type[13] == :Cont -# @test alpine.var_type[14] == :Bin -# @test alpine.var_type[15] == :Cont -# @test alpine.var_type[16] == :Cont -# @test alpine.var_type[17] == :Cont -# @test alpine.var_type[18] == :Cont -# @test alpine.var_type[19] == :Cont -# @test alpine.var_type[20] == :Cont -# @test alpine.var_type[21] == :Bin -# @test alpine.var_type[22] == :Cont -# end - -# @testset "Expression Parsing || bmpl && binlin && binprod with linear lifting and coefficients" begin -# test_solver = optimizer_with_attributes( -# Alpine.Optimizer, -# "minlp_solver" => JUNIPER, -# "nlp_solver" => IPOPT, -# "mip_solver" => HIGHS, -# "log_level" => 100, -# ) - -# m = bmpl_linearlifting(solver = test_solver) - -# alpine = _build(m) - -# lk1 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1), (1.0, 17)])), -# ) -# lk2 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 11), (1.0, 12)])), -# ) -# lk3 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 7), (2.0, 6)])), -# ) -# lk4 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6), (1.0, 19)])), -# ) -# lk5 = Dict{Symbol,Any}( -# Pair{Symbol,Any}(:sign, :+), -# Pair{Symbol,Any}(:scalar, 0.0), -# Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6), (1.0, 25)])), -# ) - -# @test haskey(alpine.linear_terms, lk1) -# @test haskey(alpine.linear_terms, lk2) -# @test haskey(alpine.linear_terms, lk3) -# @test haskey(alpine.linear_terms, lk4) -# @test haskey(alpine.linear_terms, lk5) - -# @test alpine.linear_terms[lk1][:lifted_constr_ref] == :(x[20] == x[1] + x[17]) -# @test alpine.linear_terms[lk2][:lifted_constr_ref] == :(x[13] == x[11] + x[12]) -# @test alpine.linear_terms[lk3][:lifted_constr_ref] == :(x[15] == 2 * x[6] + x[7]) -# @test alpine.linear_terms[lk4][:lifted_constr_ref] == :(x[21] == x[6] + x[19]) -# @test alpine.linear_terms[lk5][:lifted_constr_ref] == :(x[26] == x[6] + x[25]) - -# @test alpine.linear_terms[lk1][:y_idx] == 20 -# @test alpine.linear_terms[lk2][:y_idx] == 13 -# @test alpine.linear_terms[lk3][:y_idx] == 15 -# @test alpine.linear_terms[lk4][:y_idx] == 21 -# @test alpine.linear_terms[lk5][:y_idx] == 26 - -# @test alpine.linear_terms[lk1][:y_type] == :Cont -# @test alpine.linear_terms[lk2][:y_type] == :Cont -# @test alpine.linear_terms[lk3][:y_type] == :Cont -# @test alpine.linear_terms[lk4][:y_type] == :Cont -# @test alpine.linear_terms[lk5][:y_type] == :Cont - -# nlk1 = Expr[:(x[18]), :(x[7])] -# nlk2 = Expr[:(x[6]), :(x[7]), :(x[8])] -# nlk3 = Expr[:(x[7]), :(x[10])] -# nlk4 = Expr[:(x[2]), :(x[26])] -# nlk5 = Expr[:(x[1]), :(x[13])] -# nlk6 = Expr[:(x[1]), :(x[15])] -# nlk7 = Expr[:(x[2]), :(x[6])] -# nlk8 = Expr[:(x[24]), :(x[23])] -# nlk9 = Expr[:(x[1]), :(x[2])] -# nlk10 = Expr[:(x[2]), :(x[3])] -# nlk11 = Expr[:(x[20]), :(x[21])] -# nlk12 = Expr[:(x[3]), :(x[4])] - -# @test haskey(alpine.nonconvex_terms, nlk1) -# @test haskey(alpine.nonconvex_terms, nlk2) -# @test haskey(alpine.nonconvex_terms, nlk3) -# @test haskey(alpine.nonconvex_terms, nlk4) -# @test haskey(alpine.nonconvex_terms, nlk5) -# @test haskey(alpine.nonconvex_terms, nlk6) -# @test haskey(alpine.nonconvex_terms, nlk7) -# @test haskey(alpine.nonconvex_terms, nlk8) -# @test haskey(alpine.nonconvex_terms, nlk9) -# @test haskey(alpine.nonconvex_terms, nlk10) -# @test haskey(alpine.nonconvex_terms, nlk11) -# @test haskey(alpine.nonconvex_terms, nlk12) - -# @test alpine.nonconvex_terms[nlk1][:id] == 7 -# @test alpine.nonconvex_terms[nlk2][:id] == 1 -# @test alpine.nonconvex_terms[nlk3][:id] == 9 -# @test alpine.nonconvex_terms[nlk4][:id] == 12 -# @test alpine.nonconvex_terms[nlk5][:id] == 3 -# @test alpine.nonconvex_terms[nlk6][:id] == 4 -# @test alpine.nonconvex_terms[nlk7][:id] == 5 -# @test alpine.nonconvex_terms[nlk8][:id] == 11 -# @test alpine.nonconvex_terms[nlk9][:id] == 6 -# @test alpine.nonconvex_terms[nlk10][:id] == 2 -# @test alpine.nonconvex_terms[nlk11][:id] == 8 -# @test alpine.nonconvex_terms[nlk12][:id] == 10 - -# @test alpine.nonconvex_terms[nlk1][:y_type] == :Cont -# @test alpine.nonconvex_terms[nlk2][:y_type] == :Cont -# @test alpine.nonconvex_terms[nlk3][:y_type] == :Cont -# @test alpine.nonconvex_terms[nlk4][:y_type] == :Cont -# @test alpine.nonconvex_terms[nlk5][:y_type] == :Cont -# @test alpine.nonconvex_terms[nlk6][:y_type] == :Cont -# @test alpine.nonconvex_terms[nlk7][:y_type] == :Cont -# @test alpine.nonconvex_terms[nlk8][:y_type] == :Cont -# @test alpine.nonconvex_terms[nlk9][:y_type] == :Bin -# @test alpine.nonconvex_terms[nlk10][:y_type] == :Bin -# @test alpine.nonconvex_terms[nlk11][:y_type] == :Cont -# @test alpine.nonconvex_terms[nlk12][:y_type] == :Bin - -# @test alpine.nonconvex_terms[nlk1][:y_idx] == 19 -# @test alpine.nonconvex_terms[nlk2][:y_idx] == 11 -# @test alpine.nonconvex_terms[nlk3][:y_idx] == 23 -# @test alpine.nonconvex_terms[nlk4][:y_idx] == 27 -# @test alpine.nonconvex_terms[nlk5][:y_idx] == 14 -# @test alpine.nonconvex_terms[nlk6][:y_idx] == 16 -# @test alpine.nonconvex_terms[nlk7][:y_idx] == 17 -# @test alpine.nonconvex_terms[nlk8][:y_idx] == 25 -# @test alpine.nonconvex_terms[nlk9][:y_idx] == 18 -# @test alpine.nonconvex_terms[nlk10][:y_idx] == 12 -# @test alpine.nonconvex_terms[nlk11][:y_idx] == 22 -# @test alpine.nonconvex_terms[nlk12][:y_idx] == 24 - -# @test alpine.nonconvex_terms[nlk1][:nonlinear_type] == :BINLIN -# @test alpine.nonconvex_terms[nlk2][:nonlinear_type] == :MULTILINEAR -# @test alpine.nonconvex_terms[nlk3][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[nlk4][:nonlinear_type] == :BINLIN -# @test alpine.nonconvex_terms[nlk5][:nonlinear_type] == :BINLIN -# @test alpine.nonconvex_terms[nlk6][:nonlinear_type] == :BINLIN -# @test alpine.nonconvex_terms[nlk7][:nonlinear_type] == :BINLIN -# @test alpine.nonconvex_terms[nlk8][:nonlinear_type] == :BINLIN -# @test alpine.nonconvex_terms[nlk9][:nonlinear_type] == :BINPROD -# @test alpine.nonconvex_terms[nlk10][:nonlinear_type] == :BINPROD -# @test alpine.nonconvex_terms[nlk11][:nonlinear_type] == :BILINEAR -# @test alpine.nonconvex_terms[nlk12][:nonlinear_type] == :BINPROD -# end -# end +@testset "Expression Parsing || bilinear || Affine || exprs.jl" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "log_level" => 100, + ) + + m = exprstest(solver = test_solver) + + alpine = _build(m) + + ex = alpine.bounding_constr_expr_mip[1] + affdict = Alpine.expr_linear_to_affine(ex) + @test affdict[:coefs] == [-1.0] + @test affdict[:coefs] == alpine.bounding_constr_mip[1][:coefs] + @test affdict[:vars] == [:(x[1])] + @test affdict[:vars] == alpine.bounding_constr_mip[1][:vars] + @test isapprox(affdict[:rhs], 109.0; atol = 1e-3) + @test affdict[:rhs] == alpine.bounding_constr_mip[1][:rhs] + @test affdict[:sense] == :(<=) + @test affdict[:sense] == alpine.bounding_constr_mip[1][:sense] + + ex = alpine.bounding_constr_expr_mip[2] + affdict = Alpine.expr_linear_to_affine(ex) + @test affdict[:coefs] == [3.0, 3.0, 3.0, 3.0] + @test affdict[:coefs] == alpine.bounding_constr_mip[2][:coefs] + @test affdict[:vars] == [:(x[8]), :(x[9]), :(x[10]), :(x[11])] + @test affdict[:vars] == alpine.bounding_constr_mip[2][:vars] + @test isapprox(affdict[:rhs], 111.0; atol = 1e-3) + @test affdict[:rhs] == alpine.bounding_constr_mip[2][:rhs] + @test affdict[:sense] == :(>=) + @test affdict[:sense] == alpine.bounding_constr_mip[2][:sense] + + ex = alpine.bounding_constr_expr_mip[3] + affdict = Alpine.expr_linear_to_affine(ex) + @test affdict[:coefs] == [-1.0, 20.0] + @test affdict[:coefs] == alpine.bounding_constr_mip[3][:coefs] + @test affdict[:vars] == [:(x[12]), :(x[13])] + @test affdict[:vars] == alpine.bounding_constr_mip[3][:vars] + @test isapprox(affdict[:rhs], 222.0; atol = 1e-3) + @test affdict[:rhs] == alpine.bounding_constr_mip[3][:rhs] + @test affdict[:sense] == :(>=) + @test affdict[:sense] == alpine.bounding_constr_mip[3][:sense] + + # 1.0 * x[12] - 115.0 >= 0.0 + ex = alpine.bounding_constr_expr_mip[4] + affdict = Alpine.expr_linear_to_affine(ex) + @test affdict[:coefs] == [-1.0] + @test affdict[:coefs] == alpine.bounding_constr_mip[4][:coefs] + @test affdict[:vars] == [:(x[12])] + @test affdict[:vars] == alpine.bounding_constr_mip[4][:vars] + @test isapprox(affdict[:rhs], 115.0; atol = 1e-3) + @test affdict[:rhs] == alpine.bounding_constr_mip[4][:rhs] + @test affdict[:sense] == :(<=) + @test affdict[:sense] == alpine.bounding_constr_mip[4][:sense] + + # 1.0 * x[12] - 115.0 <= 0.0 + ex = alpine.bounding_constr_expr_mip[5] + affdict = Alpine.expr_linear_to_affine(ex) + @test affdict[:coefs] == [1.0] + @test affdict[:coefs] == alpine.bounding_constr_mip[5][:coefs] + @test affdict[:vars] == [:(x[12])] + @test affdict[:vars] == alpine.bounding_constr_mip[5][:vars] + @test isapprox(affdict[:rhs], 115.0; atol = 1e-3) + @test affdict[:rhs] == alpine.bounding_constr_mip[5][:rhs] + @test affdict[:sense] == :(>=) + @test affdict[:sense] == alpine.bounding_constr_mip[5][:sense] + + # -1.0 * x[12] - 115.0 >= 0.0 + ex = alpine.bounding_constr_expr_mip[6] + affdict = Alpine.expr_linear_to_affine(ex) + @test affdict[:coefs] == [-1.0] + @test affdict[:coefs] == alpine.bounding_constr_mip[6][:coefs] + @test affdict[:vars] == [:(x[12])] + @test affdict[:vars] == alpine.bounding_constr_mip[6][:vars] + @test isapprox(affdict[:rhs], 115.0; atol = 1e-3) + @test affdict[:rhs] == alpine.bounding_constr_mip[6][:rhs] + @test affdict[:sense] == :(<=) + @test affdict[:sense] == alpine.bounding_constr_mip[6][:sense] + + # (x[1] + 1.0 * x[14]) - 555.0 >= 0.0 + ex = alpine.bounding_constr_expr_mip[7] + affdict = Alpine.expr_linear_to_affine(ex) + @test affdict[:coefs] == [1.0, 1.0] + @test affdict[:coefs] == alpine.bounding_constr_mip[7][:coefs] + @test affdict[:vars] == [:(x[1]), :(x[14])] + @test affdict[:vars] == alpine.bounding_constr_mip[7][:vars] + @test isapprox(affdict[:rhs], 555.0; atol = 1e-3) + @test affdict[:rhs] == alpine.bounding_constr_mip[7][:rhs] + @test affdict[:sense] == :(>=) + @test affdict[:sense] == alpine.bounding_constr_mip[7][:sense] + + # ((x[8] - 7.0 * x[9]) + x[10] + x[4]) - 6666.0 <= 0.0 + ex = alpine.bounding_constr_expr_mip[8] + affdict = Alpine.expr_linear_to_affine(ex) + @test affdict[:coefs] == [1.0, -7.0, 1.0, 1.0] + @test affdict[:coefs] == alpine.bounding_constr_mip[8][:coefs] + @test affdict[:vars] == [:(x[8]), :(x[9]), :(x[10]), :(x[4])] + @test affdict[:vars] == alpine.bounding_constr_mip[8][:vars] + @test isapprox(affdict[:rhs], 6666.0; atol = 1e-3) + @test affdict[:rhs] == alpine.bounding_constr_mip[8][:rhs] + @test affdict[:sense] == :(<=) + @test affdict[:sense] == alpine.bounding_constr_mip[8][:sense] + + # ((13.0 * x[1] - x[2]) + 30.0 * x[3] + x[4]) - 77.0 >= 0.0 + ex = alpine.bounding_constr_expr_mip[9] + affdict = Alpine.expr_linear_to_affine(ex) + @test affdict[:coefs] == [13.0, -1.0, 30.0, 1.0] + @test affdict[:coefs] == alpine.bounding_constr_mip[9][:coefs] + @test affdict[:vars] == [:(x[1]), :(x[2]), :(x[3]), :(x[4])] + @test affdict[:vars] == alpine.bounding_constr_mip[9][:vars] + @test isapprox(affdict[:rhs], 77.0; atol = 1e-3) + @test affdict[:rhs] == alpine.bounding_constr_mip[9][:rhs] + @test affdict[:sense] == :(>=) + @test affdict[:sense] == alpine.bounding_constr_mip[9][:sense] +end + +@testset "Expression Parsing || bilinear || Affine || nlp1.jl" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "log_level" => 100, + ) + m = nlp1(solver = test_solver) + + alpine = _build(m) + + ex = alpine.bounding_constr_expr_mip[1] + affdict = Alpine.expr_linear_to_affine(ex) + @test affdict[:coefs] == [1.0] + @test affdict[:coefs] == alpine.bounding_constr_mip[1][:coefs] + @test affdict[:vars] == [:(x[5])] + @test affdict[:vars] == alpine.bounding_constr_mip[1][:vars] + @test isapprox(affdict[:rhs], 8.0; atol = 1e-3) + @test affdict[:rhs] == alpine.bounding_constr_mip[1][:rhs] + @test affdict[:sense] == :(>=) + @test affdict[:sense] == alpine.bounding_constr_mip[1][:sense] +end + +@testset "Expression Parsing || bilinear || Affine || nlp3.jl" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "log_level" => 100, + ) + + m = nlp3(solver = test_solver) + + alpine = _build(m) + + ex = alpine.bounding_constr_expr_mip[1] + affdict = Alpine.expr_linear_to_affine(ex) + @test affdict[:coefs] == [0.0025, 0.0025] + @test affdict[:coefs] == alpine.bounding_constr_mip[1][:coefs] + @test affdict[:vars] == [:(x[4]), :(x[6])] + @test affdict[:vars] == alpine.bounding_constr_mip[1][:vars] + @test isapprox(affdict[:rhs], 1.0; atol = 1e-3) + @test affdict[:rhs] == alpine.bounding_constr_mip[1][:rhs] + @test affdict[:sense] == :(<=) + @test affdict[:sense] == alpine.bounding_constr_mip[1][:sense] + + ex = alpine.bounding_constr_expr_mip[2] + affdict = Alpine.expr_linear_to_affine(ex) + @test affdict[:coefs] == [-0.0025, 0.0025, 0.0025] + @test affdict[:coefs] == alpine.bounding_constr_mip[2][:coefs] + @test affdict[:vars] == [:(x[4]), :(x[5]), :(x[7])] + @test affdict[:vars] == alpine.bounding_constr_mip[2][:vars] + @test isapprox(affdict[:rhs], 1.0; atol = 1e-3) + @test affdict[:rhs] == alpine.bounding_constr_mip[2][:rhs] + @test affdict[:sense] == :(<=) + @test affdict[:sense] == alpine.bounding_constr_mip[2][:sense] + + ex = alpine.bounding_constr_expr_mip[3] + affdict = Alpine.expr_linear_to_affine(ex) + @test affdict[:coefs] == [-0.01, 0.01] + @test affdict[:coefs] == alpine.bounding_constr_mip[3][:coefs] + @test affdict[:vars] == [:(x[5]), :(x[8])] + @test affdict[:vars] == alpine.bounding_constr_mip[3][:vars] + @test isapprox(affdict[:rhs], 1.0; atol = 1e-3) + @test affdict[:rhs] == alpine.bounding_constr_mip[3][:rhs] + @test affdict[:sense] == :(<=) + @test affdict[:sense] == alpine.bounding_constr_mip[3][:sense] + + ex = alpine.bounding_constr_expr_mip[4] + affdict = Alpine.expr_linear_to_affine(ex) + @test (affdict[:coefs] .== [100.0, -1.0, 833.33252]) == [true, true, true] + @test affdict[:coefs] == alpine.bounding_constr_mip[4][:coefs] + @test affdict[:vars] == [:(x[1]), :(x[9]), :(x[4])] + @test affdict[:vars] == alpine.bounding_constr_mip[4][:vars] + @test isapprox(affdict[:rhs], 83333.333; atol = 1e-3) + @test affdict[:rhs] == alpine.bounding_constr_mip[4][:rhs] + @test affdict[:sense] == :(<=) + @test affdict[:sense] == alpine.bounding_constr_mip[4][:sense] + + ex = alpine.bounding_constr_expr_mip[5] + affdict = Alpine.expr_linear_to_affine(ex) + @test affdict[:coefs] == [1.0, -1.0, -1250.0, 1250.0] + @test affdict[:coefs] == alpine.bounding_constr_mip[5][:coefs] + @test affdict[:vars] == [:(x[10]), :(x[11]), :(x[4]), :(x[5])] + @test affdict[:vars] == alpine.bounding_constr_mip[5][:vars] + @test isapprox(affdict[:rhs], 0.0; atol = 1e-3) + @test affdict[:rhs] == alpine.bounding_constr_mip[5][:rhs] + @test affdict[:sense] == :(<=) + @test affdict[:sense] == alpine.bounding_constr_mip[5][:sense] + + ex = alpine.bounding_constr_expr_mip[6] + affdict = Alpine.expr_linear_to_affine(ex) + @test affdict[:coefs] == [1.0, -1.0, -2500.0] + @test affdict[:coefs] == alpine.bounding_constr_mip[6][:coefs] + @test affdict[:vars] == [:(x[12]), :(x[13]), :(x[5])] + @test affdict[:vars] == alpine.bounding_constr_mip[6][:vars] + @test isapprox(affdict[:rhs], -1.25e6; atol = 1e-3) + @test affdict[:rhs] == alpine.bounding_constr_mip[6][:rhs] + @test affdict[:sense] == :(<=) + @test affdict[:sense] == alpine.bounding_constr_mip[6][:sense] +end + +@testset "Expression Parsing || bilinear || Simple || bi1.jl " begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "log_level" => 100, + ) + + m = operator_c(solver = test_solver) + + alpine = _build(m) # Setup internal model + + @test length(keys(alpine.nonconvex_terms)) == 8 + @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 1), Expr(:ref, :x, 1)]) + @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 2), Expr(:ref, :x, 2)]) + @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 3), Expr(:ref, :x, 3)]) + @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 4), Expr(:ref, :x, 4)]) + @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 2), Expr(:ref, :x, 3)]) + @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 3), Expr(:ref, :x, 4)]) + + # TODO setup detailed check on this problem +end +@testset "Expression Parsing || bilinear || Complex || blend029.jl " begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "minlp_solver" => JUNIPER, + "mip_solver" => HIGHS, + "log_level" => 100, + ) + + m = blend029(solver = test_solver) + + alpine = _build(m) # Setup internal model + + @test length(keys(alpine.nonconvex_terms)) == 28 + @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 37), Expr(:ref, :x, 55)]) + @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 38), Expr(:ref, :x, 56)]) + @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 37), Expr(:ref, :x, 26)]) + @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 43), Expr(:ref, :x, 26)]) + @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 47), Expr(:ref, :x, 59)]) + @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 48), Expr(:ref, :x, 60)]) + @test haskey(alpine.nonconvex_terms, [Expr(:ref, :x, 47), Expr(:ref, :x, 36)]) + + @test alpine.bounding_constr_mip[1][:rhs] == 1.0 + @test alpine.bounding_constr_mip[1][:vars] == + Any[:(x[1]), :(x[4]), :(x[7]), :(x[10]), :(x[49])] + @test alpine.bounding_constr_mip[1][:sense] == :(==) + @test alpine.bounding_constr_mip[1][:coefs] == Any[1.0, 1.0, 1.0, 1.0, 1.0] + @test alpine.bounding_constr_mip[1][:cnt] == 5 + + @test alpine.bounding_constr_mip[4][:rhs] == 0.1 + @test alpine.bounding_constr_mip[4][:vars] == + Any[:(x[4]), :(x[16]), :(x[25]), :(x[34]), :(x[58])] + @test alpine.bounding_constr_mip[4][:sense] == :(==) + @test alpine.bounding_constr_mip[4][:coefs] == Any[-1.0, -1.0, -1.0, 1.0, 1.0] + @test alpine.bounding_constr_mip[4][:cnt] == 5 + + @test alpine.bounding_constr_mip[17][:rhs] == -0.14 + @test alpine.bounding_constr_mip[17][:vars] == + Any[:(x[11]), :(x[23]), :(x[32]), :(x[64]), :(x[65])] + @test alpine.bounding_constr_mip[17][:sense] == :(==) + @test alpine.bounding_constr_mip[17][:coefs] == Any[-1.0, -1.0, -1.0, -1.0, 1.0] + @test alpine.bounding_constr_mip[17][:cnt] == 5 + + @test alpine.bounding_constr_mip[31][:rhs] == 0.0 + @test alpine.bounding_constr_mip[31][:vars] == Any[:(x[13])] + @test alpine.bounding_constr_mip[31][:sense] == :(>=) + @test alpine.bounding_constr_mip[31][:coefs] == Any[1.0] + @test alpine.bounding_constr_mip[31][:cnt] == 1 + + @test alpine.bounding_constr_mip[145][:rhs] == 1.0 + @test alpine.bounding_constr_mip[145][:vars] == Any[:(x[73])] + @test alpine.bounding_constr_mip[145][:sense] == :(<=) + @test alpine.bounding_constr_mip[145][:coefs] == Any[1.0] + @test alpine.bounding_constr_mip[145][:cnt] == 1 + + @test alpine.bounding_constr_mip[67][:rhs] == -1.0 + @test alpine.bounding_constr_mip[67][:vars] == Any[:(x[73])] + @test alpine.bounding_constr_mip[67][:sense] == :(>=) + @test alpine.bounding_constr_mip[67][:coefs] == Any[-1.0] + @test alpine.bounding_constr_mip[67][:cnt] == 1 + + @test alpine.bounding_constr_mip[187][:rhs] == 1.0 + @test alpine.bounding_constr_mip[187][:vars] == Any[:(x[79]), :(x[94])] + @test alpine.bounding_constr_mip[187][:sense] == :(<=) + @test alpine.bounding_constr_mip[187][:coefs] == Any[1.0, 1.0] + @test alpine.bounding_constr_mip[187][:cnt] == 2 + + @test alpine.bounding_constr_mip[202][:rhs] == 0.04 + @test alpine.bounding_constr_mip[202][:vars] == + Any[:(x[103]), :(x[1]), :(x[13]), :(x[25]), :(x[28]), :(x[31])] + @test alpine.bounding_constr_mip[202][:sense] == :(==) + @test alpine.bounding_constr_mip[202][:coefs] == Any[1.0, -0.6, -0.2, 0.2, 0.2, 0.2] + @test alpine.bounding_constr_mip[202][:cnt] == 6 + + @test alpine.nonconvex_terms[[:(x[37]), :(x[55])]][:id] == 1 + @test alpine.nonconvex_terms[[:(x[37]), :(x[55])]][:lifted_var_ref] == :(x[103]) + @test alpine.nonconvex_terms[[:(x[37]), :(x[55])]][:convexified] == false + @test alpine.nonconvex_terms[[:(x[37]), :(x[55])]][:nonlinear_type] == :BILINEAR + + @test alpine.bounding_constr_mip[206][:rhs] == 0.0 + @test alpine.bounding_constr_mip[206][:vars] == + Any[:(x[107]), :(x[103]), :(x[108]), :(x[109]), :(x[110]), :(x[2]), :(x[14])] + @test alpine.bounding_constr_mip[206][:sense] == :(==) + @test alpine.bounding_constr_mip[206][:coefs] == + Any[1.0, -1.0, 1.0, 1.0, 1.0, -0.6, -0.2] + @test alpine.bounding_constr_mip[206][:cnt] == 7 + + @test alpine.nonconvex_terms[[:(x[38]), :(x[56])]][:id] == 5 + @test alpine.nonconvex_terms[[:(x[38]), :(x[56])]][:lifted_var_ref] == :(x[107]) + @test alpine.nonconvex_terms[[:(x[38]), :(x[56])]][:convexified] == false + @test alpine.nonconvex_terms[[:(x[38]), :(x[56])]][:nonlinear_type] == :BILINEAR + + @test alpine.nonconvex_terms[[:(x[37]), :(x[26])]][:id] == 6 + @test alpine.nonconvex_terms[[:(x[37]), :(x[26])]][:lifted_var_ref] == :(x[108]) + @test alpine.nonconvex_terms[[:(x[37]), :(x[26])]][:convexified] == false + @test alpine.nonconvex_terms[[:(x[37]), :(x[26])]][:nonlinear_type] == :BILINEAR + + @test alpine.nonconvex_terms[[:(x[37]), :(x[32])]][:id] == 8 + @test alpine.nonconvex_terms[[:(x[37]), :(x[32])]][:lifted_var_ref] == :(x[110]) + @test alpine.nonconvex_terms[[:(x[37]), :(x[32])]][:convexified] == false + @test alpine.nonconvex_terms[[:(x[37]), :(x[32])]][:nonlinear_type] == :BILINEAR + + @test alpine.bounding_constr_mip[213][:rhs] == 0.0 + @test alpine.bounding_constr_mip[213][:vars] == + Any[:(x[129]), :(x[127]), :(x[124]), :(x[130]), :(x[6]), :(x[18])] + @test alpine.bounding_constr_mip[213][:sense] == :(==) + @test alpine.bounding_constr_mip[213][:coefs] == Any[1.0, -1.0, -1.0, 1.0, -0.4, -0.4] + @test alpine.bounding_constr_mip[213][:cnt] == 6 + + @test alpine.nonconvex_terms[[:(x[48]), :(x[60])]][:id] == 27 + @test alpine.nonconvex_terms[[:(x[48]), :(x[60])]][:lifted_var_ref] == :(x[129]) + @test alpine.nonconvex_terms[[:(x[48]), :(x[60])]][:convexified] == false + @test alpine.nonconvex_terms[[:(x[48]), :(x[60])]][:nonlinear_type] == :BILINEAR + + @test alpine.nonconvex_terms[[:(x[47]), :(x[59])]][:id] == 25 + @test alpine.nonconvex_terms[[:(x[47]), :(x[59])]][:lifted_var_ref] == :(x[127]) + @test alpine.nonconvex_terms[[:(x[47]), :(x[59])]][:convexified] == false + @test alpine.nonconvex_terms[[:(x[47]), :(x[59])]][:nonlinear_type] == :BILINEAR + + @test alpine.nonconvex_terms[[:(x[47]), :(x[36])]][:id] == 28 + @test alpine.nonconvex_terms[[:(x[47]), :(x[36])]][:lifted_var_ref] == :(x[130]) + @test alpine.nonconvex_terms[[:(x[47]), :(x[36])]][:convexified] == false + @test alpine.nonconvex_terms[[:(x[47]), :(x[36])]][:nonlinear_type] == :BILINEAR +end + +@testset "Expression Parsing || multilinear || Simple || multi.jl " begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "log_level" => 100, + ) + + m = multi3(solver = test_solver, exprmode = 1) + + alpine = _build(m) # Setup internal model + + @test length(keys(alpine.nonconvex_terms)) == 1 + @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3])]][:id] == 1 + @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3])]][:lifted_var_ref] == :(x[4]) + @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3])]][:nonlinear_type] == + :MULTILINEAR + + @test alpine.bounding_obj_mip[:rhs] == 0 + @test alpine.bounding_obj_mip[:vars] == Expr[:(x[4])] + @test alpine.bounding_obj_mip[:coefs] == [1.0] + @test alpine.bounding_obj_mip[:cnt] == 1 + @test alpine.bounding_obj_mip[:sense] === nothing + + @test alpine.bounding_constr_mip[1][:rhs] == 3.0 + @test alpine.bounding_constr_mip[1][:vars] == Any[:(x[1]), :(x[2]), :(x[3])] + @test alpine.bounding_constr_mip[1][:sense] == :(<=) + @test alpine.bounding_constr_mip[1][:coefs] == Any[1.0, 1.0, 1.0] + @test alpine.bounding_constr_mip[1][:cnt] == 3 + + m = multi3(solver = test_solver, exprmode = 2) + + alpine = _build(m) + + @test length(keys(alpine.nonconvex_terms)) == 2 + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:id] == 1 + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:lifted_var_ref] == + :(x[4]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[[Expr(:ref, :x, 4), Expr(:ref, :x, 3)]][:id] == 2 + @test alpine.nonconvex_terms[[Expr(:ref, :x, 4), Expr(:ref, :x, 3)]][:lifted_var_ref] == + :(x[5]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 4), Expr(:ref, :x, 3)]][:nonlinear_type] == + :BILINEAR + + @test alpine.bounding_obj_mip[:rhs] == 0 + @test alpine.bounding_obj_mip[:vars] == Expr[:(x[5])] + @test alpine.bounding_obj_mip[:coefs] == [1.0] + @test alpine.bounding_obj_mip[:cnt] == 1 + @test alpine.bounding_obj_mip[:sense] === nothing + + m = multi3(solver = test_solver, exprmode = 3) + + alpine = _build(m) + + @test length(keys(alpine.nonconvex_terms)) == 2 + @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:id] == 1 + @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:lifted_var_ref] == + :(x[4]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 4)]][:id] == 2 + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 4)]][:lifted_var_ref] == + :(x[5]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 4)]][:nonlinear_type] == + :BILINEAR + + @test alpine.bounding_obj_mip[:rhs] == 0 + @test alpine.bounding_obj_mip[:vars] == Expr[:(x[5])] + @test alpine.bounding_obj_mip[:coefs] == [1.0] + @test alpine.bounding_obj_mip[:cnt] == 1 + @test alpine.bounding_obj_mip[:sense] === nothing + + m = multi4(solver = test_solver, exprmode = 1) + + alpine = _build(m) + + @test length(keys(alpine.nonconvex_terms)) == 1 + + @test alpine.bounding_obj_mip[:rhs] == 0 + @test alpine.bounding_obj_mip[:vars] == Expr[:(x[5])] + @test alpine.bounding_obj_mip[:coefs] == [1.0] + @test alpine.bounding_obj_mip[:cnt] == 1 + @test alpine.bounding_obj_mip[:sense] === nothing + + @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:id] == 1 + @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:lifted_var_ref] == + :(x[5]) + @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:nonlinear_type] == + :MULTILINEAR + + @test alpine.bounding_constr_mip[1][:rhs] == 4.0 + @test alpine.bounding_constr_mip[1][:vars] == Any[:(x[1]), :(x[2]), :(x[3]), :(x[4])] + @test alpine.bounding_constr_mip[1][:sense] == :(<=) + @test alpine.bounding_constr_mip[1][:coefs] == Any[1.0, 1.0, 1.0, 1.0] + @test alpine.bounding_constr_mip[1][:cnt] == 4 + + m = multi4(solver = test_solver, exprmode = 2) + + alpine = _build(m) + + @test length(keys(alpine.nonconvex_terms)) == 3 + + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:id] == 1 + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:lifted_var_ref] == + :(x[5]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:id] == 2 + @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:lifted_var_ref] == + :(x[6]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[[Expr(:ref, :x, 5), Expr(:ref, :x, 6)]][:id] == 3 + @test alpine.nonconvex_terms[[Expr(:ref, :x, 5), Expr(:ref, :x, 6)]][:lifted_var_ref] == + :(x[7]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 5), Expr(:ref, :x, 6)]][:nonlinear_type] == + :BILINEAR + + @test alpine.bounding_obj_mip[:rhs] == 0 + @test alpine.bounding_obj_mip[:vars] == Expr[:(x[7])] + @test alpine.bounding_obj_mip[:coefs] == [1.0] + @test alpine.bounding_obj_mip[:cnt] == 1 + @test alpine.bounding_obj_mip[:sense] === nothing + + m = multi4(solver = test_solver, exprmode = 3) + + alpine = _build(m) + + @test length(keys(alpine.nonconvex_terms)) == 2 + + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:id] == 1 + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:lifted_var_ref] == + :(x[5]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[[:(x[5]), :(x[3]), :(x[4])]][:id] == 2 + @test alpine.nonconvex_terms[[:(x[5]), :(x[3]), :(x[4])]][:lifted_var_ref] == :(x[6]) + @test alpine.nonconvex_terms[[:(x[5]), :(x[3]), :(x[4])]][:nonlinear_type] == + :MULTILINEAR + + @test alpine.bounding_obj_mip[:rhs] == 0 + @test alpine.bounding_obj_mip[:vars] == Expr[:(x[6])] + @test alpine.bounding_obj_mip[:coefs] == [1.0] + @test alpine.bounding_obj_mip[:cnt] == 1 + @test alpine.bounding_obj_mip[:sense] === nothing + + m = multi4(solver = test_solver, exprmode = 4) + + alpine = _build(m) + + @test length(keys(alpine.nonconvex_terms)) == 2 + + @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:id] == 1 + @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:lifted_var_ref] == + :(x[5]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[5])]][:id] == 2 + @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[5])]][:lifted_var_ref] == :(x[6]) + @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[5])]][:nonlinear_type] == + :MULTILINEAR + + @test alpine.bounding_obj_mip[:rhs] == 0 + @test alpine.bounding_obj_mip[:vars] == Expr[:(x[6])] + @test alpine.bounding_obj_mip[:coefs] == [1.0] + @test alpine.bounding_obj_mip[:cnt] == 1 + @test alpine.bounding_obj_mip[:sense] === nothing + + @test alpine.bounding_obj_mip[:rhs] == 0 + @test alpine.bounding_obj_mip[:vars] == Expr[:(x[6])] + @test alpine.bounding_obj_mip[:coefs] == [1.0] + @test alpine.bounding_obj_mip[:cnt] == 1 + @test alpine.bounding_obj_mip[:sense] === nothing + + m = multi4(solver = test_solver, exprmode = 5) + + alpine = _build(m) + + @test length(keys(alpine.nonconvex_terms)) == 3 + + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:id] == 1 + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:lifted_var_ref] == + :(x[5]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 5)]][:id] == 2 + @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 5)]][:lifted_var_ref] == + :(x[6]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 5)]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[[Expr(:ref, :x, 6), Expr(:ref, :x, 4)]][:id] == 3 + @test alpine.nonconvex_terms[[Expr(:ref, :x, 6), Expr(:ref, :x, 4)]][:lifted_var_ref] == + :(x[7]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 6), Expr(:ref, :x, 4)]][:nonlinear_type] == + :BILINEAR + + @test alpine.bounding_obj_mip[:rhs] == 0 + @test alpine.bounding_obj_mip[:vars] == Expr[:(x[7])] + @test alpine.bounding_obj_mip[:coefs] == [1.0] + @test alpine.bounding_obj_mip[:cnt] == 1 + @test alpine.bounding_obj_mip[:sense] === nothing + + @test alpine.bounding_obj_mip[:rhs] == 0 + @test alpine.bounding_obj_mip[:vars] == Expr[:(x[7])] + @test alpine.bounding_obj_mip[:coefs] == [1.0] + @test alpine.bounding_obj_mip[:cnt] == 1 + @test alpine.bounding_obj_mip[:sense] === nothing + + m = multi4(solver = test_solver, exprmode = 6) + + alpine = _build(m) + + @test length(keys(alpine.nonconvex_terms)) == 2 + + @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3])]][:id] == 1 + @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3])]][:lifted_var_ref] == :(x[5]) + @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[[Expr(:ref, :x, 5), Expr(:ref, :x, 4)]][:id] == 2 + @test alpine.nonconvex_terms[[Expr(:ref, :x, 5), Expr(:ref, :x, 4)]][:lifted_var_ref] == + :(x[6]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 5), Expr(:ref, :x, 4)]][:nonlinear_type] == + :BILINEAR + + @test alpine.bounding_obj_mip[:rhs] == 0 + @test alpine.bounding_obj_mip[:vars] == Expr[:(x[6])] + @test alpine.bounding_obj_mip[:coefs] == [1.0] + @test alpine.bounding_obj_mip[:cnt] == 1 + @test alpine.bounding_obj_mip[:sense] === nothing + + m = multi4(solver = test_solver, exprmode = 7) + + alpine = _build(m) + + @test length(keys(alpine.nonconvex_terms)) == 3 + + @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:id] == 1 + @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:lifted_var_ref] == + :(x[5]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 3), Expr(:ref, :x, 4)]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 5)]][:id] == 2 + @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 5)]][:lifted_var_ref] == + :(x[6]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 5)]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 6)]][:id] == 3 + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 6)]][:lifted_var_ref] == + :(x[7]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 6)]][:nonlinear_type] == + :BILINEAR + + @test alpine.bounding_obj_mip[:rhs] == 0 + @test alpine.bounding_obj_mip[:vars] == Expr[:(x[7])] + @test alpine.bounding_obj_mip[:coefs] == [1.0] + @test alpine.bounding_obj_mip[:cnt] == 1 + @test alpine.bounding_obj_mip[:sense] === nothing + + m = multi4(solver = test_solver, exprmode = 8) + + alpine = _build(m) + + @test length(keys(alpine.nonconvex_terms)) == 2 + + @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:id] == 1 + @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:lifted_var_ref] == + :(x[5]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[[:(x[1]), :(x[5]), :(x[4])]][:id] == 2 + @test alpine.nonconvex_terms[[:(x[1]), :(x[5]), :(x[4])]][:lifted_var_ref] == :(x[6]) + @test alpine.nonconvex_terms[[:(x[1]), :(x[5]), :(x[4])]][:nonlinear_type] == + :MULTILINEAR + + @test alpine.bounding_obj_mip[:rhs] == 0 + @test alpine.bounding_obj_mip[:vars] == Expr[:(x[6])] + @test alpine.bounding_obj_mip[:coefs] == [1.0] + @test alpine.bounding_obj_mip[:cnt] == 1 + @test alpine.bounding_obj_mip[:sense] === nothing + + m = multi4(solver = test_solver, exprmode = 9) + + alpine = _build(m) + + @test length(keys(alpine.nonconvex_terms)) == 2 + + @test alpine.nonconvex_terms[[:(x[2]), :(x[3]), :(x[4])]][:id] == 1 + @test alpine.nonconvex_terms[[:(x[2]), :(x[3]), :(x[4])]][:lifted_var_ref] == :(x[5]) + @test alpine.nonconvex_terms[[:(x[2]), :(x[3]), :(x[4])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 5)]][:id] == 2 + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 5)]][:lifted_var_ref] == + :(x[6]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 5)]][:nonlinear_type] == + :BILINEAR + + @test alpine.bounding_obj_mip[:rhs] == 0 + @test alpine.bounding_obj_mip[:vars] == Expr[:(x[6])] + @test alpine.bounding_obj_mip[:coefs] == [1.0] + @test alpine.bounding_obj_mip[:cnt] == 1 + @test alpine.bounding_obj_mip[:sense] === nothing + + m = multi4(solver = test_solver, exprmode = 10) + + alpine = _build(m) + @test length(keys(alpine.nonconvex_terms)) == 3 + + @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:id] == 1 + @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:lifted_var_ref] == + :(x[5]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[[Expr(:ref, :x, 4), Expr(:ref, :x, 5)]][:id] == 2 + @test alpine.nonconvex_terms[[Expr(:ref, :x, 4), Expr(:ref, :x, 5)]][:lifted_var_ref] == + :(x[6]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 4), Expr(:ref, :x, 5)]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 6)]][:id] == 3 + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 6)]][:lifted_var_ref] == + :(x[7]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 6)]][:nonlinear_type] == + :BILINEAR + + @test alpine.bounding_obj_mip[:rhs] == 0 + @test alpine.bounding_obj_mip[:vars] == Expr[:(x[7])] + @test alpine.bounding_obj_mip[:coefs] == [1.0] + @test alpine.bounding_obj_mip[:cnt] == 1 + @test alpine.bounding_obj_mip[:sense] === nothing + + m = multi4(solver = test_solver, exprmode = 11) + + alpine = _build(m) + + @test length(keys(alpine.nonconvex_terms)) == 3 + + @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:id] == 1 + @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:lifted_var_ref] == + :(x[5]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 3)]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 5)]][:id] == 2 + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 5)]][:lifted_var_ref] == + :(x[6]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 5)]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[[Expr(:ref, :x, 6), Expr(:ref, :x, 4)]][:id] == 3 + @test alpine.nonconvex_terms[[Expr(:ref, :x, 6), Expr(:ref, :x, 4)]][:lifted_var_ref] == + :(x[7]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 6), Expr(:ref, :x, 4)]][:nonlinear_type] == + :BILINEAR + + @test alpine.bounding_obj_mip[:rhs] == 0 + @test alpine.bounding_obj_mip[:vars] == Expr[:(x[7])] + @test alpine.bounding_obj_mip[:coefs] == [1.0] + @test alpine.bounding_obj_mip[:cnt] == 1 + @test alpine.bounding_obj_mip[:sense] === nothing +end + +@testset "Expression Parsing || bilinear || Complex-div || div.jl" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "log_level" => 100, + ) + + m = div(solver = test_solver) + + alpine = _build(m) # Setup internal model + + @test length(keys(alpine.nonconvex_terms)) == 3 + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 1)]][:id] == 1 + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 1)]][:lifted_var_ref] == + :(x[3]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 1)]][:nonlinear_type] == + :MONOMIAL + + @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 2)]][:id] == 2 + @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 2)]][:lifted_var_ref] == + :(x[4]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 2), Expr(:ref, :x, 2)]][:nonlinear_type] == + :MONOMIAL + + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:id] == 3 + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:lifted_var_ref] == + :(x[5]) + @test alpine.nonconvex_terms[[Expr(:ref, :x, 1), Expr(:ref, :x, 2)]][:nonlinear_type] == + :BILINEAR + + aff_mip = alpine.bounding_constr_mip + + @test aff_mip[1][:rhs] == 0.0 + @test aff_mip[1][:vars] == Any[:(x[1])] + @test aff_mip[1][:sense] == :(>=) + @test round(aff_mip[1][:coefs][1]; digits = 1) == -3.0 + @test aff_mip[1][:cnt] == 1 + + @test aff_mip[2][:rhs] == 0.0 + @test aff_mip[2][:vars] == Any[:(x[2])] + @test aff_mip[2][:sense] == :(>=) + @test aff_mip[2][:coefs] == Any[0.25] + @test aff_mip[2][:cnt] == 1 + + @test aff_mip[3][:rhs] == 0.0 + @test aff_mip[3][:vars] == Any[:(x[2])] + @test aff_mip[3][:sense] == :(>=) + @test aff_mip[3][:coefs] == Any[5.0] + @test aff_mip[3][:cnt] == 1 + + @test aff_mip[4][:rhs] == 0.0 + @test aff_mip[4][:vars] == Any[:(x[2])] + @test aff_mip[4][:sense] == :(>=) + @test aff_mip[4][:coefs] == Any[-120.0] + @test aff_mip[4][:cnt] == 1 + + @test aff_mip[5][:rhs] == 0.0 + @test aff_mip[5][:vars] == Any[:(x[2])] + @test aff_mip[5][:sense] == :(>=) + @test aff_mip[5][:coefs] == Any[72000.0] + @test aff_mip[5][:cnt] == 1 + + @test aff_mip[6][:rhs] == 0.0 + @test aff_mip[6][:vars] == Any[:(x[1])] + @test aff_mip[6][:sense] == :(>=) + @test aff_mip[6][:coefs] == Any[72000.0] + @test aff_mip[6][:cnt] == 1 + + @test aff_mip[7][:rhs] == 8.0 + @test aff_mip[7][:vars] == Any[:(x[5])] + @test aff_mip[7][:sense] == :(>=) + @test aff_mip[7][:coefs] == Any[0.6] + @test aff_mip[7][:cnt] == 1 + + @test aff_mip[8][:rhs] == 0.0 + @test aff_mip[8][:vars] == Any[:(x[2]), :(x[5])] + @test aff_mip[8][:sense] == :(>=) + @test aff_mip[8][:coefs] == Any[5.6, -72000.0] + @test aff_mip[8][:cnt] == 2 + + @test aff_mip[9][:rhs] == 0.0 + @test aff_mip[9][:vars] == Any[:(x[2]), :(x[5])] + @test aff_mip[9][:sense] == :(>=) + @test aff_mip[9][:coefs] == Any[5.6, -36000.0] + @test aff_mip[9][:cnt] == 2 + + @test aff_mip[10][:rhs] == 0.0 + @test aff_mip[10][:vars] == Any[:(x[2]), :(x[5]), :(x[2])] + @test aff_mip[10][:sense] == :(>=) + @test aff_mip[10][:coefs] == Any[5.6, -300.0, -1.75] + @test aff_mip[10][:cnt] == 3 + + @test aff_mip[11][:rhs] == 0.0 + @test aff_mip[11][:vars] == Any[:(x[2]), :(x[1]), :(x[5])] + @test aff_mip[11][:sense] == :(>=) + @test aff_mip[11][:coefs] == Any[5.6, -0.5, 0.5] + @test aff_mip[11][:cnt] == 3 +end + +@testset "Expression Parsing || part1 " begin + m = Model( + optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "log_level" => 100, + ), + ) + @variable(m, x[1:4] >= 0) + @NLconstraint(m, x[1]^2 >= 1) # Basic monomial x[5]=x[1]^2 + @NLconstraint(m, x[1] * x[2] <= 1) # x[6] <= 1 : x[6] = x[1]*x[2] + @NLconstraint(m, x[1]^2 * x[2]^2 <= 1) # x[5] + x[7] <= 1 : x[7] = x[2]^2 + @NLconstraint(m, x[1] * (x[2] * x[3]) >= 1) # x[9] >= 1 : x[8] = x[2] * x[3] && x[9] = x[1]*x[8] + @NLconstraint(m, x[1]^2 * (x[2]^2 * x[3]^2) <= 1) # x[12] <= 1 : x[10] = x[3] ^ 2 && x[11] = x[7] * x[10] && x[12] = x[11]*[5] + + alpine = _build(m) + + @test alpine.bounding_constr_expr_mip[1] == :(x[5] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[2] == :(x[6] - 1.0 <= 0.0) + @test alpine.bounding_constr_expr_mip[3] == :(x[8] - 1.0 <= 0.0) + @test alpine.bounding_constr_expr_mip[4] == :(x[10] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[5] == :(x[13] - 1.0 <= 0.0) + @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[1])]) + @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2])]) + @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[2])]) + @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[3])]) + @test haskey(alpine.nonconvex_terms, [:(x[5]), :(x[7])]) + @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[9])]) + @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[3])]) + @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2])]) + @test haskey(alpine.nonconvex_terms, [:(x[5]), :(x[12])]) + + @test alpine.nonconvex_terms[[:(x[1]), :(x[1])]][:id] == 1 + @test alpine.nonconvex_terms[[:(x[1]), :(x[2])]][:id] == 2 + @test alpine.nonconvex_terms[[:(x[2]), :(x[2])]][:id] == 3 + @test alpine.nonconvex_terms[[:(x[5]), :(x[7])]][:id] == 4 + @test alpine.nonconvex_terms[[:(x[2]), :(x[3])]][:id] == 5 + @test alpine.nonconvex_terms[[:(x[1]), :(x[9])]][:id] == 6 + @test alpine.nonconvex_terms[[:(x[3]), :(x[3])]][:id] == 7 + @test alpine.nonconvex_terms[[:(x[7]), :(x[11])]][:id] == 8 + @test alpine.nonconvex_terms[[:(x[5]), :(x[12])]][:id] == 9 +end + +@testset "Expression Parsing || part2" begin + m = Model( + optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "log_level" => 100, + ), + ) + + @variable(m, x[1:4] >= 0) + @NLconstraint(m, (x[1] * x[2]) * x[3] >= 1) + @NLconstraint(m, (x[1]^2 * x[2]^2) * x[3]^2 <= 1) + + @NLconstraint(m, x[1] * (x[2]^2 * x[3]^2) >= 1) + @NLconstraint(m, (x[1]^2 * x[2]) * x[3]^2 <= 1) + @NLconstraint(m, x[1]^2 * (x[2] * x[3]) >= 1) + @NLconstraint(m, (x[1] * x[2]^2) * x[3] <= 1) + + alpine = _build(m) + + @test alpine.bounding_constr_expr_mip[1] == :(x[6] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[2] == :(x[11] - 1.0 <= 0.0) + @test alpine.bounding_constr_expr_mip[3] == :(x[13] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[4] == :(x[15] - 1.0 <= 0.0) + @test alpine.bounding_constr_expr_mip[5] == :(x[17] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[6] == :(x[19] - 1.0 <= 0.0) + + @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2])]) #5 + @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[5])]) #6 + @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[1])]) #7 + @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[2])]) #8 + @test haskey(alpine.nonconvex_terms, [:(x[7]), :(x[8])]) #9 + @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[3])]) #10 + @test haskey(alpine.nonconvex_terms, [:(x[9]), :(x[10])]) #11 + @test haskey(alpine.nonconvex_terms, [:(x[8]), :(x[10])]) #12 + @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[12])]) #13 + @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[7])]) #14 + @test haskey(alpine.nonconvex_terms, [:(x[14]), :(x[10])]) #15 + @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[3])]) #16 + @test haskey(alpine.nonconvex_terms, [:(x[7]), :(x[16])]) #17 + @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[8])]) #18 + @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[18])]) #19 + + @test alpine.nonconvex_terms[[:(x[1]), :(x[2])]][:id] == 1 + @test alpine.nonconvex_terms[[:(x[3]), :(x[5])]][:id] == 2 + @test alpine.nonconvex_terms[[:(x[1]), :(x[1])]][:id] == 3 + @test alpine.nonconvex_terms[[:(x[2]), :(x[2])]][:id] == 4 + @test alpine.nonconvex_terms[[:(x[7]), :(x[8])]][:id] == 5 + @test alpine.nonconvex_terms[[:(x[3]), :(x[3])]][:id] == 6 + @test alpine.nonconvex_terms[[:(x[9]), :(x[10])]][:id] == 7 + @test alpine.nonconvex_terms[[:(x[8]), :(x[10])]][:id] == 8 + @test alpine.nonconvex_terms[[:(x[1]), :(x[12])]][:id] == 9 + @test alpine.nonconvex_terms[[:(x[2]), :(x[7])]][:id] == 10 + @test alpine.nonconvex_terms[[:(x[14]), :(x[10])]][:id] == 11 + @test alpine.nonconvex_terms[[:(x[2]), :(x[3])]][:id] == 12 + @test alpine.nonconvex_terms[[:(x[7]), :(x[16])]][:id] == 13 + @test alpine.nonconvex_terms[[:(x[1]), :(x[8])]][:id] == 14 + @test alpine.nonconvex_terms[[:(x[3]), :(x[18])]][:id] == 15 +end + +@testset "Expression Parsing || part3" begin + m = Model( + optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "log_level" => 100, + ), + ) + + @variable(m, x[1:4] >= 0) + @NLconstraint(m, ((x[1] * x[2]) * x[3]) * x[4] >= 1) + @NLconstraint(m, ((x[1]^2 * x[2]) * x[3]) * x[4] <= 1) + @NLconstraint(m, ((x[1] * x[2]^2) * x[3]) * x[4] >= 1) + @NLconstraint(m, ((x[1] * x[2]) * x[3]^2) * x[4] <= 1) + @NLconstraint(m, ((x[1] * x[2]) * x[3]) * x[4]^2 >= 1) + @NLconstraint(m, ((x[1]^2 * x[2]^2) * x[3]^2) * x[4]^2 <= 1) + + alpine = _build(m) + + @test alpine.bounding_constr_expr_mip[1] == :(x[7] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[2] == :(x[11] - 1.0 <= 0.0) + @test alpine.bounding_constr_expr_mip[3] == :(x[15] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[4] == :(x[18] - 1.0 <= 0.0) + @test alpine.bounding_constr_expr_mip[5] == :(x[20] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[6] == :(x[23] - 1.0 <= 0.0) + + @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2])]) #5 + @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[5])]) #6 + @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[6])]) #7 + @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[1])]) #8 + @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[8])]) #9 + @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[9])]) #10 + @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[10])]) #11 + @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[2])]) #12 + @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[12])]) #13 + @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[13])]) #14 + @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[14])]) #15 + @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[3])]) #16 + @test haskey(alpine.nonconvex_terms, [:(x[5]), :(x[16])]) #17 + @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[17])]) #18 + @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[4])]) #19 + @test haskey(alpine.nonconvex_terms, [:(x[6]), :(x[19])]) #20 + @test haskey(alpine.nonconvex_terms, [:(x[8]), :(x[12])]) #21 + @test haskey(alpine.nonconvex_terms, [:(x[21]), :(x[16])]) #22 + @test haskey(alpine.nonconvex_terms, [:(x[22]), :(x[19])]) #23 + + @test alpine.nonconvex_terms[[:(x[1]), :(x[2])]][:id] == 1 + @test alpine.nonconvex_terms[[:(x[3]), :(x[5])]][:id] == 2 + @test alpine.nonconvex_terms[[:(x[4]), :(x[6])]][:id] == 3 + @test alpine.nonconvex_terms[[:(x[1]), :(x[1])]][:id] == 4 + @test alpine.nonconvex_terms[[:(x[2]), :(x[8])]][:id] == 5 + @test alpine.nonconvex_terms[[:(x[3]), :(x[9])]][:id] == 6 + @test alpine.nonconvex_terms[[:(x[4]), :(x[10])]][:id] == 7 + @test alpine.nonconvex_terms[[:(x[2]), :(x[2])]][:id] == 8 + @test alpine.nonconvex_terms[[:(x[1]), :(x[12])]][:id] == 9 + @test alpine.nonconvex_terms[[:(x[3]), :(x[13])]][:id] == 10 + @test alpine.nonconvex_terms[[:(x[4]), :(x[14])]][:id] == 11 + @test alpine.nonconvex_terms[[:(x[3]), :(x[3])]][:id] == 12 + @test alpine.nonconvex_terms[[:(x[5]), :(x[16])]][:id] == 13 + @test alpine.nonconvex_terms[[:(x[4]), :(x[17])]][:id] == 14 + @test alpine.nonconvex_terms[[:(x[4]), :(x[4])]][:id] == 15 + @test alpine.nonconvex_terms[[:(x[6]), :(x[19])]][:id] == 16 + @test alpine.nonconvex_terms[[:(x[8]), :(x[12])]][:id] == 17 + @test alpine.nonconvex_terms[[:(x[21]), :(x[16])]][:id] == 18 + @test alpine.nonconvex_terms[[:(x[22]), :(x[19])]][:id] == 19 +end + +@testset "Expression Parsing || part7" begin + m = Model( + optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "log_level" => 100, + ), + ) + @variable(m, x[1:4] >= 0) + + @NLconstraint(m, x[1] * x[2] * x[3] * x[4] >= 1) + @NLconstraint(m, x[1]^2 * x[2] * x[3] * x[4] >= 1) + @NLconstraint(m, x[1] * x[2]^2 * x[3] * x[4] >= 1) + @NLconstraint(m, x[1] * x[2] * x[3]^2 * x[4]^2 >= 1) + @NLconstraint(m, x[1] * x[2]^2 * x[3]^2 * x[4] >= 1) + @NLconstraint(m, x[1]^2 * x[2] * x[3] * x[4]^2 >= 1) + @NLconstraint(m, x[1]^2 * x[2]^2 * x[3]^2 * x[4]^2 >= 1) + + alpine = _build(m) + + @test alpine.bounding_constr_expr_mip[1] == :(x[5] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[2] == :(x[7] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[3] == :(x[9] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[4] == :(x[12] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[5] == :(x[13] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[6] == :(x[14] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[7] == :(x[15] - 1.0 >= 0.0) + + @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2]), :(x[3]), :(x[4])]) #5 + @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[1])]) #6 + @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[3]), :(x[4]), :(x[6])]) #7 + @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[2])]) #8 + @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[3]), :(x[4]), :(x[8])]) #9 + @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[3])]) #10 + @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[4])]) #11 + @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2]), :(x[10]), :(x[11])]) #12 + @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[4]), :(x[8]), :(x[10])]) #13 + @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[3]), :(x[6]), :(x[11])]) #14 + @test haskey(alpine.nonconvex_terms, [:(x[6]), :(x[8]), :(x[10]), :(x[11])]) #15 + + @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:id] == 1 #5 + @test alpine.nonconvex_terms[[:(x[1]), :(x[1])]][:id] == 2 #6 + @test alpine.nonconvex_terms[[:(x[2]), :(x[3]), :(x[4]), :(x[6])]][:id] == 3 #7 + @test alpine.nonconvex_terms[[:(x[2]), :(x[2])]][:id] == 4 #8 + @test alpine.nonconvex_terms[[:(x[1]), :(x[3]), :(x[4]), :(x[8])]][:id] == 5 #9 + @test alpine.nonconvex_terms[[:(x[3]), :(x[3])]][:id] == 6 #10 + @test alpine.nonconvex_terms[[:(x[4]), :(x[4])]][:id] == 7 #11 + @test alpine.nonconvex_terms[[:(x[1]), :(x[2]), :(x[10]), :(x[11])]][:id] == 8 #12 + @test alpine.nonconvex_terms[[:(x[1]), :(x[4]), :(x[8]), :(x[10])]][:id] == 9 #13 + @test alpine.nonconvex_terms[[:(x[2]), :(x[3]), :(x[6]), :(x[11])]][:id] == 10 #14 + @test alpine.nonconvex_terms[[:(x[6]), :(x[8]), :(x[10]), :(x[11])]][:id] == 11 #15 +end + +@testset "Expression Parsing || part8" begin + m = Model( + optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "log_level" => 100, + ), + ) + @variable(m, x[1:4] >= 0) + + @NLconstraint(m, (x[1] * x[2] * x[3]) * x[4] >= 1) + @NLconstraint(m, (x[1]^2 * x[2] * x[3]) * x[4] >= 1) + @NLconstraint(m, x[1] * (x[2]^2 * x[3]) * x[4] >= 1) + @NLconstraint(m, x[1] * (x[2] * x[3]^2) * x[4] >= 1) + @NLconstraint(m, (x[1] * x[2]^2) * x[3] * x[4] >= 1) + @NLconstraint(m, (x[1] * x[2]) * x[3]^2 * x[4] >= 1) + @NLconstraint(m, (x[1] * x[2]) * x[3] * x[4]^2 >= 1) + @NLconstraint(m, (x[1] * x[2]) * x[3]^2 * x[4]^2 >= 1) + @NLconstraint(m, (x[1]^2 * x[2]^2 * x[3]^2) * x[4]^2 >= 1) + + alpine = _build(m) + + @test alpine.bounding_constr_expr_mip[1] == :(x[6] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[2] == :(x[9] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[3] == :(x[12] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[4] == :(x[15] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[5] == :(x[17] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[6] == :(x[19] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[7] == :(x[21] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[8] == :(x[22] - 1.0 >= 0.0) + @test alpine.bounding_constr_expr_mip[9] == :(x[24] - 1.0 >= 0.0) + + @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2]), :(x[3])]) #5 + @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[5])]) #6 + @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[1])]) #7 + @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[3]), :(x[7])]) #8 + @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[8])]) #9 + @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[2])]) #10 + @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[10])]) #11 + @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[4]), :(x[11])]) #12 + @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[3])]) #13 + @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[13])]) #14 + @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[4]), :(x[14])]) #15 + @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[10])]) #16 + @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[4]), :(x[16])]) #17 + @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[2])]) #18 + @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[18]), :(x[13])]) #19 + @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[4])]) #20 + @test haskey(alpine.nonconvex_terms, [:(x[3]), :(x[18]), :(x[20])]) #21 + @test haskey(alpine.nonconvex_terms, [:(x[18]), :(x[13]), :(x[20])]) #22 + @test haskey(alpine.nonconvex_terms, [:(x[7]), :(x[10]), :(x[13])]) #23 + @test haskey(alpine.nonconvex_terms, [:(x[23]), :(x[20])]) #24 +end + +@testset "Expression Parsing || Convex" begin + @testset "Convex Parsing :: PART I" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "log_level" => 100, + ) + m = convex_test(solver = test_solver) + + alpine = _build(m) + + @test alpine.num_constr_convex == 21 + + # 0 : OBJ + @test alpine.obj_structure == :convex + @test alpine.nonlinear_constrs[0][:expr_orig] == :objective + @test alpine.nonlinear_constrs[0][:convex_type] == :convexA + @test alpine.nonlinear_constrs[0][:convexified] == false + + @test alpine.bounding_obj_mip[:sense] === nothing + @test alpine.bounding_obj_mip[:coefs] == [1.0, 1.0] + @test alpine.bounding_obj_mip[:vars] == [:(x[1]), :(x[3])] + @test alpine.bounding_obj_mip[:rhs] == 0.0 + @test alpine.bounding_obj_mip[:powers] == [2, 2] + @test alpine.bounding_obj_mip[:cnt] == 2 + + # 1 + @test alpine.constr_structure[1] == :convex + @test alpine.nonlinear_constrs[1][:expr_orig] == :constraints + @test alpine.nonlinear_constrs[1][:convex_type] == :convexA + @test alpine.nonlinear_constrs[1][:convexified] == false + @test alpine.bounding_constr_mip[1][:sense] == :(<=) + @test alpine.bounding_constr_mip[1][:coefs] == [3.0, 4.0] + @test alpine.bounding_constr_mip[1][:vars] == [:(x[1]), :(x[2])] + @test alpine.bounding_constr_mip[1][:rhs] == 25.0 + @test alpine.bounding_constr_mip[1][:powers] == [2, 2] + @test alpine.bounding_constr_mip[1][:cnt] == 2 + + # 2 + @test alpine.constr_structure[2] == :convex + @test alpine.nonlinear_constrs[2][:expr_orig] == :constraints + @test alpine.nonlinear_constrs[2][:convex_type] == :convexA + @test alpine.nonlinear_constrs[2][:convexified] == false + @test alpine.bounding_constr_mip[2][:sense] == :(<=) + @test alpine.bounding_constr_mip[2][:coefs] == [3.0, 4.0] + @test alpine.bounding_constr_mip[2][:vars] == [:(x[1]), :(x[2])] + @test alpine.bounding_constr_mip[2][:rhs] == 25.0 + @test alpine.bounding_constr_mip[2][:powers] == [2, 2] + @test alpine.bounding_constr_mip[2][:cnt] == 2 + + # 4 + @test alpine.constr_structure[4] == :convex + @test alpine.nonlinear_constrs[4][:expr_orig] == :constraints + @test alpine.nonlinear_constrs[4][:convex_type] == :convexA + @test alpine.nonlinear_constrs[4][:convexified] == false + @test alpine.bounding_constr_mip[4][:sense] == :(<=) + @test alpine.bounding_constr_mip[4][:coefs] == [3.0, 4.0] + @test alpine.bounding_constr_mip[4][:vars] == [:(x[1]), :(x[2])] + @test alpine.bounding_constr_mip[4][:rhs] == 10.0 + @test alpine.bounding_constr_mip[4][:powers] == [2, 2] + @test alpine.bounding_constr_mip[4][:cnt] == 2 + + # 5 + @test alpine.constr_structure[5] == :convex + @test alpine.nonlinear_constrs[5][:expr_orig] == :constraints + @test alpine.nonlinear_constrs[5][:convex_type] == :convexA + @test alpine.nonlinear_constrs[5][:convexified] == :false + @test alpine.bounding_constr_mip[5][:sense] == :(<=) + @test alpine.bounding_constr_mip[5][:coefs] == [3.0, 4.0, 6.0] + @test alpine.bounding_constr_mip[5][:vars] == [:(x[1]), :(x[2]), :(x[3])] + @test alpine.bounding_constr_mip[5][:rhs] == 10.0 + @test alpine.bounding_constr_mip[5][:powers] == [2, 2, 2] + @test alpine.bounding_constr_mip[5][:cnt] == 3 + + # 6 + @test alpine.constr_structure[6] == :convex + @test alpine.nonlinear_constrs[6][:expr_orig] == :constraints + @test alpine.nonlinear_constrs[6][:convex_type] == :convexC + @test alpine.nonlinear_constrs[6][:convexified] == :false + @test alpine.bounding_constr_mip[6][:sense] == :(<=) + @test alpine.bounding_constr_mip[6][:coefs] == [3.0, 4.0, 5.0] + @test alpine.bounding_constr_mip[6][:vars] == [:(x[1]), :(x[2]), :(x[5])] + @test alpine.bounding_constr_mip[6][:rhs] == 100.0 + @test alpine.bounding_constr_mip[6][:powers] == [0.5, 0.5, 0.5] + @test alpine.bounding_constr_mip[6][:cnt] == 3 + + # 7 + @test alpine.constr_structure[7] == :convex + @test alpine.nonlinear_constrs[7][:expr_orig] == :constraints + @test alpine.nonlinear_constrs[7][:convex_type] == :convexC + @test alpine.nonlinear_constrs[7][:convexified] == :false + @test alpine.bounding_constr_mip[7][:sense] == :(>=) + @test alpine.bounding_constr_mip[7][:coefs] == [-3.0, -4.0] + @test alpine.bounding_constr_mip[7][:vars] == [:(x[1]), :(x[2])] + @test alpine.bounding_constr_mip[7][:rhs] == -100.0 + @test alpine.bounding_constr_mip[7][:powers] == [0.5, 0.5] + @test alpine.bounding_constr_mip[7][:cnt] == 2 + + # 8 + @test alpine.constr_structure[8] == :convex + @test alpine.nonlinear_constrs[8][:expr_orig] == :constraints + @test alpine.nonlinear_constrs[8][:convex_type] == :convexB + @test alpine.nonlinear_constrs[8][:convexified] == :false + @test alpine.bounding_constr_mip[8][:sense] == :(<=) + @test alpine.bounding_constr_mip[8][:coefs] == [3.0, 1.0, 5.0] + @test alpine.bounding_constr_mip[8][:vars] == [:(x[1]), :(x[2]), :(x[3])] + @test alpine.bounding_constr_mip[8][:rhs] == 200.0 + @test alpine.bounding_constr_mip[8][:powers] == [3.0, 3.0, 3.0] + @test alpine.bounding_constr_mip[8][:cnt] == 3 + + # 9 + @test alpine.constr_structure[9] == :convex + @test alpine.nonlinear_constrs[9][:expr_orig] == :constraints + @test alpine.nonlinear_constrs[9][:convex_type] == :convexB + @test alpine.nonlinear_constrs[9][:convexified] == :false + @test alpine.bounding_constr_mip[9][:sense] == :(<=) + @test alpine.bounding_constr_mip[9][:coefs] == [1.0, 1.0, 1.0, 100.0] + @test alpine.bounding_constr_mip[9][:vars] == [:(x[1]), :(x[2]), :(x[3]), :(x[4])] + @test alpine.bounding_constr_mip[9][:rhs] == 200.0 + @test alpine.bounding_constr_mip[9][:powers] == [3, 3, 3, 3] + @test alpine.bounding_constr_mip[9][:cnt] == 4 + + # 11 + @test alpine.constr_structure[11] == :convex + @test alpine.nonlinear_constrs[11][:expr_orig] == :constraints + @test alpine.nonlinear_constrs[11][:convex_type] == :convexA + @test alpine.nonlinear_constrs[11][:convexified] == :false + @test alpine.bounding_constr_mip[11][:sense] == :(<=) + @test alpine.bounding_constr_mip[11][:coefs] == [3.0, 4.0] + @test alpine.bounding_constr_mip[11][:vars] == [:(x[1]), :(x[2])] + @test alpine.bounding_constr_mip[11][:rhs] == 25.0 + @test alpine.bounding_constr_mip[11][:powers] == [2, 2] + @test alpine.bounding_constr_mip[11][:cnt] == 2 + + # 14 + @test alpine.constr_structure[14] == :convex + @test alpine.nonlinear_constrs[14][:expr_orig] == :constraints + @test alpine.nonlinear_constrs[14][:convex_type] == :convexA + @test alpine.nonlinear_constrs[14][:convexified] == :false + @test alpine.bounding_constr_mip[14][:sense] == :(<=) + @test alpine.bounding_constr_mip[14][:coefs] == [3.0, 5.0] + @test alpine.bounding_constr_mip[14][:vars] == [:(x[1]), :(x[2])] + @test alpine.bounding_constr_mip[14][:rhs] == 25.0 + @test alpine.bounding_constr_mip[14][:powers] == [2, 2] + @test alpine.bounding_constr_mip[14][:cnt] == 2 + + # 15 + @test alpine.constr_structure[15] == :convex + @test alpine.nonlinear_constrs[15][:expr_orig] == :constraints + @test alpine.nonlinear_constrs[15][:convex_type] == :convexA + @test alpine.nonlinear_constrs[15][:convexified] == :false + @test alpine.bounding_constr_mip[15][:sense] == :(<=) + @test alpine.bounding_constr_mip[15][:coefs] == [3.0, 5.0, 1.0] + @test alpine.bounding_constr_mip[15][:vars] == [:(x[1]), :(x[2]), :(x[4])] + @test alpine.bounding_constr_mip[15][:rhs] == 25.0 + @test alpine.bounding_constr_mip[15][:powers] == [2, 2, 2] + @test alpine.bounding_constr_mip[15][:cnt] == 3 + + # 19 + @test alpine.constr_structure[19] == :convex + @test alpine.nonlinear_constrs[19][:expr_orig] == :constraints + @test alpine.nonlinear_constrs[19][:convex_type] == :convexA + @test alpine.nonlinear_constrs[19][:convexified] == :false + @test alpine.bounding_constr_mip[19][:sense] == :(<=) + @test alpine.bounding_constr_mip[19][:coefs] == [3.0, 16.0] + @test alpine.bounding_constr_mip[19][:vars] == [:(x[1]), :(x[2])] + @test alpine.bounding_constr_mip[19][:rhs] == 40.0 + @test alpine.bounding_constr_mip[19][:powers] == [2, 2] + @test alpine.bounding_constr_mip[19][:cnt] == 2 + + # 22 + @test alpine.constr_structure[22] == :convex + @test alpine.nonlinear_constrs[22][:expr_orig] == :constraints + @test alpine.nonlinear_constrs[22][:convex_type] == :convexA + @test alpine.nonlinear_constrs[22][:convexified] == :false + @test alpine.bounding_constr_mip[22][:sense] == :(<=) + @test alpine.bounding_constr_mip[22][:coefs] == [3.0, 4.0, 5.0, 6.0] + @test alpine.bounding_constr_mip[22][:vars] == + [:(x[1]), :(x[2]), :(x[3]), :(x[4])] + @test alpine.bounding_constr_mip[22][:rhs] == 15.0 + @test alpine.bounding_constr_mip[22][:powers] == [2, 2, 2, 2] + @test alpine.bounding_constr_mip[22][:cnt] == 4 + + # 25 + @test alpine.constr_structure[25] == :convex + @test alpine.nonlinear_constrs[25][:expr_orig] == :constraints + @test alpine.nonlinear_constrs[25][:convex_type] == :convexA + @test alpine.nonlinear_constrs[25][:convexified] == :false + @test alpine.bounding_constr_mip[25][:sense] == :(<=) + @test alpine.bounding_constr_mip[25][:coefs] == [1.0, 1.0, 1.0, 1.0, 1.0] + @test alpine.bounding_constr_mip[25][:vars] == + [:(x[1]), :(x[2]), :(x[3]), :(x[4]), :(x[5])] + @test alpine.bounding_constr_mip[25][:rhs] == 99999.0 + @test alpine.bounding_constr_mip[25][:powers] == [2, 2, 2, 2, 2] + @test alpine.bounding_constr_mip[25][:cnt] == 5 + + # 26 + @test alpine.constr_structure[26] == :convex + @test alpine.nonlinear_constrs[26][:expr_orig] == :constraints + @test alpine.nonlinear_constrs[26][:convex_type] == :convexA + @test alpine.nonlinear_constrs[26][:convexified] == :false + @test alpine.bounding_constr_mip[26][:sense] == :(<=) + @test alpine.bounding_constr_mip[26][:coefs] == [3.0, 4.0] + @test alpine.bounding_constr_mip[26][:vars] == [:(x[1]), :(x[2])] + @test alpine.bounding_constr_mip[26][:rhs] == 200.0 + @test alpine.bounding_constr_mip[26][:powers] == [4, 4] + @test alpine.bounding_constr_mip[26][:cnt] == 2 + end +end + +@testset "Expression Prasing || Linear Lifting" begin + @testset "Expression Parsing || Linear Lifting || nlp2" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "partition_scaling_factor" => 8, + "log_level" => 100, + ) + + m = nlp2(solver = test_solver) + + alpine = _build(m) + + @test length(alpine.linear_terms) == 2 + @test length(alpine.nonconvex_terms) == 4 + + lk = Vector{Any}(undef, 2) + lk[1] = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, -1.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3)])), + ) + lk[2] = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, -2.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6)])), + ) + + @test length(keys(alpine.linear_terms)) == 2 + yids = [4, 7] + for i in 1:length(keys(alpine.linear_terms)) + for j in keys(alpine.linear_terms) + if alpine.linear_terms[j][:id] == i + @test j == lk[i] + @test j[:sign] == :+ + @test j[:scalar] == lk[i][:scalar] + @test j[:coef_var] == lk[i][:coef_var] + @test alpine.linear_terms[j][:y_idx] == yids[i] + end + end + end + + @test haskey(alpine.linear_terms, lk[1]) + @test haskey(alpine.linear_terms, lk[2]) + + @test haskey(alpine.nonconvex_terms, [:(x[2]), :(x[2])]) + @test haskey(alpine.nonconvex_terms, [:(x[4]), :(x[4])]) + @test haskey(alpine.nonconvex_terms, [:(x[7]), :(x[7])]) + @test haskey(alpine.nonconvex_terms, [:(x[1]), :(x[1])]) + @test alpine.nonconvex_terms[[:(x[1]), :(x[1])]][:id] == 1 + @test alpine.nonconvex_terms[[:(x[2]), :(x[2])]][:id] == 3 + @test alpine.nonconvex_terms[[:(x[4]), :(x[4])]][:id] == 2 + @test alpine.nonconvex_terms[[:(x[7]), :(x[7])]][:id] == 4 + @test alpine.nonconvex_terms[[:(x[1]), :(x[1])]][:lifted_var_ref].args[2] == 3 + @test alpine.nonconvex_terms[[:(x[2]), :(x[2])]][:lifted_var_ref].args[2] == 6 + @test alpine.nonconvex_terms[[:(x[4]), :(x[4])]][:lifted_var_ref].args[2] == 5 + @test alpine.nonconvex_terms[[:(x[7]), :(x[7])]][:lifted_var_ref].args[2] == 8 + end + + @testset "Expression Parsing || Linear Lifting || general" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "log_level" => 100, + ) + + m = basic_linear_lift(solver = test_solver) + + alpine = _build(m) # Setup internal model + + lk = Vector{Any}(undef, 5) + lk[1] = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1), (-1.0, 2)])), + ) + lk[2] = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(3.0, 2), (-1.0, 3)])), + ) + lk[3] = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1), (1.0, 3)])), + ) + lk[4] = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 2), (1.0, 1)])), + ) + lk[5] = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 3.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 2), (1.0, 1), (1.0, 3)])), + ) + + @test length(keys(alpine.linear_terms)) == 5 + yids = [8, 9, 12, 14, 16] + for i in 1:length(keys(alpine.linear_terms)) + for j in keys(alpine.linear_terms) + if alpine.linear_terms[j][:id] == i + @test j == lk[i] + @test j[:sign] == :+ + @test j[:scalar] == lk[i][:scalar] + @test j[:coef_var] == lk[i][:coef_var] + @test alpine.linear_terms[j][:y_idx] == yids[i] + end + end + end + + nlk1 = [:(x[8]), :(x[9]), :(x[12])] + nlk2 = [:(x[2]), :(x[2])] + nlk3 = [:(x[2]), :(x[3])] + nlk4 = [:(x[8]), :(x[8])] + nlk5 = [:(x[1]), :(x[3])] + nlk6 = [:(x[8]), :(x[9])] + nlk7 = [:(x[1]), :(x[2])] + nlk8 = [:(x[16]), :(x[15])] + nlk9 = [:(x[14]), :(x[14])] + + @test alpine.nonconvex_terms[nlk1][:id] == 7 + @test alpine.nonconvex_terms[nlk2][:id] == 3 + @test alpine.nonconvex_terms[nlk3][:id] == 4 + @test alpine.nonconvex_terms[nlk4][:id] == 6 + @test alpine.nonconvex_terms[nlk5][:id] == 2 + @test alpine.nonconvex_terms[nlk6][:id] == 5 + @test alpine.nonconvex_terms[nlk7][:id] == 1 + @test alpine.nonconvex_terms[nlk8][:id] == 9 + @test alpine.nonconvex_terms[nlk9][:id] == 8 + + @test alpine.nonconvex_terms[nlk1][:lifted_var_ref].args[2] == 13 + @test alpine.nonconvex_terms[nlk2][:lifted_var_ref].args[2] == 6 + @test alpine.nonconvex_terms[nlk3][:lifted_var_ref].args[2] == 7 + @test alpine.nonconvex_terms[nlk4][:lifted_var_ref].args[2] == 11 + @test alpine.nonconvex_terms[nlk5][:lifted_var_ref].args[2] == 5 + @test alpine.nonconvex_terms[nlk6][:lifted_var_ref].args[2] == 10 + @test alpine.nonconvex_terms[nlk7][:lifted_var_ref].args[2] == 4 + @test alpine.nonconvex_terms[nlk8][:lifted_var_ref].args[2] == 17 + @test alpine.nonconvex_terms[nlk9][:lifted_var_ref].args[2] == 15 + + @test alpine.nonconvex_terms[nlk1][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[nlk2][:nonlinear_type] == :MONOMIAL + @test alpine.nonconvex_terms[nlk3][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[nlk4][:nonlinear_type] == :MONOMIAL + @test alpine.nonconvex_terms[nlk5][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[nlk6][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[nlk7][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[nlk8][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[nlk9][:nonlinear_type] == :MONOMIAL + + @test alpine.nonconvex_terms[nlk1][:var_idxs] == [8, 9, 12] + @test alpine.nonconvex_terms[nlk2][:var_idxs] == [2, 2] + @test alpine.nonconvex_terms[nlk3][:var_idxs] == [2, 3] + @test alpine.nonconvex_terms[nlk4][:var_idxs] == [8] + @test alpine.nonconvex_terms[nlk5][:var_idxs] == [1, 3] + @test alpine.nonconvex_terms[nlk6][:var_idxs] == [8, 9] + @test alpine.nonconvex_terms[nlk7][:var_idxs] == [1, 2] + @test alpine.nonconvex_terms[nlk8][:var_idxs] == [16, 15] + @test alpine.nonconvex_terms[nlk9][:var_idxs] == [14] + end + + @testset "Expression Parsing || Linear Lifting || brainpc3" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "partition_scaling_factor" => 8, + "log_level" => 100, + ) + + m = brainpc3(solver = test_solver) + + alpine = _build(m) + + @test alpine.nonconvex_terms[Expr[:(x[6912]), :(x[6912])]][:y_idx] == 6913 + @test alpine.nonconvex_terms[Expr[:(x[6912]), :(x[6912])]][:id] == 2 + @test alpine.nonconvex_terms[Expr[:(x[6912]), :(x[6912])]][:lifted_constr_ref] == + :(x[6913] == (*)(x[6912])) + @test alpine.nonconvex_terms[Expr[:(x[6912]), :(x[6912])]][:nonlinear_type] == + :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[6912]), :(x[6912])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6912]), :(x[6912])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6969])]][:y_idx] == 6970 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6969])]][:id] == 25 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6969])]][:lifted_constr_ref] == + :(x[6970] == x[6903] * x[6969]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6969])]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6969])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6969])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6914])]][:y_idx] == 6915 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6914])]][:id] == 3 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6914])]][:lifted_constr_ref] == + :(x[6915] == x[6903] * x[6914]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6914])]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6914])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6914])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6919])]][:y_idx] == 6920 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6919])]][:id] == 5 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6919])]][:lifted_constr_ref] == + :(x[6920] == x[6903] * x[6919]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6919])]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6919])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6919])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6927]), :(x[6927])]][:y_idx] == 6928 + @test alpine.nonconvex_terms[Expr[:(x[6927]), :(x[6927])]][:id] == 8 + @test alpine.nonconvex_terms[Expr[:(x[6927]), :(x[6927])]][:lifted_constr_ref] == + :(x[6928] == (*)(x[6927])) + @test alpine.nonconvex_terms[Expr[:(x[6927]), :(x[6927])]][:nonlinear_type] == + :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[6927]), :(x[6927])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6927]), :(x[6927])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6952]), :(x[6952])]][:y_idx] == 6953 + @test alpine.nonconvex_terms[Expr[:(x[6952]), :(x[6952])]][:id] == 18 + @test alpine.nonconvex_terms[Expr[:(x[6952]), :(x[6952])]][:lifted_constr_ref] == + :(x[6953] == (*)(x[6952])) + @test alpine.nonconvex_terms[Expr[:(x[6952]), :(x[6952])]][:nonlinear_type] == + :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[6952]), :(x[6952])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6952]), :(x[6952])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6962]), :(x[6962])]][:y_idx] == 6963 + @test alpine.nonconvex_terms[Expr[:(x[6962]), :(x[6962])]][:id] == 22 + @test alpine.nonconvex_terms[Expr[:(x[6962]), :(x[6962])]][:lifted_constr_ref] == + :(x[6963] == (*)(x[6962])) + @test alpine.nonconvex_terms[Expr[:(x[6962]), :(x[6962])]][:nonlinear_type] == + :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[6962]), :(x[6962])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6962]), :(x[6962])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6974])]][:y_idx] == 6975 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6974])]][:id] == 27 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6974])]][:lifted_constr_ref] == + :(x[6975] == x[6903] * x[6974]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6974])]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6974])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6974])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6934])]][:y_idx] == 6935 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6934])]][:id] == 11 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6934])]][:lifted_constr_ref] == + :(x[6935] == x[6903] * x[6934]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6934])]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6934])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6934])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6959])]][:y_idx] == 6960 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6959])]][:id] == 21 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6959])]][:lifted_constr_ref] == + :(x[6960] == x[6903] * x[6959]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6959])]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6959])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6959])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7014])]][:y_idx] == 7015 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7014])]][:id] == 43 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7014])]][:lifted_constr_ref] == + :(x[7015] == x[6903] * x[7014]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7014])]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7014])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7014])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6939])]][:y_idx] == 6940 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6939])]][:id] == 13 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6939])]][:lifted_constr_ref] == + :(x[6940] == x[6903] * x[6939]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6939])]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6939])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6939])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[7017]), :(x[7017])]][:y_idx] == 7018 + @test alpine.nonconvex_terms[Expr[:(x[7017]), :(x[7017])]][:id] == 44 + @test alpine.nonconvex_terms[Expr[:(x[7017]), :(x[7017])]][:lifted_constr_ref] == + :(x[7018] == (*)(x[7017])) + @test alpine.nonconvex_terms[Expr[:(x[7017]), :(x[7017])]][:nonlinear_type] == + :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[7017]), :(x[7017])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[7017]), :(x[7017])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6929])]][:y_idx] == 6930 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6929])]][:id] == 9 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6929])]][:lifted_constr_ref] == + :(x[6930] == x[6903] * x[6929]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6929])]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6929])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6929])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[7012]), :(x[7012])]][:y_idx] == 7013 + @test alpine.nonconvex_terms[Expr[:(x[7012]), :(x[7012])]][:id] == 42 + @test alpine.nonconvex_terms[Expr[:(x[7012]), :(x[7012])]][:lifted_constr_ref] == + :(x[7013] == (*)(x[7012])) + @test alpine.nonconvex_terms[Expr[:(x[7012]), :(x[7012])]][:nonlinear_type] == + :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[7012]), :(x[7012])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[7012]), :(x[7012])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6947]), :(x[6947])]][:y_idx] == 6948 + @test alpine.nonconvex_terms[Expr[:(x[6947]), :(x[6947])]][:id] == 16 + @test alpine.nonconvex_terms[Expr[:(x[6947]), :(x[6947])]][:lifted_constr_ref] == + :(x[6948] == (*)(x[6947])) + @test alpine.nonconvex_terms[Expr[:(x[6947]), :(x[6947])]][:nonlinear_type] == + :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[6947]), :(x[6947])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6947]), :(x[6947])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[7032]), :(x[7032])]][:y_idx] == 7033 + @test alpine.nonconvex_terms[Expr[:(x[7032]), :(x[7032])]][:id] == 50 + @test alpine.nonconvex_terms[Expr[:(x[7032]), :(x[7032])]][:lifted_constr_ref] == + :(x[7033] == (*)(x[7032])) + @test alpine.nonconvex_terms[Expr[:(x[7032]), :(x[7032])]][:nonlinear_type] == + :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[7032]), :(x[7032])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[7032]), :(x[7032])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6997]), :(x[6997])]][:y_idx] == 6998 + @test alpine.nonconvex_terms[Expr[:(x[6997]), :(x[6997])]][:id] == 36 + @test alpine.nonconvex_terms[Expr[:(x[6997]), :(x[6997])]][:lifted_constr_ref] == + :(x[6998] == (*)(x[6997])) + @test alpine.nonconvex_terms[Expr[:(x[6997]), :(x[6997])]][:nonlinear_type] == + :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[6997]), :(x[6997])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6997]), :(x[6997])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[7027]), :(x[7027])]][:y_idx] == 7028 + @test alpine.nonconvex_terms[Expr[:(x[7027]), :(x[7027])]][:id] == 48 + @test alpine.nonconvex_terms[Expr[:(x[7027]), :(x[7027])]][:lifted_constr_ref] == + :(x[7028] == (*)(x[7027])) + @test alpine.nonconvex_terms[Expr[:(x[7027]), :(x[7027])]][:nonlinear_type] == + :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[7027]), :(x[7027])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[7027]), :(x[7027])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[7037]), :(x[7037])]][:y_idx] == 7038 + @test alpine.nonconvex_terms[Expr[:(x[7037]), :(x[7037])]][:id] == 52 + @test alpine.nonconvex_terms[Expr[:(x[7037]), :(x[7037])]][:lifted_constr_ref] == + :(x[7038] == (*)(x[7037])) + @test alpine.nonconvex_terms[Expr[:(x[7037]), :(x[7037])]][:nonlinear_type] == + :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[7037]), :(x[7037])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[7037]), :(x[7037])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[7007]), :(x[7007])]][:y_idx] == 7008 + @test alpine.nonconvex_terms[Expr[:(x[7007]), :(x[7007])]][:id] == 40 + @test alpine.nonconvex_terms[Expr[:(x[7007]), :(x[7007])]][:lifted_constr_ref] == + :(x[7008] == (*)(x[7007])) + @test alpine.nonconvex_terms[Expr[:(x[7007]), :(x[7007])]][:nonlinear_type] == + :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[7007]), :(x[7007])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[7007]), :(x[7007])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6964])]][:y_idx] == 6965 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6964])]][:id] == 23 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6964])]][:lifted_constr_ref] == + :(x[6965] == x[6903] * x[6964]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6964])]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6964])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6964])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6924])]][:y_idx] == 6925 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6924])]][:id] == 7 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6924])]][:lifted_constr_ref] == + :(x[6925] == x[6903] * x[6924]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6924])]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6924])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6924])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6979])]][:y_idx] == 6980 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6979])]][:id] == 29 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6979])]][:lifted_constr_ref] == + :(x[6980] == x[6903] * x[6979]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6979])]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6979])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6979])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6994])]][:y_idx] == 6995 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6994])]][:id] == 35 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6994])]][:lifted_constr_ref] == + :(x[6995] == x[6903] * x[6994]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6994])]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6994])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6994])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6972]), :(x[6972])]][:y_idx] == 6973 + @test alpine.nonconvex_terms[Expr[:(x[6972]), :(x[6972])]][:id] == 26 + @test alpine.nonconvex_terms[Expr[:(x[6972]), :(x[6972])]][:lifted_constr_ref] == + :(x[6973] == (*)(x[6972])) + @test alpine.nonconvex_terms[Expr[:(x[6972]), :(x[6972])]][:nonlinear_type] == + :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[6972]), :(x[6972])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6972]), :(x[6972])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7019])]][:y_idx] == 7020 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7019])]][:id] == 45 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7019])]][:lifted_constr_ref] == + :(x[7020] == x[6903] * x[7019]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7019])]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7019])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7019])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6992]), :(x[6992])]][:y_idx] == 6993 + @test alpine.nonconvex_terms[Expr[:(x[6992]), :(x[6992])]][:id] == 34 + @test alpine.nonconvex_terms[Expr[:(x[6992]), :(x[6992])]][:lifted_constr_ref] == + :(x[6993] == (*)(x[6992])) + @test alpine.nonconvex_terms[Expr[:(x[6992]), :(x[6992])]][:nonlinear_type] == + :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[6992]), :(x[6992])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6992]), :(x[6992])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[7002]), :(x[7002])]][:y_idx] == 7003 + @test alpine.nonconvex_terms[Expr[:(x[7002]), :(x[7002])]][:id] == 38 + @test alpine.nonconvex_terms[Expr[:(x[7002]), :(x[7002])]][:lifted_constr_ref] == + :(x[7003] == (*)(x[7002])) + @test alpine.nonconvex_terms[Expr[:(x[7002]), :(x[7002])]][:nonlinear_type] == + :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[7002]), :(x[7002])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[7002]), :(x[7002])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[7022]), :(x[7022])]][:y_idx] == 7023 + @test alpine.nonconvex_terms[Expr[:(x[7022]), :(x[7022])]][:id] == 46 + @test alpine.nonconvex_terms[Expr[:(x[7022]), :(x[7022])]][:lifted_constr_ref] == + :(x[7023] == (*)(x[7022])) + @test alpine.nonconvex_terms[Expr[:(x[7022]), :(x[7022])]][:nonlinear_type] == + :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[7022]), :(x[7022])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[7022]), :(x[7022])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6908])]][:y_idx] == 6909 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6908])]][:id] == 1 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6908])]][:lifted_constr_ref] == + :(x[6909] == x[6903] * x[6908]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6908])]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6908])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6908])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6949])]][:y_idx] == 6950 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6949])]][:id] == 17 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6949])]][:lifted_constr_ref] == + :(x[6950] == x[6903] * x[6949]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6949])]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6949])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6949])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7004])]][:y_idx] == 7005 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7004])]][:id] == 39 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7004])]][:lifted_constr_ref] == + :(x[7005] == x[6903] * x[7004]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7004])]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7004])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7004])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6917]), :(x[6917])]][:y_idx] == 6918 + @test alpine.nonconvex_terms[Expr[:(x[6917]), :(x[6917])]][:id] == 4 + @test alpine.nonconvex_terms[Expr[:(x[6917]), :(x[6917])]][:lifted_constr_ref] == + :(x[6918] == (*)(x[6917])) + @test alpine.nonconvex_terms[Expr[:(x[6917]), :(x[6917])]][:nonlinear_type] == + :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[6917]), :(x[6917])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6917]), :(x[6917])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6937]), :(x[6937])]][:y_idx] == 6938 + @test alpine.nonconvex_terms[Expr[:(x[6937]), :(x[6937])]][:id] == 12 + @test alpine.nonconvex_terms[Expr[:(x[6937]), :(x[6937])]][:lifted_constr_ref] == + :(x[6938] == (*)(x[6937])) + @test alpine.nonconvex_terms[Expr[:(x[6937]), :(x[6937])]][:nonlinear_type] == + :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[6937]), :(x[6937])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6937]), :(x[6937])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6932]), :(x[6932])]][:y_idx] == 6933 + @test alpine.nonconvex_terms[Expr[:(x[6932]), :(x[6932])]][:id] == 10 + @test alpine.nonconvex_terms[Expr[:(x[6932]), :(x[6932])]][:lifted_constr_ref] == + :(x[6933] == (*)(x[6932])) + @test alpine.nonconvex_terms[Expr[:(x[6932]), :(x[6932])]][:nonlinear_type] == + :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[6932]), :(x[6932])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6932]), :(x[6932])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6989])]][:y_idx] == 6990 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6989])]][:id] == 33 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6989])]][:lifted_constr_ref] == + :(x[6990] == x[6903] * x[6989]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6989])]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6989])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6989])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6977]), :(x[6977])]][:y_idx] == 6978 + @test alpine.nonconvex_terms[Expr[:(x[6977]), :(x[6977])]][:id] == 28 + @test alpine.nonconvex_terms[Expr[:(x[6977]), :(x[6977])]][:lifted_constr_ref] == + :(x[6978] == (*)(x[6977])) + @test alpine.nonconvex_terms[Expr[:(x[6977]), :(x[6977])]][:nonlinear_type] == + :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[6977]), :(x[6977])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6977]), :(x[6977])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6987]), :(x[6987])]][:y_idx] == 6988 + @test alpine.nonconvex_terms[Expr[:(x[6987]), :(x[6987])]][:id] == 32 + @test alpine.nonconvex_terms[Expr[:(x[6987]), :(x[6987])]][:lifted_constr_ref] == + :(x[6988] == (*)(x[6987])) + @test alpine.nonconvex_terms[Expr[:(x[6987]), :(x[6987])]][:nonlinear_type] == + :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[6987]), :(x[6987])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6987]), :(x[6987])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7034])]][:y_idx] == 7035 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7034])]][:id] == 51 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7034])]][:lifted_constr_ref] == + :(x[7035] == x[6903] * x[7034]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7034])]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7034])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7034])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6967]), :(x[6967])]][:y_idx] == 6968 + @test alpine.nonconvex_terms[Expr[:(x[6967]), :(x[6967])]][:id] == 24 + @test alpine.nonconvex_terms[Expr[:(x[6967]), :(x[6967])]][:lifted_constr_ref] == + :(x[6968] == (*)(x[6967])) + @test alpine.nonconvex_terms[Expr[:(x[6967]), :(x[6967])]][:nonlinear_type] == + :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[6967]), :(x[6967])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6967]), :(x[6967])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6957]), :(x[6957])]][:y_idx] == 6958 + @test alpine.nonconvex_terms[Expr[:(x[6957]), :(x[6957])]][:id] == 20 + @test alpine.nonconvex_terms[Expr[:(x[6957]), :(x[6957])]][:lifted_constr_ref] == + :(x[6958] == (*)(x[6957])) + @test alpine.nonconvex_terms[Expr[:(x[6957]), :(x[6957])]][:nonlinear_type] == + :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[6957]), :(x[6957])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6957]), :(x[6957])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7009])]][:y_idx] == 7010 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7009])]][:id] == 41 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7009])]][:lifted_constr_ref] == + :(x[7010] == x[6903] * x[7009]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7009])]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7009])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7009])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6942]), :(x[6942])]][:y_idx] == 6943 + @test alpine.nonconvex_terms[Expr[:(x[6942]), :(x[6942])]][:id] == 14 + @test alpine.nonconvex_terms[Expr[:(x[6942]), :(x[6942])]][:lifted_constr_ref] == + :(x[6943] == (*)(x[6942])) + @test alpine.nonconvex_terms[Expr[:(x[6942]), :(x[6942])]][:nonlinear_type] == + :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[6942]), :(x[6942])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6942]), :(x[6942])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6982]), :(x[6982])]][:y_idx] == 6983 + @test alpine.nonconvex_terms[Expr[:(x[6982]), :(x[6982])]][:id] == 30 + @test alpine.nonconvex_terms[Expr[:(x[6982]), :(x[6982])]][:lifted_constr_ref] == + :(x[6983] == (*)(x[6982])) + @test alpine.nonconvex_terms[Expr[:(x[6982]), :(x[6982])]][:nonlinear_type] == + :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[6982]), :(x[6982])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6982]), :(x[6982])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6999])]][:y_idx] == 7000 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6999])]][:id] == 37 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6999])]][:lifted_constr_ref] == + :(x[7000] == x[6903] * x[6999]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6999])]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6999])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6999])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6944])]][:y_idx] == 6945 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6944])]][:id] == 15 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6944])]][:lifted_constr_ref] == + :(x[6945] == x[6903] * x[6944]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6944])]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6944])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6944])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7024])]][:y_idx] == 7025 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7024])]][:id] == 47 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7024])]][:lifted_constr_ref] == + :(x[7025] == x[6903] * x[7024]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7024])]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7024])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7024])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6954])]][:y_idx] == 6955 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6954])]][:id] == 19 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6954])]][:lifted_constr_ref] == + :(x[6955] == x[6903] * x[6954]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6954])]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6954])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6954])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6922]), :(x[6922])]][:y_idx] == 6923 + @test alpine.nonconvex_terms[Expr[:(x[6922]), :(x[6922])]][:id] == 6 + @test alpine.nonconvex_terms[Expr[:(x[6922]), :(x[6922])]][:lifted_constr_ref] == + :(x[6923] == (*)(x[6922])) + @test alpine.nonconvex_terms[Expr[:(x[6922]), :(x[6922])]][:nonlinear_type] == + :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[6922]), :(x[6922])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6922]), :(x[6922])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6984])]][:y_idx] == 6985 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6984])]][:id] == 31 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6984])]][:lifted_constr_ref] == + :(x[6985] == x[6903] * x[6984]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6984])]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6984])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[6984])]][:constr_id] == + Set(Any[0]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7029])]][:y_idx] == 7030 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7029])]][:id] == 49 + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7029])]][:lifted_constr_ref] == + :(x[7030] == x[6903] * x[7029]) + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7029])]][:nonlinear_type] == + :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7029])]][:y_type] == :Cont + @test alpine.nonconvex_terms[Expr[:(x[6903]), :(x[7029])]][:constr_id] == + Set(Any[0]) + lk1 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6910), (-1.0, 6909)])), + ) + @test alpine.linear_terms[lk1][:y_idx] == 6911 + @test alpine.linear_terms[lk1][:id] == 3 + @test alpine.linear_terms[lk1][:y_type] == :(Cont) + lk2 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3467), (1.0, 16)])), + ) + @test alpine.linear_terms[lk2][:y_idx] == 6908 + @test alpine.linear_terms[lk2][:id] == 1 + @test alpine.linear_terms[lk2][:y_type] == :(Cont) + lk3 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(0.001548, 6903), (1.0, 7016), (1.0, 5702)]), + ), + ) + @test alpine.linear_terms[lk3][:y_idx] == 7017 + @test alpine.linear_terms[lk3][:id] == 67 + @test alpine.linear_terms[lk3][:y_type] == :(Cont) + lk4 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 5162), (1.0, 1711)])), + ) + @test alpine.linear_terms[lk4][:y_idx] == 7004 + @test alpine.linear_terms[lk4][:id] == 59 + @test alpine.linear_terms[lk4][:y_type] == :(Cont) + lk5 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 7021), (0.001435, 6903), (1.0, 6002)]), + ), + ) + @test alpine.linear_terms[lk5][:y_idx] == 7022 + @test alpine.linear_terms[lk5][:id] == 70 + @test alpine.linear_terms[lk5][:y_type] == :(Cont) + lk6 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6935), (1.0, 166)])), + ) + @test alpine.linear_terms[lk6][:y_idx] == 6936 + @test alpine.linear_terms[lk6][:id] == 18 + @test alpine.linear_terms[lk6][:y_type] == :(Cont) + lk7 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 4262), (0.00247, 6903), (1.0, 6981)]), + ), + ) + @test alpine.linear_terms[lk7][:y_idx] == 6982 + @test alpine.linear_terms[lk7][:id] == 46 + @test alpine.linear_terms[lk7][:y_type] == :(Cont) + lk8 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 7005), (1.0, 1711)])), + ) + @test alpine.linear_terms[lk8][:y_idx] == 7006 + @test alpine.linear_terms[lk8][:id] == 60 + @test alpine.linear_terms[lk8][:y_type] == :(Cont) + lk9 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1951), (1.0, 5402)])), + ) + @test alpine.linear_terms[lk9][:y_idx] == 7009 + @test alpine.linear_terms[lk9][:id] == 62 + @test alpine.linear_terms[lk9][:y_type] == :(Cont) + lk10 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 226), (-1.0, 6945)])), + ) + @test alpine.linear_terms[lk10][:y_idx] == 6946 + @test alpine.linear_terms[lk10][:id] == 24 + @test alpine.linear_terms[lk10][:y_type] == :(Cont) + lk11 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 7030), (1.0, 3151)])), + ) + @test alpine.linear_terms[lk11][:y_idx] == 7031 + @test alpine.linear_terms[lk11][:id] == 75 + @test alpine.linear_terms[lk11][:y_type] == :(Cont) + lk12 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 6991), (1.0, 4622), (0.002066, 6903)]), + ), + ) + @test alpine.linear_terms[lk12][:y_idx] == 6992 + @test alpine.linear_terms[lk12][:id] == 52 + @test alpine.linear_terms[lk12][:y_type] == :(Cont) + lk13 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 7026), (1.0, 6302), (0.001323, 6903)]), + ), + ) + @test alpine.linear_terms[lk13][:y_idx] == 7027 + @test alpine.linear_terms[lk13][:id] == 73 + @test alpine.linear_terms[lk13][:y_type] == :(Cont) + lk14 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 46), (1.0, 3497)])), + ) + @test alpine.linear_terms[lk14][:y_idx] == 6914 + @test alpine.linear_terms[lk14][:id] == 5 + @test alpine.linear_terms[lk14][:y_type] == :(Cont) + lk15 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6960), (1.0, 391)])), + ) + @test alpine.linear_terms[lk15][:y_idx] == 6961 + @test alpine.linear_terms[lk15][:id] == 33 + @test alpine.linear_terms[lk15][:y_type] == :(Cont) + lk16 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 631), (-1.0, 6975)])), + ) + @test alpine.linear_terms[lk16][:y_idx] == 6976 + @test alpine.linear_terms[lk16][:id] == 42 + @test alpine.linear_terms[lk16][:y_type] == :(Cont) + lk17 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1351), (-1.0, 6995)])), + ) + @test alpine.linear_terms[lk17][:y_idx] == 6996 + @test alpine.linear_terms[lk17][:id] == 54 + @test alpine.linear_terms[lk17][:y_type] == :(Cont) + lk18 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3557), (1.0, 106)])), + ) + @test alpine.linear_terms[lk18][:y_idx] == 6924 + @test alpine.linear_terms[lk18][:id] == 11 + @test alpine.linear_terms[lk18][:y_type] == :(Cont) + lk19 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 3647), (1.0, 6941), (0.004795, 6903)]), + ), + ) + @test alpine.linear_terms[lk19][:y_idx] == 6942 + @test alpine.linear_terms[lk19][:id] == 22 + @test alpine.linear_terms[lk19][:y_type] == :(Cont) + lk20 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3722), (1.0, 271)])), + ) + @test alpine.linear_terms[lk20][:y_idx] == 6949 + @test alpine.linear_terms[lk20][:id] == 26 + @test alpine.linear_terms[lk20][:y_type] == :(Cont) + lk21 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3647), (1.0, 196)])), + ) + @test alpine.linear_terms[lk21][:y_idx] == 6939 + @test alpine.linear_terms[lk21][:id] == 20 + @test alpine.linear_terms[lk21][:y_type] == :(Cont) + lk22 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 3467), (1.0, 6911), (6.34e-6, 6903)]), + ), + ) + @test alpine.linear_terms[lk22][:y_idx] == 6912 + @test alpine.linear_terms[lk22][:id] == 4 + @test alpine.linear_terms[lk22][:y_type] == :(Cont) + lk23 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1531), (1.0, 4982)])), + ) + @test alpine.linear_terms[lk23][:y_idx] == 6999 + @test alpine.linear_terms[lk23][:id] == 56 + @test alpine.linear_terms[lk23][:y_type] == :(Cont) + lk24 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 106), (-1.0, 6925)])), + ) + @test alpine.linear_terms[lk24][:y_idx] == 6926 + @test alpine.linear_terms[lk24][:id] == 12 + @test alpine.linear_terms[lk24][:y_type] == :(Cont) + lk25 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 2251), (-1.0, 7015)])), + ) + @test alpine.linear_terms[lk25][:y_idx] == 7016 + @test alpine.linear_terms[lk25][:id] == 66 + @test alpine.linear_terms[lk25][:y_type] == :(Cont) + lk26 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 6936), (0.004985, 6903), (1.0, 3617)]), + ), + ) + @test alpine.linear_terms[lk26][:y_idx] == 6937 + @test alpine.linear_terms[lk26][:id] == 19 + @test alpine.linear_terms[lk26][:y_type] == :(Cont) + lk27 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6915), (1.0, 46)])), + ) + @test alpine.linear_terms[lk27][:y_idx] == 6916 + @test alpine.linear_terms[lk27][:id] == 6 + @test alpine.linear_terms[lk27][:y_type] == :(Cont) + lk28 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 3557), (0.005968, 6903), (1.0, 6926)]), + ), + ) + @test alpine.linear_terms[lk28][:y_idx] == 6927 + @test alpine.linear_terms[lk28][:id] == 13 + @test alpine.linear_terms[lk28][:y_type] == :(Cont) + lk29 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 271), (-1.0, 6950)])), + ) + @test alpine.linear_terms[lk29][:y_idx] == 6951 + @test alpine.linear_terms[lk29][:id] == 27 + @test alpine.linear_terms[lk29][:y_type] == :(Cont) + lk30 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(0.002971, 6903), (1.0, 6971), (1.0, 3962)]), + ), + ) + @test alpine.linear_terms[lk30][:y_idx] == 6972 + @test alpine.linear_terms[lk30][:id] == 40 + @test alpine.linear_terms[lk30][:y_type] == :(Cont) + lk31 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 511), (-1.0, 6970)])), + ) + @test alpine.linear_terms[lk31][:y_idx] == 6971 + @test alpine.linear_terms[lk31][:id] == 39 + @test alpine.linear_terms[lk31][:y_type] == :(Cont) + lk32 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 7031), (1.0, 6602), (0.00121, 6903)]), + ), + ) + @test alpine.linear_terms[lk32][:y_idx] == 7032 + @test alpine.linear_terms[lk32][:id] == 76 + @test alpine.linear_terms[lk32][:y_type] == :(Cont) + lk33 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(0.00166, 6903), (1.0, 7011), (1.0, 5402)]), + ), + ) + @test alpine.linear_terms[lk33][:y_idx] == 7012 + @test alpine.linear_terms[lk33][:id] == 64 + @test alpine.linear_terms[lk33][:y_type] == :(Cont) + lk34 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, -0.003214), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 16)])), + ) + @test alpine.linear_terms[lk34][:y_idx] == 6910 + @test alpine.linear_terms[lk34][:id] == 2 + @test alpine.linear_terms[lk34][:y_type] == :(Cont) + lk35 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 7035), (1.0, 3451)])), + ) + @test alpine.linear_terms[lk35][:y_idx] == 7036 + @test alpine.linear_terms[lk35][:id] == 78 + @test alpine.linear_terms[lk35][:y_type] == :(Cont) + lk36 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 2551), (1.0, 6002)])), + ) + @test alpine.linear_terms[lk36][:y_idx] == 7019 + @test alpine.linear_terms[lk36][:id] == 68 + @test alpine.linear_terms[lk36][:y_type] == :(Cont) + lk37 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3842), (1.0, 391)])), + ) + @test alpine.linear_terms[lk37][:y_idx] == 6959 + @test alpine.linear_terms[lk37][:id] == 32 + @test alpine.linear_terms[lk37][:y_type] == :(Cont) + lk38 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 6966), (0.00307, 6903), (1.0, 3902)]), + ), + ) + @test alpine.linear_terms[lk38][:y_idx] == 6967 + @test alpine.linear_terms[lk38][:id] == 37 + @test alpine.linear_terms[lk38][:y_type] == :(Cont) + lk39 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 3722), (0.003829, 6903), (1.0, 6951)]), + ), + ) + @test alpine.linear_terms[lk39][:y_idx] == 6952 + @test alpine.linear_terms[lk39][:id] == 28 + @test alpine.linear_terms[lk39][:y_type] == :(Cont) + lk40 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 451), (1.0, 3902)])), + ) + @test alpine.linear_terms[lk40][:y_idx] == 6964 + @test alpine.linear_terms[lk40][:id] == 35 + @test alpine.linear_terms[lk40][:y_type] == :(Cont) + lk41 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 7006), (1.0, 5162), (0.001713, 6903)]), + ), + ) + @test alpine.linear_terms[lk41][:y_idx] == 7007 + @test alpine.linear_terms[lk41][:id] == 61 + @test alpine.linear_terms[lk41][:y_type] == :(Cont) + lk42 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 811), (-1.0, 6980)])), + ) + @test alpine.linear_terms[lk42][:y_idx] == 6981 + @test alpine.linear_terms[lk42][:id] == 45 + @test alpine.linear_terms[lk42][:y_type] == :(Cont) + lk43 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 7001), (1.0, 4982), (0.00173, 6903)]), + ), + ) + @test alpine.linear_terms[lk43][:y_idx] == 7002 + @test alpine.linear_terms[lk43][:id] == 58 + @test alpine.linear_terms[lk43][:y_type] == :(Cont) + lk44 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6920), (1.0, 76)])), + ) + @test alpine.linear_terms[lk44][:y_idx] == 6921 + @test alpine.linear_terms[lk44][:id] == 9 + @test alpine.linear_terms[lk44][:y_type] == :(Cont) + lk45 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 4622), (1.0, 1171)])), + ) + @test alpine.linear_terms[lk45][:y_idx] == 6989 + @test alpine.linear_terms[lk45][:id] == 50 + @test alpine.linear_terms[lk45][:y_type] == :(Cont) + lk46 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 991), (1.0, 4442)])), + ) + @test alpine.linear_terms[lk46][:y_idx] == 6984 + @test alpine.linear_terms[lk46][:id] == 47 + @test alpine.linear_terms[lk46][:y_type] == :(Cont) + lk47 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6930), (1.0, 136)])), + ) + @test alpine.linear_terms[lk47][:y_idx] == 6931 + @test alpine.linear_terms[lk47][:id] == 15 + @test alpine.linear_terms[lk47][:y_type] == :(Cont) + lk48 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 4802), (0.001891, 6903), (1.0, 6996)]), + ), + ) + @test alpine.linear_terms[lk48][:y_idx] == 6997 + @test alpine.linear_terms[lk48][:id] == 55 + @test alpine.linear_terms[lk48][:y_type] == :(Cont) + lk49 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 511), (1.0, 3962)])), + ) + @test alpine.linear_terms[lk49][:y_idx] == 6969 + @test alpine.linear_terms[lk49][:id] == 38 + @test alpine.linear_terms[lk49][:y_type] == :(Cont) + lk50 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 811), (1.0, 4262)])), + ) + @test alpine.linear_terms[lk50][:y_idx] == 6979 + @test alpine.linear_terms[lk50][:id] == 44 + @test alpine.linear_terms[lk50][:y_type] == :(Cont) + lk51 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(0.01551, 6903), (1.0, 6916), (1.0, 3497)]), + ), + ) + @test alpine.linear_terms[lk51][:y_idx] == 6917 + @test alpine.linear_terms[lk51][:id] == 7 + @test alpine.linear_terms[lk51][:y_type] == :(Cont) + lk52 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 451), (-1.0, 6965)])), + ) + @test alpine.linear_terms[lk52][:y_idx] == 6966 + @test alpine.linear_terms[lk52][:id] == 36 + @test alpine.linear_terms[lk52][:y_type] == :(Cont) + lk53 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(0.005773, 6903), (1.0, 3587), (1.0, 6931)]), + ), + ) + @test alpine.linear_terms[lk53][:y_idx] == 6932 + @test alpine.linear_terms[lk53][:id] == 16 + @test alpine.linear_terms[lk53][:y_type] == :(Cont) + lk54 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 631), (1.0, 4082)])), + ) + @test alpine.linear_terms[lk54][:y_idx] == 6974 + @test alpine.linear_terms[lk54][:id] == 41 + @test alpine.linear_terms[lk54][:y_type] == :(Cont) + lk55 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 991), (-1.0, 6985)])), + ) + @test alpine.linear_terms[lk55][:y_idx] == 6986 + @test alpine.linear_terms[lk55][:id] == 48 + @test alpine.linear_terms[lk55][:y_type] == :(Cont) + lk56 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 4802), (1.0, 1351)])), + ) + @test alpine.linear_terms[lk56][:y_idx] == 6994 + @test alpine.linear_terms[lk56][:id] == 53 + @test alpine.linear_terms[lk56][:y_type] == :(Cont) + lk57 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 6946), (0.004409, 6903), (1.0, 3677)]), + ), + ) + @test alpine.linear_terms[lk57][:y_idx] == 6947 + @test alpine.linear_terms[lk57][:id] == 25 + @test alpine.linear_terms[lk57][:y_type] == :(Cont) + lk58 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 2251), (1.0, 5702)])), + ) + @test alpine.linear_terms[lk58][:y_idx] == 7014 + @test alpine.linear_terms[lk58][:id] == 65 + @test alpine.linear_terms[lk58][:y_type] == :(Cont) + lk59 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 7020), (1.0, 2551)])), + ) + @test alpine.linear_terms[lk59][:y_idx] == 7021 + @test alpine.linear_terms[lk59][:id] == 69 + @test alpine.linear_terms[lk59][:y_type] == :(Cont) + lk60 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6940), (1.0, 196)])), + ) + @test alpine.linear_terms[lk60][:y_idx] == 6941 + @test alpine.linear_terms[lk60][:id] == 21 + @test alpine.linear_terms[lk60][:y_type] == :(Cont) + lk61 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 3527), (1.0, 6921), (0.008919, 6903)]), + ), + ) + @test alpine.linear_terms[lk61][:y_idx] == 6922 + @test alpine.linear_terms[lk61][:id] == 10 + @test alpine.linear_terms[lk61][:y_type] == :(Cont) + lk62 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 7025), (1.0, 2851)])), + ) + @test alpine.linear_terms[lk62][:y_idx] == 7026 + @test alpine.linear_terms[lk62][:id] == 72 + @test alpine.linear_terms[lk62][:y_type] == :(Cont) + lk63 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 6986), (1.0, 4442), (0.002252, 6903)]), + ), + ) + @test alpine.linear_terms[lk63][:y_idx] == 6987 + @test alpine.linear_terms[lk63][:id] == 49 + @test alpine.linear_terms[lk63][:y_type] == :(Cont) + lk64 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(0.002765, 6903), (1.0, 6976), (1.0, 4082)]), + ), + ) + @test alpine.linear_terms[lk64][:y_idx] == 6977 + @test alpine.linear_terms[lk64][:id] == 43 + @test alpine.linear_terms[lk64][:y_type] == :(Cont) + lk65 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 6956), (0.003269, 6903), (1.0, 3782)]), + ), + ) + @test alpine.linear_terms[lk65][:y_idx] == 6957 + @test alpine.linear_terms[lk65][:id] == 31 + @test alpine.linear_terms[lk65][:y_type] == :(Cont) + lk66 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3587), (1.0, 136)])), + ) + @test alpine.linear_terms[lk66][:y_idx] == 6929 + @test alpine.linear_terms[lk66][:id] == 14 + @test alpine.linear_terms[lk66][:y_type] == :(Cont) + lk67 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 166), (1.0, 3617)])), + ) + @test alpine.linear_terms[lk67][:y_idx] == 6934 + @test alpine.linear_terms[lk67][:id] == 17 + @test alpine.linear_terms[lk67][:y_type] == :(Cont) + lk68 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 7010), (1.0, 1951)])), + ) + @test alpine.linear_terms[lk68][:y_idx] == 7011 + @test alpine.linear_terms[lk68][:id] == 63 + @test alpine.linear_terms[lk68][:y_type] == :(Cont) + lk69 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 7036), (0.001098, 6903), (1.0, 6902)]), + ), + ) + @test alpine.linear_terms[lk69][:y_idx] == 7037 + @test alpine.linear_terms[lk69][:id] == 79 + @test alpine.linear_terms[lk69][:y_type] == :(Cont) + lk70 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3527), (1.0, 76)])), + ) + @test alpine.linear_terms[lk70][:y_idx] == 6919 + @test alpine.linear_terms[lk70][:id] == 8 + @test alpine.linear_terms[lk70][:y_type] == :(Cont) + lk71 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}( + :coef_var, + Set(Any[(1.0, 6961), (1.0, 3842), (0.00317, 6903)]), + ), + ) + @test alpine.linear_terms[lk71][:y_idx] == 6962 + @test alpine.linear_terms[lk71][:id] == 34 + @test alpine.linear_terms[lk71][:y_type] == :(Cont) + lk72 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6990), (1.0, 1171)])), + ) + @test alpine.linear_terms[lk72][:y_idx] == 6991 + @test alpine.linear_terms[lk72][:id] == 51 + @test alpine.linear_terms[lk72][:y_type] == :(Cont) + lk73 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3451), (1.0, 6902)])), + ) + @test alpine.linear_terms[lk73][:y_idx] == 7034 + @test alpine.linear_terms[lk73][:id] == 77 + @test alpine.linear_terms[lk73][:y_type] == :(Cont) + lk74 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6302), (1.0, 2851)])), + ) + @test alpine.linear_terms[lk74][:y_idx] == 7024 + @test alpine.linear_terms[lk74][:id] == 71 + @test alpine.linear_terms[lk74][:y_type] == :(Cont) + lk75 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1531), (-1.0, 7000)])), + ) + @test alpine.linear_terms[lk75][:y_idx] == 7001 + @test alpine.linear_terms[lk75][:id] == 57 + @test alpine.linear_terms[lk75][:y_type] == :(Cont) + lk76 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3151), (1.0, 6602)])), + ) + @test alpine.linear_terms[lk76][:y_idx] == 7029 + @test alpine.linear_terms[lk76][:id] == 74 + @test alpine.linear_terms[lk76][:y_type] == :(Cont) + lk77 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 3782), (1.0, 331)])), + ) + @test alpine.linear_terms[lk77][:y_idx] == 6954 + @test alpine.linear_terms[lk77][:id] == 29 + @test alpine.linear_terms[lk77][:y_type] == :(Cont) + lk78 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(-1.0, 6955), (1.0, 331)])), + ) + @test alpine.linear_terms[lk78][:y_idx] == 6956 + @test alpine.linear_terms[lk78][:id] == 30 + @test alpine.linear_terms[lk78][:y_type] == :(Cont) + lk79 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 226), (1.0, 3677)])), + ) + @test alpine.linear_terms[lk79][:y_idx] == 6944 + @test alpine.linear_terms[lk79][:id] == 23 + @test alpine.linear_terms[lk79][:y_type] == :(Cont) + end +end + +@testset "Expression Parsing || Basic Multiplication Operators (Machine Generated for diffs)" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "minlp_solver" => JUNIPER, + "mip_solver" => HIGHS, + "log_level" => 100, + ) + + m = operator_basic(solver = test_solver) + JuMP.set_optimize_hook(m, MOI.Utilities.attach_optimizer) + JuMP.optimize!(m) + JuMP.set_optimize_hook(m, nothing) + alpine = JuMP.backend(m).optimizer.model + Alpine.load!(alpine) + + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4])]][:y_idx] == 31 + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4])]][:id] == 27 + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4])]][:lifted_constr_ref] == + :(x[31] == x[3] * x[4]) + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[76])]][:y_idx] == 83 + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[76])]][:id] == 79 + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[76])]][:lifted_constr_ref] == + :(x[83] == x[4] * x[5] * x[76]) + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[76])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[2])]][:y_idx] == 9 + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[2])]][:id] == 5 + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[2])]][:lifted_constr_ref] == + :(x[9] == (*)(x[2])) + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[2])]][:nonlinear_type] == :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7])]][:y_idx] == 19 + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7])]][:id] == 15 + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7])]][:lifted_constr_ref] == + :(x[19] == x[5] * x[7]) + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[31])]][:y_idx] == 32 + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[31])]][:id] == 28 + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[31])]][:lifted_constr_ref] == + :(x[32] == x[2] * x[31]) + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[31])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10])]][:y_idx] == 49 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10])]][:id] == 45 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10])]][:lifted_constr_ref] == + :(x[49] == x[1] * x[2] * x[10]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5]), :(x[9])]][:y_idx] == 50 + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5]), :(x[9])]][:id] == 46 + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5]), :(x[9])]][:lifted_constr_ref] == + :(x[50] == x[3] * x[5] * x[9]) + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[5]), :(x[9])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[47])]][:y_idx] == 69 + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[47])]][:id] == 65 + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[47])]][:lifted_constr_ref] == + :(x[69] == x[4] * x[47]) + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[47])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[4])]][:y_idx] == 28 + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[4])]][:id] == 24 + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[4])]][:lifted_constr_ref] == + :(x[28] == (*)(x[4])) + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[4])]][:nonlinear_type] == :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[10])]][:y_idx] == 37 + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[10])]][:id] == 33 + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[10])]][:lifted_constr_ref] == + :(x[37] == x[4] * x[10]) + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[10])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[1])]][:y_idx] == 5 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[1])]][:id] == 1 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[1])]][:lifted_constr_ref] == + :(x[5] == (*)(x[1])) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[1])]][:nonlinear_type] == :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[95])]][:y_idx] == 96 + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[95])]][:id] == 92 + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[95])]][:lifted_constr_ref] == + :(x[96] == x[5] * x[95]) + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[95])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[40])]][:y_idx] == 41 + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[40])]][:id] == 37 + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[40])]][:lifted_constr_ref] == + :(x[41] == x[2] * x[40]) + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[40])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10])]][:y_idx] == 26 + @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10])]][:id] == 22 + @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10])]][:lifted_constr_ref] == + :(x[26] == x[6] * x[10]) + @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[78]), :(x[28])]][:y_idx] == 84 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[78]), :(x[28])]][:id] == 80 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[78]), :(x[28])]][:lifted_constr_ref] == + :(x[84] == x[1] * x[78] * x[28]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[78]), :(x[28])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[43])]][:y_idx] == 58 + @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[43])]][:id] == 54 + @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[43])]][:lifted_constr_ref] == + :(x[58] == x[6] * x[43]) + @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[43])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[6]), :(x[10])]][:y_idx] == 106 + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[6]), :(x[10])]][:id] == 102 + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[6]), :(x[10])]][:lifted_constr_ref] == + :(x[106] == x[4] * x[6] * x[10]) + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[6]), :(x[10])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4]), :(x[10])]][:y_idx] == 90 + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4]), :(x[10])]][:id] == 86 + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4]), :(x[10])]][:lifted_constr_ref] == + :(x[90] == x[2] * x[4] * x[10]) + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[4]), :(x[10])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[41])]][:y_idx] == 42 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[41])]][:id] == 38 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[41])]][:lifted_constr_ref] == + :(x[42] == x[1] * x[41]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[41])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[37])]][:y_idx] == 38 + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[37])]][:id] == 34 + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[37])]][:lifted_constr_ref] == + :(x[38] == x[2] * x[37]) + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[37])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[85])]][:y_idx] == 87 + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[85])]][:id] == 83 + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[85])]][:lifted_constr_ref] == + :(x[87] == x[5] * x[85]) + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[85])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5]), :(x[28])]][:y_idx] == 66 + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5]), :(x[28])]][:id] == 62 + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5]), :(x[28])]][:lifted_constr_ref] == + :(x[66] == x[2] * x[3] * x[5] * x[28]) + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5]), :(x[28])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10])]][:y_idx] == 53 + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10])]][:id] == 49 + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10])]][:lifted_constr_ref] == + :(x[53] == x[5] * x[9] * x[10]) + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6]), :(x[28])]][:y_idx] == 107 + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6]), :(x[28])]][:id] == 103 + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6]), :(x[28])]][:lifted_constr_ref] == + :(x[107] == x[3] * x[6] * x[28]) + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6]), :(x[28])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5])]][:y_idx] == 17 + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5])]][:id] == 13 + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5])]][:lifted_constr_ref] == + :(x[17] == x[2] * x[5]) + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[37])]][:y_idx] == 57 + @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[37])]][:id] == 53 + @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[37])]][:lifted_constr_ref] == + :(x[57] == x[6] * x[37]) + @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[37])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7]), :(x[28])]][:y_idx] == 81 + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7]), :(x[28])]][:id] == 77 + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7]), :(x[28])]][:lifted_constr_ref] == + :(x[81] == x[5] * x[7] * x[28]) + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[7]), :(x[28])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[38])]][:y_idx] == 39 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[38])]][:id] == 35 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[38])]][:lifted_constr_ref] == + :(x[39] == x[1] * x[38]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[38])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[9])]][:y_idx] == 48 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[9])]][:id] == 44 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[9])]][:lifted_constr_ref] == + :(x[48] == x[1] * x[3] * x[9]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[9])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[23])]][:y_idx] == 24 + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[23])]][:id] == 20 + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[23])]][:lifted_constr_ref] == + :(x[24] == x[4] * x[23]) + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[23])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[17])]][:y_idx] == 23 + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[17])]][:id] == 19 + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[17])]][:lifted_constr_ref] == + :(x[23] == x[3] * x[17]) + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[17])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[10])]][:y_idx] == 51 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[10])]][:id] == 47 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[10])]][:lifted_constr_ref] == + :(x[51] == x[1] * x[9] * x[10]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[10])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[7])]][:y_idx] == 75 + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[7])]][:id] == 71 + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[7])]][:lifted_constr_ref] == + :(x[75] == x[4] * x[5] * x[7]) + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[5]), :(x[7])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[28])]][:y_idx] == 95 + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[28])]][:id] == 91 + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[28])]][:lifted_constr_ref] == + :(x[95] == x[9] * x[10] * x[28]) + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10]), :(x[28])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10])]][:y_idx] == 11 + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10])]][:id] == 7 + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10])]][:lifted_constr_ref] == + :(x[11] == x[9] * x[10]) + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[10])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[37])]][:y_idx] == 100 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[37])]][:id] == 96 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[37])]][:lifted_constr_ref] == + :(x[100] == x[1] * x[2] * x[37]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[37])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4]), :(x[5])]][:y_idx] == 62 + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4]), :(x[5])]][:id] == 58 + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4]), :(x[5])]][:lifted_constr_ref] == + :(x[62] == x[2] * x[3] * x[4] * x[5]) + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4]), :(x[5])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[9]), :(x[10])]][:y_idx] == 65 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[9]), :(x[10])]][:id] == 61 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[9]), :(x[10])]][:lifted_constr_ref] == + :(x[65] == x[1] * x[4] * x[9] * x[10]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[9]), :(x[10])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7]), :(x[28])]][:y_idx] == 80 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7]), :(x[28])]][:id] == 76 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7]), :(x[28])]][:lifted_constr_ref] == + :(x[80] == x[1] * x[7] * x[28]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7]), :(x[28])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3])]][:y_idx] == 46 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3])]][:id] == 42 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3])]][:lifted_constr_ref] == + :(x[46] == x[1] * x[2] * x[3]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[40])]][:y_idx] == 59 + @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[40])]][:id] == 55 + @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[40])]][:lifted_constr_ref] == + :(x[59] == x[17] * x[40]) + @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[40])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[85])]][:y_idx] == 86 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[85])]][:id] == 82 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[85])]][:lifted_constr_ref] == + :(x[86] == x[1] * x[85]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[85])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[31])]][:y_idx] == 97 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[31])]][:id] == 93 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[31])]][:lifted_constr_ref] == + :(x[97] == x[1] * x[2] * x[31]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[31])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[28])]][:y_idx] == 29 + @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[28])]][:id] == 25 + @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[28])]][:lifted_constr_ref] == + :(x[29] == x[13] * x[28]) + @test alpine.nonconvex_terms[Expr[:(x[13]), :(x[28])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[28])]][:y_idx] == 92 + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[28])]][:id] == 88 + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[28])]][:lifted_constr_ref] == + :(x[92] == x[2] * x[3] * x[28]) + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[28])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9])]][:y_idx] == 20 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9])]][:id] == 16 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9])]][:lifted_constr_ref] == + :(x[20] == x[1] * x[9]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10]), :(x[28])]][:y_idx] == 109 + @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10]), :(x[28])]][:id] == 105 + @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10]), :(x[28])]][:lifted_constr_ref] == + :(x[109] == x[14] * x[10] * x[28]) + @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10]), :(x[28])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[92])]][:y_idx] == 93 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[92])]][:id] == 89 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[92])]][:lifted_constr_ref] == + :(x[93] == x[1] * x[92]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[92])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4])]][:y_idx] == 85 + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4])]][:id] == 81 + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4])]][:lifted_constr_ref] == + :(x[85] == x[2] * x[3] * x[4]) + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[4])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[11])]][:y_idx] == 16 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[11])]][:id] == 12 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[11])]][:lifted_constr_ref] == + :(x[16] == x[1] * x[11]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[11])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[21])]][:y_idx] == 25 + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[21])]][:id] == 21 + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[21])]][:lifted_constr_ref] == + :(x[25] == x[4] * x[21]) + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[21])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[53]), :(x[28])]][:y_idx] == 73 + @test alpine.nonconvex_terms[Expr[:(x[53]), :(x[28])]][:id] == 69 + @test alpine.nonconvex_terms[Expr[:(x[53]), :(x[28])]][:lifted_constr_ref] == + :(x[73] == x[53] * x[28]) + @test alpine.nonconvex_terms[Expr[:(x[53]), :(x[28])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[32])]][:y_idx] == 34 + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[32])]][:id] == 30 + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[32])]][:lifted_constr_ref] == + :(x[34] == x[5] * x[32]) + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[32])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[28])]][:y_idx] == 40 + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[28])]][:id] == 36 + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[28])]][:lifted_constr_ref] == + :(x[40] == x[3] * x[28]) + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[28])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10]), :(x[28])]][:y_idx] == 67 + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10]), :(x[28])]][:id] == 63 + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10]), :(x[28])]][:lifted_constr_ref] == + :(x[67] == x[5] * x[9] * x[10] * x[28]) + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[10]), :(x[28])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[43])]][:y_idx] == 102 + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[43])]][:id] == 98 + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[43])]][:lifted_constr_ref] == + :(x[102] == x[5] * x[9] * x[43]) + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9]), :(x[43])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[26])]][:y_idx] == 27 + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[26])]][:id] == 23 + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[26])]][:lifted_constr_ref] == + :(x[27] == x[4] * x[26]) + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[26])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[20]), :(x[31])]][:y_idx] == 56 + @test alpine.nonconvex_terms[Expr[:(x[20]), :(x[31])]][:id] == 52 + @test alpine.nonconvex_terms[Expr[:(x[20]), :(x[31])]][:lifted_constr_ref] == + :(x[56] == x[20] * x[31]) + @test alpine.nonconvex_terms[Expr[:(x[20]), :(x[31])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[4]), :(x[9])]][:y_idx] == 63 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[4]), :(x[9])]][:id] == 59 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[4]), :(x[9])]][:lifted_constr_ref] == + :(x[63] == x[1] * x[3] * x[4] * x[9]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[3]), :(x[4]), :(x[9])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10])]][:y_idx] == 15 + @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10])]][:id] == 11 + @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10])]][:lifted_constr_ref] == + :(x[15] == x[14] * x[10]) + @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[10])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[76])]][:y_idx] == 77 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[76])]][:id] == 73 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[76])]][:lifted_constr_ref] == + :(x[77] == x[1] * x[4] * x[76]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[76])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[88])]][:y_idx] == 89 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[88])]][:id] == 85 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[88])]][:lifted_constr_ref] == + :(x[89] == x[1] * x[88]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[88])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[90])]][:y_idx] == 94 + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[90])]][:id] == 90 + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[90])]][:lifted_constr_ref] == + :(x[94] == x[5] * x[90]) + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[90])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10]), :(x[28])]][:y_idx] == 108 + @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10]), :(x[28])]][:id] == 104 + @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10]), :(x[28])]][:lifted_constr_ref] == + :(x[108] == x[6] * x[10] * x[28]) + @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[10]), :(x[28])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[48])]][:y_idx] == 70 + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[48])]][:id] == 66 + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[48])]][:lifted_constr_ref] == + :(x[70] == x[4] * x[48]) + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[48])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[31])]][:y_idx] == 54 + @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[31])]][:id] == 50 + @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[31])]][:lifted_constr_ref] == + :(x[54] == x[6] * x[31]) + @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[31])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[31])]][:y_idx] == 99 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[31])]][:id] == 95 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[31])]][:lifted_constr_ref] == + :(x[99] == x[1] * x[9] * x[31]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[9]), :(x[31])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[35])]][:y_idx] == 36 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[35])]][:id] == 32 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[35])]][:lifted_constr_ref] == + :(x[36] == x[1] * x[35]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[35])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9])]][:y_idx] == 14 + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9])]][:id] == 10 + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9])]][:lifted_constr_ref] == + :(x[14] == x[5] * x[9]) + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[9])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[13])]][:y_idx] == 22 + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[13])]][:id] == 18 + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[13])]][:lifted_constr_ref] == + :(x[22] == x[4] * x[13]) + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[13])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10]), :(x[28])]][:y_idx] == 64 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10]), :(x[28])]][:id] == 60 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10]), :(x[28])]][:lifted_constr_ref] == + :(x[64] == x[1] * x[2] * x[10] * x[28]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[10]), :(x[28])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[46]), :(x[28])]][:y_idx] == 72 + @test alpine.nonconvex_terms[Expr[:(x[46]), :(x[28])]][:id] == 68 + @test alpine.nonconvex_terms[Expr[:(x[46]), :(x[28])]][:lifted_constr_ref] == + :(x[72] == x[46] * x[28]) + @test alpine.nonconvex_terms[Expr[:(x[46]), :(x[28])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[31])]][:y_idx] == 55 + @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[31])]][:id] == 51 + @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[31])]][:lifted_constr_ref] == + :(x[55] == x[17] * x[31]) + @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[31])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[31])]][:y_idx] == 98 + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[31])]][:id] == 94 + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[31])]][:lifted_constr_ref] == + :(x[98] == x[2] * x[5] * x[31]) + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[31])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[28])]][:y_idx] == 43 + @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[28])]][:id] == 39 + @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[28])]][:lifted_constr_ref] == + :(x[43] == x[10] * x[28]) + @test alpine.nonconvex_terms[Expr[:(x[10]), :(x[28])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[10])]][:y_idx] == 78 + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[10])]][:id] == 74 + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[10])]][:lifted_constr_ref] == + :(x[78] == x[2] * x[10]) + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[10])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[10])]][:y_idx] == 52 + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[10])]][:id] == 48 + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[10])]][:lifted_constr_ref] == + :(x[52] == x[2] * x[5] * x[10]) + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[5]), :(x[10])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[90])]][:y_idx] == 91 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[90])]][:id] == 87 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[90])]][:lifted_constr_ref] == + :(x[91] == x[1] * x[90]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[90])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[17])]][:y_idx] == 104 + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[17])]][:id] == 100 + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[17])]][:lifted_constr_ref] == + :(x[104] == x[3] * x[4] * x[17]) + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[17])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[9])]][:y_idx] == 76 + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[9])]][:id] == 72 + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[9])]][:lifted_constr_ref] == + :(x[76] == x[3] * x[9]) + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[9])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[78])]][:y_idx] == 79 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[78])]][:id] == 75 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[78])]][:lifted_constr_ref] == + :(x[79] == x[1] * x[4] * x[78]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[78])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[3])]][:y_idx] == 10 + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[3])]][:id] == 6 + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[3])]][:lifted_constr_ref] == + :(x[10] == (*)(x[3])) + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[3])]][:nonlinear_type] == :MONOMIAL + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[49])]][:y_idx] == 71 + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[49])]][:id] == 67 + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[49])]][:lifted_constr_ref] == + :(x[71] == x[4] * x[49]) + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[49])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[9])]][:y_idx] == 88 + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[9])]][:id] == 84 + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[9])]][:lifted_constr_ref] == + :(x[88] == x[3] * x[4] * x[9]) + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[9])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[15]), :(x[28])]][:y_idx] == 30 + @test alpine.nonconvex_terms[Expr[:(x[15]), :(x[28])]][:id] == 26 + @test alpine.nonconvex_terms[Expr[:(x[15]), :(x[28])]][:lifted_constr_ref] == + :(x[30] == x[15] * x[28]) + @test alpine.nonconvex_terms[Expr[:(x[15]), :(x[28])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[46])]][:y_idx] == 68 + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[46])]][:id] == 64 + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[46])]][:lifted_constr_ref] == + :(x[68] == x[4] * x[46]) + @test alpine.nonconvex_terms[Expr[:(x[4]), :(x[46])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[11])]][:y_idx] == 12 + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[11])]][:id] == 8 + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[11])]][:lifted_constr_ref] == + :(x[12] == x[5] * x[11]) + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[11])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[7])]][:y_idx] == 74 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[7])]][:id] == 70 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[7])]][:lifted_constr_ref] == + :(x[74] == x[1] * x[4] * x[7]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[7])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[20])]][:y_idx] == 105 + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[20])]][:id] == 101 + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[20])]][:lifted_constr_ref] == + :(x[105] == x[3] * x[4] * x[20]) + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[20])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[11])]][:y_idx] == 82 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[11])]][:id] == 78 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[11])]][:lifted_constr_ref] == + :(x[82] == x[1] * x[4] * x[11]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[4]), :(x[11])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[43])]][:y_idx] == 44 + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[43])]][:id] == 40 + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[43])]][:lifted_constr_ref] == + :(x[44] == x[9] * x[43]) + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[43])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:y_idx] == 61 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:id] == 57 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:lifted_constr_ref] == + :(x[61] == x[1] * x[2] * x[3] * x[4]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3]), :(x[4])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[10])]][:y_idx] == 18 + @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[10])]][:id] == 14 + @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[10])]][:lifted_constr_ref] == + :(x[18] == x[17] * x[10]) + @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[10])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7])]][:y_idx] == 8 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7])]][:id] == 4 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7])]][:lifted_constr_ref] == + :(x[8] == x[1] * x[7]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[7])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2])]][:y_idx] == 6 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2])]][:id] == 2 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2])]][:lifted_constr_ref] == + :(x[6] == x[1] * x[2]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[40])]][:y_idx] == 101 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[40])]][:id] == 97 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[40])]][:lifted_constr_ref] == + :(x[101] == x[1] * x[2] * x[40]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[40])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[37])]][:y_idx] == 60 + @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[37])]][:id] == 56 + @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[37])]][:lifted_constr_ref] == + :(x[60] == x[17] * x[37]) + @test alpine.nonconvex_terms[Expr[:(x[17]), :(x[37])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[6])]][:y_idx] == 103 + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[6])]][:id] == 99 + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[6])]][:lifted_constr_ref] == + :(x[103] == x[3] * x[4] * x[6]) + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[4]), :(x[6])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3])]][:y_idx] == 7 + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3])]][:id] == 3 + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3])]][:lifted_constr_ref] == + :(x[7] == x[2] * x[3]) + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5])]][:y_idx] == 47 + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5])]][:id] == 43 + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5])]][:lifted_constr_ref] == + :(x[47] == x[2] * x[3] * x[5]) + @test alpine.nonconvex_terms[Expr[:(x[2]), :(x[3]), :(x[5])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6])]][:y_idx] == 13 + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6])]][:id] == 9 + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6])]][:lifted_constr_ref] == + :(x[13] == x[3] * x[6]) + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[6])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[31])]][:y_idx] == 35 + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[31])]][:id] == 31 + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[31])]][:lifted_constr_ref] == + :(x[35] == x[9] * x[31]) + @test alpine.nonconvex_terms[Expr[:(x[9]), :(x[31])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[32])]][:y_idx] == 33 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[32])]][:id] == 29 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[32])]][:lifted_constr_ref] == + :(x[33] == x[1] * x[32]) + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[32])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[20])]][:y_idx] == 21 + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[20])]][:id] == 17 + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[20])]][:lifted_constr_ref] == + :(x[21] == x[3] * x[20]) + @test alpine.nonconvex_terms[Expr[:(x[3]), :(x[20])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[44])]][:y_idx] == 45 + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[44])]][:id] == 41 + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[44])]][:lifted_constr_ref] == + :(x[45] == x[5] * x[44]) + @test alpine.nonconvex_terms[Expr[:(x[5]), :(x[44])]][:nonlinear_type] == :BILINEAR + + @test alpine.bounding_constr_mip[1][:rhs] == 1.0 + @test alpine.bounding_constr_mip[1][:vars] == Any[:(x[5])] + @test alpine.bounding_constr_mip[1][:coefs] == Any[1.0] + @test alpine.bounding_constr_mip[1][:sense] == :(>=) + @test alpine.bounding_constr_mip[1][:cnt] == 1 + @test alpine.bounding_constr_mip[2][:rhs] == 1.0 + @test alpine.bounding_constr_mip[2][:vars] == Any[:(x[6])] + @test alpine.bounding_constr_mip[2][:coefs] == Any[1.0] + @test alpine.bounding_constr_mip[2][:sense] == :(<=) + @test alpine.bounding_constr_mip[2][:cnt] == 1 + @test alpine.bounding_constr_mip[3][:rhs] == 1.0 + @test alpine.bounding_constr_mip[3][:vars] == Any[:(x[5]), :(x[7])] + @test alpine.bounding_constr_mip[3][:coefs] == Any[1.0, 1.0] + @test alpine.bounding_constr_mip[3][:sense] == :(<=) + @test alpine.bounding_constr_mip[3][:cnt] == 2 + @test alpine.bounding_constr_mip[4][:rhs] == 1.0 + @test alpine.bounding_constr_mip[4][:vars] == Any[:(x[8])] + @test alpine.bounding_constr_mip[4][:coefs] == Any[1.0] + @test alpine.bounding_constr_mip[4][:sense] == :(>=) + @test alpine.bounding_constr_mip[4][:cnt] == 1 + @test alpine.bounding_constr_mip[5][:rhs] == 1.0 + @test alpine.bounding_constr_mip[5][:vars] == Any[:(x[12])] + @test alpine.bounding_constr_mip[5][:coefs] == Any[1.0] + @test alpine.bounding_constr_mip[5][:sense] == :(<=) + @test alpine.bounding_constr_mip[5][:cnt] == 1 + @test alpine.bounding_constr_mip[6][:rhs] == 1.0 + @test alpine.bounding_constr_mip[6][:vars] == Any[:(x[13])] + @test alpine.bounding_constr_mip[6][:coefs] == Any[1.0] + @test alpine.bounding_constr_mip[6][:sense] == :(>=) + @test alpine.bounding_constr_mip[6][:cnt] == 1 + @test alpine.bounding_constr_mip[7][:rhs] == 1.0 + @test alpine.bounding_constr_mip[7][:vars] == Any[:(x[15])] + @test alpine.bounding_constr_mip[7][:coefs] == Any[1.0] + @test alpine.bounding_constr_mip[7][:sense] == :(<=) + @test alpine.bounding_constr_mip[7][:cnt] == 1 + @test alpine.bounding_constr_mip[8][:rhs] == 1.0 + @test alpine.bounding_constr_mip[8][:vars] == Any[:(x[16])] + @test alpine.bounding_constr_mip[8][:coefs] == Any[1.0] + @test alpine.bounding_constr_mip[8][:sense] == :(>=) + @test alpine.bounding_constr_mip[8][:cnt] == 1 + @test alpine.bounding_constr_mip[9][:rhs] == 1.0 + @test alpine.bounding_constr_mip[9][:vars] == Any[:(x[18])] + @test alpine.bounding_constr_mip[9][:coefs] == Any[1.0] + @test alpine.bounding_constr_mip[9][:sense] == :(<=) + @test alpine.bounding_constr_mip[9][:cnt] == 1 + @test alpine.bounding_constr_mip[10][:rhs] == 1.0 + @test alpine.bounding_constr_mip[10][:vars] == Any[:(x[19])] + @test alpine.bounding_constr_mip[10][:coefs] == Any[1.0] + @test alpine.bounding_constr_mip[10][:sense] == :(>=) + @test alpine.bounding_constr_mip[10][:cnt] == 1 + @test alpine.bounding_constr_mip[11][:rhs] == 1.0 + @test alpine.bounding_constr_mip[11][:vars] == Any[:(x[21])] + @test alpine.bounding_constr_mip[11][:coefs] == Any[1.0] + @test alpine.bounding_constr_mip[11][:sense] == :(<=) + @test alpine.bounding_constr_mip[11][:cnt] == 1 + @test alpine.bounding_constr_mip[12][:rhs] == 1.0 + @test alpine.bounding_constr_mip[12][:vars] == Any[:(x[22])] + @test alpine.bounding_constr_mip[12][:coefs] == Any[1.0] + @test alpine.bounding_constr_mip[12][:sense] == :(>=) + @test alpine.bounding_constr_mip[12][:cnt] == 1 + @test alpine.bounding_constr_mip[13][:rhs] == 1.0 + @test alpine.bounding_constr_mip[13][:vars] == Any[:(x[24])] + @test alpine.bounding_constr_mip[13][:coefs] == Any[1.0] + @test alpine.bounding_constr_mip[13][:sense] == :(<=) + @test alpine.bounding_constr_mip[13][:cnt] == 1 + @test alpine.bounding_constr_mip[14][:rhs] == 1.0 + @test alpine.bounding_constr_mip[14][:vars] == Any[:(x[25])] + @test alpine.bounding_constr_mip[14][:coefs] == Any[1.0] + @test alpine.bounding_constr_mip[14][:sense] == :(>=) + @test alpine.bounding_constr_mip[14][:cnt] == 1 + @test alpine.bounding_constr_mip[15][:rhs] == 1.0 + @test alpine.bounding_constr_mip[15][:vars] == Any[:(x[27])] + @test alpine.bounding_constr_mip[15][:coefs] == Any[1.0] + @test alpine.bounding_constr_mip[15][:sense] == :(<=) + @test alpine.bounding_constr_mip[15][:cnt] == 1 +end + +@testset "Expression Parsing || corner cases" begin + @testset "Corner Cases - 1 : sign convertor special case" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "minlp_solver" => JUNIPER, + "log_level" => 100, + ) + + m = Model(test_solver) + @variable(m, 0 <= x[1:5] <= 1, Bin) + @NLconstraint(m, x[1] + -x[2] >= 2) + @objective(m, Min, x[1] + x[2]) + alpine = _build(m) + + @test alpine.bounding_constr_mip[1][:rhs] == 2.0 + @test alpine.bounding_constr_mip[1][:vars] == Any[:(x[1]), :(x[2])] + @test alpine.bounding_constr_mip[1][:coefs] == Any[1.0, -1.0] + @test alpine.bounding_constr_mip[1][:sense] == :(>=) + @test alpine.bounding_constr_mip[1][:cnt] == 2 + end + + @testset "Corner Cases - 2 : full sub-expression" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "log_level" => 100, + ) + + m = Model(test_solver) + @variable(m, x[1:5] >= 0) + @NLconstraint(m, (x[1] + 10 + 4 * x[2] + 200) * 5 >= 2 * 5) + @constraint(m, x[1] + x[2] + 200 >= 2) + @objective(m, Min, x[1] + x[2]) + alpine = _build(m) + + @test alpine.bounding_constr_mip[1][:rhs] == -198.0 + @test alpine.bounding_constr_mip[1][:vars] == Any[:(x[1]), :(x[2])] + @test alpine.bounding_constr_mip[1][:coefs] == Any[1.0, 1.0] + @test alpine.bounding_constr_mip[1][:sense] == :(>=) + @test alpine.bounding_constr_mip[1][:cnt] == 2 + @test alpine.bounding_constr_mip[2][:rhs] == -1040.0 + @test alpine.bounding_constr_mip[2][:vars] == Any[:(x[1]), :(x[2])] + @test alpine.bounding_constr_mip[2][:coefs] == Any[5.0, 20.0] + @test alpine.bounding_constr_mip[2][:sense] == :(>=) + @test alpine.bounding_constr_mip[2][:cnt] == 2 + end + + @testset "Corner Cases - 2 : full sub-expression" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "log_level" => 100, + ) + + m = Model(test_solver) + @variable(m, x[1:5] >= 0) + @NLconstraint(m, (x[1] + 10 + 4 * x[2] + 200) * 5 >= 2 * 5) + @constraint(m, x[1] + x[2] + 200 >= 2) + @objective(m, Min, x[1] + x[2]) + alpine = _build(m) + + @test alpine.bounding_constr_mip[1][:rhs] == -198.0 + @test alpine.bounding_constr_mip[1][:vars] == Any[:(x[1]), :(x[2])] + @test alpine.bounding_constr_mip[1][:coefs] == Any[1.0, 1.0] + @test alpine.bounding_constr_mip[1][:sense] == :(>=) + @test alpine.bounding_constr_mip[1][:cnt] == 2 + @test alpine.bounding_constr_mip[2][:rhs] == -1040.0 + @test alpine.bounding_constr_mip[2][:vars] == Any[:(x[1]), :(x[2])] + @test alpine.bounding_constr_mip[2][:coefs] == Any[5.0, 20.0] + @test alpine.bounding_constr_mip[2][:sense] == :(>=) + @test alpine.bounding_constr_mip[2][:cnt] == 2 + end +end + +@testset "Expression Parsing || Discrete Multilinear" begin + @testset "Expression Parsing || bmpl && binlin && binprod" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "minlp_solver" => JUNIPER, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "log_level" => 100, + ) + + m = bpml(solver = test_solver) + + alpine = _build(m) # Setup internal model + + @test length(keys(alpine.nonconvex_terms)) == 12 + + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[6])]][:y_idx] == 11 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2])]][:y_idx] == 12 + @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[6])]][:y_idx] == 13 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3])]][:y_idx] == 14 + @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[6])]][:y_idx] == 15 + @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[7])]][:y_idx] == 16 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[16])]][:y_idx] == 17 + @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[7]), :(x[8])]][:y_idx] == 18 + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[18])]][:y_idx] == 19 + @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[18])]][:y_idx] == 20 + @test alpine.nonconvex_terms[Expr[ + :(x[1]), + :(x[2]), + :(x[3]), + :(x[4]), + :(x[5]), + ]][:y_idx] == 21 + @test alpine.nonconvex_terms[Expr[ + :(x[6]), + :(x[7]), + :(x[9]), + :(x[10]), + :(x[6]), + ]][:y_idx] == 22 + + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[6])]][:nonlinear_type] == :BINLIN + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2])]][:nonlinear_type] == :BINPROD + @test alpine.nonconvex_terms[Expr[:(x[12]), :(x[6])]][:nonlinear_type] == :BINLIN + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[2]), :(x[3])]][:nonlinear_type] == + :BINPROD + @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[6])]][:nonlinear_type] == :BINLIN + @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[7])]][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[16])]][:nonlinear_type] == :BINLIN + @test alpine.nonconvex_terms[Expr[:(x[6]), :(x[7]), :(x[8])]][:nonlinear_type] == + :MULTILINEAR + @test alpine.nonconvex_terms[Expr[:(x[1]), :(x[18])]][:nonlinear_type] == :BINLIN + @test alpine.nonconvex_terms[Expr[:(x[14]), :(x[18])]][:nonlinear_type] == :BINLIN + @test alpine.nonconvex_terms[Expr[ + :(x[1]), + :(x[2]), + :(x[3]), + :(x[4]), + :(x[5]), + ]][:nonlinear_type] == :BINPROD + @test alpine.nonconvex_terms[Expr[ + :(x[6]), + :(x[7]), + :(x[9]), + :(x[10]), + :(x[6]), + ]][:nonlinear_type] == :MULTILINEAR + + @test length(alpine.var_type) == 22 + @test alpine.var_type[11] == :Cont + @test alpine.var_type[12] == :Bin + @test alpine.var_type[13] == :Cont + @test alpine.var_type[14] == :Bin + @test alpine.var_type[15] == :Cont + @test alpine.var_type[16] == :Cont + @test alpine.var_type[17] == :Cont + @test alpine.var_type[18] == :Cont + @test alpine.var_type[19] == :Cont + @test alpine.var_type[20] == :Cont + @test alpine.var_type[21] == :Bin + @test alpine.var_type[22] == :Cont + end + + @testset "Expression Parsing || bmpl && binlin && binprod with linear lifting and coefficients" begin + test_solver = optimizer_with_attributes( + Alpine.Optimizer, + "minlp_solver" => JUNIPER, + "nlp_solver" => IPOPT, + "mip_solver" => HIGHS, + "log_level" => 100, + ) + + m = bmpl_linearlifting(solver = test_solver) + + alpine = _build(m) + + lk1 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 1), (1.0, 17)])), + ) + lk2 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 11), (1.0, 12)])), + ) + lk3 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 7), (2.0, 6)])), + ) + lk4 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6), (1.0, 19)])), + ) + lk5 = Dict{Symbol,Any}( + Pair{Symbol,Any}(:sign, :+), + Pair{Symbol,Any}(:scalar, 0.0), + Pair{Symbol,Any}(:coef_var, Set(Any[(1.0, 6), (1.0, 25)])), + ) + + @test haskey(alpine.linear_terms, lk1) + @test haskey(alpine.linear_terms, lk2) + @test haskey(alpine.linear_terms, lk3) + @test haskey(alpine.linear_terms, lk4) + @test haskey(alpine.linear_terms, lk5) + + @test alpine.linear_terms[lk1][:lifted_constr_ref] == :(x[20] == x[1] + x[17]) + @test alpine.linear_terms[lk2][:lifted_constr_ref] == :(x[13] == x[11] + x[12]) + @test alpine.linear_terms[lk3][:lifted_constr_ref] == :(x[15] == 2 * x[6] + x[7]) + @test alpine.linear_terms[lk4][:lifted_constr_ref] == :(x[21] == x[6] + x[19]) + @test alpine.linear_terms[lk5][:lifted_constr_ref] == :(x[26] == x[6] + x[25]) + + @test alpine.linear_terms[lk1][:y_idx] == 20 + @test alpine.linear_terms[lk2][:y_idx] == 13 + @test alpine.linear_terms[lk3][:y_idx] == 15 + @test alpine.linear_terms[lk4][:y_idx] == 21 + @test alpine.linear_terms[lk5][:y_idx] == 26 + + @test alpine.linear_terms[lk1][:y_type] == :Cont + @test alpine.linear_terms[lk2][:y_type] == :Cont + @test alpine.linear_terms[lk3][:y_type] == :Cont + @test alpine.linear_terms[lk4][:y_type] == :Cont + @test alpine.linear_terms[lk5][:y_type] == :Cont + + nlk1 = Expr[:(x[18]), :(x[7])] + nlk2 = Expr[:(x[6]), :(x[7]), :(x[8])] + nlk3 = Expr[:(x[7]), :(x[10])] + nlk4 = Expr[:(x[2]), :(x[26])] + nlk5 = Expr[:(x[1]), :(x[13])] + nlk6 = Expr[:(x[1]), :(x[15])] + nlk7 = Expr[:(x[2]), :(x[6])] + nlk8 = Expr[:(x[24]), :(x[23])] + nlk9 = Expr[:(x[1]), :(x[2])] + nlk10 = Expr[:(x[2]), :(x[3])] + nlk11 = Expr[:(x[20]), :(x[21])] + nlk12 = Expr[:(x[3]), :(x[4])] + + @test haskey(alpine.nonconvex_terms, nlk1) + @test haskey(alpine.nonconvex_terms, nlk2) + @test haskey(alpine.nonconvex_terms, nlk3) + @test haskey(alpine.nonconvex_terms, nlk4) + @test haskey(alpine.nonconvex_terms, nlk5) + @test haskey(alpine.nonconvex_terms, nlk6) + @test haskey(alpine.nonconvex_terms, nlk7) + @test haskey(alpine.nonconvex_terms, nlk8) + @test haskey(alpine.nonconvex_terms, nlk9) + @test haskey(alpine.nonconvex_terms, nlk10) + @test haskey(alpine.nonconvex_terms, nlk11) + @test haskey(alpine.nonconvex_terms, nlk12) + + @test alpine.nonconvex_terms[nlk1][:id] == 7 + @test alpine.nonconvex_terms[nlk2][:id] == 1 + @test alpine.nonconvex_terms[nlk3][:id] == 9 + @test alpine.nonconvex_terms[nlk4][:id] == 12 + @test alpine.nonconvex_terms[nlk5][:id] == 3 + @test alpine.nonconvex_terms[nlk6][:id] == 4 + @test alpine.nonconvex_terms[nlk7][:id] == 5 + @test alpine.nonconvex_terms[nlk8][:id] == 11 + @test alpine.nonconvex_terms[nlk9][:id] == 6 + @test alpine.nonconvex_terms[nlk10][:id] == 2 + @test alpine.nonconvex_terms[nlk11][:id] == 8 + @test alpine.nonconvex_terms[nlk12][:id] == 10 + + @test alpine.nonconvex_terms[nlk1][:y_type] == :Cont + @test alpine.nonconvex_terms[nlk2][:y_type] == :Cont + @test alpine.nonconvex_terms[nlk3][:y_type] == :Cont + @test alpine.nonconvex_terms[nlk4][:y_type] == :Cont + @test alpine.nonconvex_terms[nlk5][:y_type] == :Cont + @test alpine.nonconvex_terms[nlk6][:y_type] == :Cont + @test alpine.nonconvex_terms[nlk7][:y_type] == :Cont + @test alpine.nonconvex_terms[nlk8][:y_type] == :Cont + @test alpine.nonconvex_terms[nlk9][:y_type] == :Bin + @test alpine.nonconvex_terms[nlk10][:y_type] == :Bin + @test alpine.nonconvex_terms[nlk11][:y_type] == :Cont + @test alpine.nonconvex_terms[nlk12][:y_type] == :Bin + + @test alpine.nonconvex_terms[nlk1][:y_idx] == 19 + @test alpine.nonconvex_terms[nlk2][:y_idx] == 11 + @test alpine.nonconvex_terms[nlk3][:y_idx] == 23 + @test alpine.nonconvex_terms[nlk4][:y_idx] == 27 + @test alpine.nonconvex_terms[nlk5][:y_idx] == 14 + @test alpine.nonconvex_terms[nlk6][:y_idx] == 16 + @test alpine.nonconvex_terms[nlk7][:y_idx] == 17 + @test alpine.nonconvex_terms[nlk8][:y_idx] == 25 + @test alpine.nonconvex_terms[nlk9][:y_idx] == 18 + @test alpine.nonconvex_terms[nlk10][:y_idx] == 12 + @test alpine.nonconvex_terms[nlk11][:y_idx] == 22 + @test alpine.nonconvex_terms[nlk12][:y_idx] == 24 + + @test alpine.nonconvex_terms[nlk1][:nonlinear_type] == :BINLIN + @test alpine.nonconvex_terms[nlk2][:nonlinear_type] == :MULTILINEAR + @test alpine.nonconvex_terms[nlk3][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[nlk4][:nonlinear_type] == :BINLIN + @test alpine.nonconvex_terms[nlk5][:nonlinear_type] == :BINLIN + @test alpine.nonconvex_terms[nlk6][:nonlinear_type] == :BINLIN + @test alpine.nonconvex_terms[nlk7][:nonlinear_type] == :BINLIN + @test alpine.nonconvex_terms[nlk8][:nonlinear_type] == :BINLIN + @test alpine.nonconvex_terms[nlk9][:nonlinear_type] == :BINPROD + @test alpine.nonconvex_terms[nlk10][:nonlinear_type] == :BINPROD + @test alpine.nonconvex_terms[nlk11][:nonlinear_type] == :BILINEAR + @test alpine.nonconvex_terms[nlk12][:nonlinear_type] == :BINPROD + end +end @testset "Expr dereferencing for @NLexpression" begin # Taken from Juniper.jl From a80065a7c10ce513e1d44c1fadd4b1d03efbb437 Mon Sep 17 00:00:00 2001 From: harshangrjn Date: Mon, 5 Sep 2022 20:40:54 -0600 Subject: [PATCH 15/18] add linking only if multilinears exist --- src/multilinear.jl | 4 +++- test/test_expression.jl | 3 +-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/multilinear.jl b/src/multilinear.jl index 1b60ffca..221e10c8 100644 --- a/src/multilinear.jl +++ b/src/multilinear.jl @@ -8,11 +8,13 @@ function amp_post_convhull(m::Optimizer; kwargs...) β = Dict() # Lifted variables for exact formulation # Convexification for non-convex terms + contains_multilinear = false for k in keys(m.nonconvex_terms) nl_type = m.nonconvex_terms[k][:nonlinear_type] if ((nl_type == :MULTILINEAR) || (nl_type == :BILINEAR)) && (m.nonconvex_terms[k][:convexified] == false) λ, α = Alp.amp_convexify_multilinear(m, k, λ, α, d) + contains_multilinear = true elseif nl_type == :MONOMIAL && !m.nonconvex_terms[k][:convexified] λ, α = Alp.amp_convexify_quadratic_univariate(m, k, λ, α, d) elseif nl_type == :BINLIN && !m.nonconvex_terms[k][:convexified] @@ -23,7 +25,7 @@ function amp_post_convhull(m::Optimizer; kwargs...) end # Add lambda linking constraints - if m.options.linking_constraints + if m.options.linking_constraints && contains_multilinear Alp._add_multilinear_linking_constraints(m, λ) end diff --git a/test/test_expression.jl b/test/test_expression.jl index 3d419a98..91f81dbc 100644 --- a/test/test_expression.jl +++ b/test/test_expression.jl @@ -3646,8 +3646,7 @@ end "minlp_solver" => JUNIPER, "nlp_solver" => IPOPT, "mip_solver" => HIGHS, - "presolve_bt" => true, - "linking_constraints" => false, + "presolve_bt" => true ) m = Model(test_solver) From 68d4510865f2fc4c95cb61b62a2627cfbad8fef5 Mon Sep 17 00:00:00 2001 From: harshangrjn Date: Mon, 5 Sep 2022 21:51:50 -0600 Subject: [PATCH 16/18] tests clean up --- examples/Project.toml | 1 - src/algorithm.jl | 13 +++--- src/heuristics.jl | 90 ----------------------------------------- src/multilinear.jl | 4 +- src/utility.jl | 15 ------- test/test_algorithm.jl | 32 +++++++-------- test/test_expression.jl | 2 +- 7 files changed, 25 insertions(+), 132 deletions(-) diff --git a/examples/Project.toml b/examples/Project.toml index 21f8f651..9a080344 100644 --- a/examples/Project.toml +++ b/examples/Project.toml @@ -1,6 +1,5 @@ [deps] Alpine = "07493b3f-dabb-5b16-a503-4139292d7dd4" -BARON = "2e2ca445-9e14-5b13-8677-4410f177f82b" CPLEX = "a076750e-1247-5638-91d2-ce28b192dca0" Gurobi = "2e9cd046-0924-5485-92f1-d5272153d98b" HiGHS = "87dc4568-4c63-4d18-b0c0-bb2238e4078b" diff --git a/src/algorithm.jl b/src/algorithm.jl index adb026af..1587e226 100644 --- a/src/algorithm.jl +++ b/src/algorithm.jl @@ -255,7 +255,7 @@ function presolve(m::Optimizer) end """ - A wrapper function that collects some automated solver adjustments within the main while loop. + A wrapper function that collects automated solver adjustments within the main while loop. """ function algorithm_automation(m::Optimizer) Alp.get_option(m, :disc_var_pick) == 3 && Alp.update_disc_cont_var(m) @@ -355,7 +355,6 @@ Otherwise, the function is invoked from [`bounding_solve`](@ref). """ function local_solve(m::Optimizer; presolve = false) - convertor = Dict(MOI.MAX_SENSE => :>, MOI.MIN_SENSE => :<) local_nlp_status = :Unknown var_type_screener = [i for i in m.var_type_orig if i in [:Bin, :Int]] @@ -452,11 +451,11 @@ function local_solve(m::Optimizer; presolve = false) m.status[:local_solve] = local_nlp_status return - elseif local_nlp_status in STATUS_INF - Alp.heu_pool_multistart(m) == MOI.LOCALLY_SOLVED && return - push!(m.logs[:obj], "INF") - m.status[:local_solve] = MOI.LOCALLY_INFEASIBLE - return + # elseif local_nlp_status in STATUS_INF + # Alp.heu_pool_multistart(m) == MOI.LOCALLY_SOLVED && return + # push!(m.logs[:obj], "INF") + # m.status[:local_solve] = MOI.LOCALLY_INFEASIBLE + # return elseif local_nlp_status == MOI.DUAL_INFEASIBLE push!(m.logs[:obj], "U") diff --git a/src/heuristics.jl b/src/heuristics.jl index 777094db..e354b1dd 100644 --- a/src/heuristics.jl +++ b/src/heuristics.jl @@ -47,93 +47,3 @@ function update_disc_cont_var(m::Optimizer) println("updated partition var selection => $(m.disc_vars)") return end - -""" - Use solutions from the MIP solution pool as starting points -""" -function heu_pool_multistart(m::Optimizer) - convertor = Dict(MOI.MAX_SENSE => :>, MOI.MIN_SENSE => :<) - Alp.is_min_sense(m) ? incumb_obj = Inf : incumb_obj = -Inf - incumb_sol = [] - found_feasible = false - - for i in 1:m.bound_sol_pool[:cnt] - if !m.bound_sol_pool[:ubstart][i] - rounded_sol = Alp.round_sol(m, m.bound_sol_pool[:sol][i]) - l_var, u_var = Alp.fix_domains(m, discrete_sol = rounded_sol, use_orig = true) - heuristic_model = MOI.instantiate( - Alp.get_option(m, :nlp_solver), - with_bridge_type = Float64, - ) - x = Alp.load_nonlinear_model(m, heuristic_model, l_var, u_var) - - MOI.optimize!(heuristic_model) - - heuristic_model_status = MOI.get(heuristic_model, MOI.TerminationStatus()) - if heuristic_model_status in STATUS_OPT || - heuristic_model_status in STATUS_LIMIT - candidate_obj = MOI.get(heuristic_model, MOI.ObjectiveValue()) - if eval(convertor[m.sense_orig])(candidate_obj, incumb_obj) - incumb_obj = candidate_obj - incumb_sol = - round.(MOI.get(heuristic_model, MOI.VariablePrimal(), x), 5) - Alp.get_option(m, :log_level) > 0 && println( - "Feasible solution obtained using lower bound solution pool [SOL:$(i)] [OBJ=$(incumb_obj)]", - ) - end - found_feasible = true - else - Alp.get_option(m, :log_level) > 99 && println( - "Multi-start heuristic returns $(heuristic_model_status) [SOL:$(i)]", - ) - end - m.bound_sol_pool[:ubstart][i] = true - end - end - - if found_feasible - Alp.update_incumb_objective(m, incumb_obj, incumb_sol) - return MOI.LOCALLY_SOLVED - end - - return MOI.LOCALLY_INFEASIBLE -end - -#-----------------------------------------------------------------# -# UNSUPPORTED FUNCTIONS # -#-----------------------------------------------------------------# - -# """ -# One-time rounding heuristic to obtain a feasible solution -# For integer solutions -# """ -# function heu_basic_rounding(m::Optimizer, relaxed_sol) - -# println("Basic Rounding Heuristic Activated...") - -# convertor = Dict(MOI.MAX_SENSE => :>, MOI.MIN_SENSE => :<) - -# rounded_sol = round_sol(m, relaxed_sol) -# l_var, u_var = fix_domains(m, discrete_sol = rounded_sol) - -# heuristic_model = MOI.instantiate(Alp.get_option(m, :nlp_solver), with_bridge_type=Float64) -# x = load_nonlinear_model(m, heuristic_model, l_var, u_var) -# MOI.optimize!(heuristic_model) -# heuristic_model_status = MOI.get(heuristic_model, MOI.TerminationStatus()) - -# if heuristic_model_status == MOI.OTHER_ERROR || heuristic_model_status in STATUS_INF -# Alp.get_option(m, :log_level) > 0 && println("Rounding obtained an Infeasible point.") -# push!(m.logs[:obj], "INF") -# return MOI.LOCALLY_INFEASIBLE -# elseif heuristic_model_status in STATUS_OPT || heuristic_model_status in STATUS_LIMIT -# candidate_obj = MOI.get(heuristic_model, MOI.ObjectiveValue()) -# candidate_sol = round.(MOI.get(heuristic_model, MOI.VariablePrimal(), x), 5) -# update_incumb_objective(m, candidate_obj, candidate_sol) -# Alp.get_option(m, :log_level) > 0 && println("Rounding obtained a feasible solution OBJ = $(m.best_obj)") -# return MOI.LOCALLY_SOLVED -# else -# error("[EXCEPTION] Unknown NLP solver status.") -# end - -# return -# end diff --git a/src/multilinear.jl b/src/multilinear.jl index 221e10c8..669ce7cf 100644 --- a/src/multilinear.jl +++ b/src/multilinear.jl @@ -369,8 +369,8 @@ function amp_warmstart_α(m::Optimizer, α::Dict) active_j = Alp.get_active_partition_idx(d, m.bound_sol_pool[:sol][ws_idx][v], v) for j in 1:partition_cnt - j == active_j ? set_start_value(α[v][j], 1.0) : - set_start_value(α[v][j], 0.0) + j == active_j ? JuMP.set_start_value(α[v][j], 1.0) : + JuMP.set_start_value(α[v][j], 0.0) end end m.bound_sol_pool[:stat][ws_idx] = :Warmstarter diff --git a/src/utility.jl b/src/utility.jl index dff7eed3..61115567 100644 --- a/src/utility.jl +++ b/src/utility.jl @@ -456,21 +456,6 @@ function weighted_min_vertex_cover(m::Optimizer, distance::Dict) return end -function round_sol(m::Optimizer, relaxed_sol) - rounded_sol = copy(relaxed_sol) - for i in 1:m.num_var_orig - if m.var_type_orig[i] == :Bin - relaxed_sol[i] >= 0.5 ? rounded_sol[i] = 1 : rounded_sol[i] = 0 - elseif m.var_type_orig[i] == :Int - rounded_sol[i] = round(relaxed_sol[i]) - else - rounded_sol[i] = relaxed_sol[i] - end - end - - return rounded_sol -end - function _fetch_mip_solver_identifier(m::Optimizer; override = "") (Alp.get_option(m, :mip_solver) === nothing) && return m.mip_solver_id = _get_solver_name(m, :mip_solver, override) diff --git a/test/test_algorithm.jl b/test/test_algorithm.jl index 588bc14b..890c8e9f 100644 --- a/test/test_algorithm.jl +++ b/test/test_algorithm.jl @@ -161,22 +161,22 @@ end @test isapprox(objective_value(m), 1.4142135534556992; atol = 1e-3) end -@testset " Validation Test || AMP || basic solve || examples/circle_MINLPLib.jl" begin - test_solver = optimizer_with_attributes( - Alpine.Optimizer, - "nlp_solver" => IPOPT, - "mip_solver" => PAVITO, - "presolve_bt" => false, - "partition_scaling_factor" => 15, - "max_iter" => 2, - ) - - m = circle_MINLPLib(solver = test_solver) - - JuMP.optimize!(m) - @test termination_status(m) == MOI.OPTIMAL - @test isapprox(objective_value(m), 4.45670663096; atol = 1E-6) -end +# @testset " Validation Test || AMP || basic solve || examples/circle_MINLPLib.jl" begin +# test_solver = optimizer_with_attributes( +# Alpine.Optimizer, +# "nlp_solver" => IPOPT, +# "mip_solver" => PAVITO, +# "presolve_bt" => false, +# "partition_scaling_factor" => 15, +# "max_iter" => 2, +# ) + +# m = circle_MINLPLib(solver = test_solver) + +# JuMP.optimize!(m) +# @test termination_status(m) == MOI.OPTIMAL +# @test isapprox(objective_value(m), 4.45670663096; atol = 1E-6) +# end @testset " Validation Test || AMP-CONV-FACET || basic solve || examples/nlp3.jl" begin test_solver = optimizer_with_attributes( diff --git a/test/test_expression.jl b/test/test_expression.jl index 91f81dbc..beeccf55 100644 --- a/test/test_expression.jl +++ b/test/test_expression.jl @@ -3646,7 +3646,7 @@ end "minlp_solver" => JUNIPER, "nlp_solver" => IPOPT, "mip_solver" => HIGHS, - "presolve_bt" => true + "presolve_bt" => true, ) m = Model(test_solver) From 5b3c1db371e58459755ab2231b833697a6eb9e18 Mon Sep 17 00:00:00 2001 From: harshangrjn Date: Mon, 5 Sep 2022 22:25:06 -0600 Subject: [PATCH 17/18] test update --- test/test_solver.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_solver.jl b/test/test_solver.jl index 977c07ef..845f3ed6 100644 --- a/test/test_solver.jl +++ b/test/test_solver.jl @@ -312,7 +312,7 @@ end "disc_var_pick" => 3, "presolve_bp" => true, "presolve_bt" => false, - "max_iter" => 1, + "max_iter" => 2, "log_level" => 100, ) From 6b096046ec6928e86a45e58364b6179f36c3e7c9 Mon Sep 17 00:00:00 2001 From: harshangrjn Date: Mon, 5 Sep 2022 22:51:21 -0600 Subject: [PATCH 18/18] [ci skip] --- src/multilinear.jl | 67 --------------------------------------------- src/utility.jl | 68 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 67 deletions(-) diff --git a/src/multilinear.jl b/src/multilinear.jl index 669ce7cf..602bf92e 100644 --- a/src/multilinear.jl +++ b/src/multilinear.jl @@ -321,29 +321,6 @@ function amp_convhull_α(m::Optimizer, idx::Int, α::Dict, dim, d::Dict) return amp_convhull_α(m, [idx], α, dim, d) end -function amp_no_good_cut_α(m::Optimizer, α::Dict) - println("Global Incumbent solution objective = $(m.best_obj)") - - for i in 1:m.bound_sol_pool[:cnt] - (m.bound_sol_pool[:stat][i] == :Cutoff) && (m.bound_sol_pool[:stat][i] = :Alive) - if m.best_obj < m.bound_sol_pool[:obj][i] && m.bound_sol_pool[:stat][i] == :Alive - no_good_idxs = keys(m.bound_sol_pool[:disc][i]) - no_good_size = length(no_good_idxs) - 1 - JuMP.@constraint( - m.model_mip, - sum(α[v][m.bound_sol_pool[:disc][i][v]] for v in no_good_idxs) <= - no_good_size - ) - Alp.get_option(m, :log_level) > 0 && println( - "!! GLOBAL cuts off POOL_SOL-$(i) POOL_OBJ=$(m.bound_sol_pool[:obj][i])!", - ) - m.bound_sol_pool[:stat][i] = :Cutoff - end - end - - return -end - function amp_warmstart_α(m::Optimizer, α::Dict) d = m.discretization @@ -628,50 +605,6 @@ function amp_post_inequalities_cont( return end -function amp_post_λ_upperbound( - m::Optimizer, - λ::Dict, - indices::Any, - dim::Tuple, - d::Dict, - tregions::Vector, - reg = [], - level = 0, -) - if level == length(indices) - isempty(tregions[level]) && return - sliced_indices = - Set(collect_indices(λ[indices][:indices], 1, [reg[1]; reg[1] + 1], dim)) - for i in 2:length(reg) - sliced_indices = intersect( - sliced_indices, - Set(collect_indices(λ[indices][:indices], i, [reg[i], reg[i] + 1], dim)), - ) - end - for i in sliced_indices - JuMP.set_upper_bound(λ[indices][:vars][i], (1 / 2)^level) - end - return - end - - for i in 1:length(tregions[level+1]) - push!(reg, tregions[level+1][i]) - Alp.amp_post_λ_upperbound(m, λ, indices, dim, d, tregions, reg, level + 1) - length(reg) < level && error("Something is wrong") - length(reg) > level && pop!(reg) - end - - return -end - -function amp_post_λ_upperbound(m::Optimizer, λ::Dict, indices::Any, ub::Float64) - for i in λ[indices][:vars] - JuMP.set_upper_bound(i, ub) - end - - return -end - function collect_indices(l::Array, fixed_dim::Int, fixed_partition::Array, dim::Tuple) k = 0 indices = diff --git a/src/utility.jl b/src/utility.jl index 61115567..5259bfda 100644 --- a/src/utility.jl +++ b/src/utility.jl @@ -525,3 +525,71 @@ function resolve_lifted_var_value(m::Optimizer, sol_vec::Array) return sol_vec end + +# Unused functions +# function amp_post_λ_upperbound( +# m::Optimizer, +# λ::Dict, +# indices::Any, +# dim::Tuple, +# d::Dict, +# tregions::Vector, +# reg = [], +# level = 0, +# ) +# if level == length(indices) +# isempty(tregions[level]) && return +# sliced_indices = +# Set(collect_indices(λ[indices][:indices], 1, [reg[1]; reg[1] + 1], dim)) +# for i in 2:length(reg) +# sliced_indices = intersect( +# sliced_indices, +# Set(collect_indices(λ[indices][:indices], i, [reg[i], reg[i] + 1], dim)), +# ) +# end +# for i in sliced_indices +# JuMP.set_upper_bound(λ[indices][:vars][i], (1 / 2)^level) +# end +# return +# end + +# for i in 1:length(tregions[level+1]) +# push!(reg, tregions[level+1][i]) +# Alp.amp_post_λ_upperbound(m, λ, indices, dim, d, tregions, reg, level + 1) +# length(reg) < level && error("Something is wrong") +# length(reg) > level && pop!(reg) +# end + +# return +# end + +# function amp_post_λ_upperbound(m::Optimizer, λ::Dict, indices::Any, ub::Float64) +# for i in λ[indices][:vars] +# JuMP.set_upper_bound(i, ub) +# end + +# return +# end + +# function amp_no_good_cut_α(m::Optimizer, α::Dict) +# println("Global Incumbent solution objective = $(m.best_obj)") + +# for i in 1:m.bound_sol_pool[:cnt] +# (m.bound_sol_pool[:stat][i] == :Cutoff) && (m.bound_sol_pool[:stat][i] = :Alive) +# if m.best_obj < m.bound_sol_pool[:obj][i] && m.bound_sol_pool[:stat][i] == :Alive +# no_good_idxs = keys(m.bound_sol_pool[:disc][i]) +# no_good_size = length(no_good_idxs) - 1 +# JuMP.@constraint( +# m.model_mip, +# sum(α[v][m.bound_sol_pool[:disc][i][v]] for v in no_good_idxs) <= +# no_good_size +# ) +# Alp.get_option(m, :log_level) > 0 && println( +# "!! GLOBAL cuts off POOL_SOL-$(i) POOL_OBJ=$(m.bound_sol_pool[:obj][i])!", +# ) +# m.bound_sol_pool[:stat][i] = :Cutoff +# end +# end + +# return +# end