diff --git a/.github/workflows/format_check.yml b/.github/workflows/format_check.yml new file mode 100644 index 0000000..85b07a5 --- /dev/null +++ b/.github/workflows/format_check.yml @@ -0,0 +1,30 @@ +name: format-check +on: + push: + branches: + - main + - 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@v4 + - name: Format check + shell: julia --color=yes {0} + run: | + using Pkg + Pkg.add(PackageSpec(name="JuliaFormatter", version="2")) + using JuliaFormatter + format(".", 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) diff --git a/src/MOI_wrapper.jl b/src/MOI_wrapper.jl index a1ad957..035b147 100644 --- a/src/MOI_wrapper.jl +++ b/src/MOI_wrapper.jl @@ -4,10 +4,7 @@ struct Optimizer{O<:MOI.ModelLike} <: MOI.AbstractOptimizer optimizer::O reformulation::AbstractComplementarityRelaxation function Optimizer(optimizer::MOI.ModelLike) - return new{typeof(optimizer)}( - optimizer, - ScholtesRelaxation(0.0), - ) + return new{typeof(optimizer)}(optimizer, ScholtesRelaxation(0.0)) end end @@ -16,30 +13,21 @@ MOI.empty!(model::Optimizer) = MOI.empty!(model.optimizer) function MOI.supports( model::Optimizer, - attr::Union{ - MOI.AbstractModelAttribute, - MOI.AbstractOptimizerAttribute, - }, + attr::Union{MOI.AbstractModelAttribute,MOI.AbstractOptimizerAttribute}, ) return MOI.supports(model.optimizer, attr) end function MOI.get( model::Optimizer, - attr::Union{ - MOI.AbstractModelAttribute, - MOI.AbstractOptimizerAttribute, - }, + attr::Union{MOI.AbstractModelAttribute,MOI.AbstractOptimizerAttribute}, ) return MOI.get(model.optimizer, attr) end function MOI.set( model::Optimizer, - attr::Union{ - MOI.AbstractModelAttribute, - MOI.AbstractOptimizerAttribute, - }, + attr::Union{MOI.AbstractModelAttribute,MOI.AbstractOptimizerAttribute}, value, ) return MOI.set(model.optimizer, attr, value) @@ -54,9 +42,7 @@ function MOI.supports_constraint( end function MOI.copy_to(dest::Optimizer, src::MOI.ModelLike) - tmp = MOI.Utilities.UniversalFallback( - MOI.Utilities.Model{Float64}() - ) + tmp = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()) tmp_index_map = MOI.copy_to(tmp, src) reformulate_to_vertical!(tmp) reformulate_as_nonlinear_program!(tmp, dest.reformulation) diff --git a/src/nonlinear.jl b/src/nonlinear.jl index 53db413..4915e59 100644 --- a/src/nonlinear.jl +++ b/src/nonlinear.jl @@ -17,20 +17,28 @@ the complementarity constraints. If the complementarity constraints are not in vertical form, an error is thrown. """ -function reformulate_as_nonlinear_program!(model::MOI.ModelLike, relaxation::AbstractComplementarityRelaxation) +function reformulate_as_nonlinear_program!( + model::MOI.ModelLike, + relaxation::AbstractComplementarityRelaxation, +) if !is_vertical(model) - error("Complementarity constraints should be reformulated in vertical form before applying nonlinear reformulation") + error( + "Complementarity constraints should be reformulated in vertical form before applying nonlinear reformulation", + ) end - cc_cons = MOI.get(model, MOI.ListOfConstraintIndices{MOI.VectorOfVariables, MOI.Complements}())[1] + cc_cons = MOI.get( + model, + MOI.ListOfConstraintIndices{MOI.VectorOfVariables,MOI.Complements}(), + )[1] fun = MOI.get(model, MOI.ConstraintFunction(), cc_cons) set = MOI.get(model, MOI.ConstraintSet(), cc_cons) n_comp = div(set.dimension, 2) ind_cc = [] - for cc in 1:n_comp + for cc = 1:n_comp x1 = fun.variables[cc] - x2 = fun.variables[cc + n_comp] + x2 = fun.variables[cc+n_comp] # Get bounds on x2 lb2, ub2 = MOIU.get_bounds(model, Float64, x2) # x2 should have at least one bound, otherwise x1 becomes a fixed variable @@ -71,7 +79,10 @@ end function _relax_complementarity_lower_bound!( model::MOI.ModelLike, relaxation::ScholtesRelaxation, - x1, x2, lb2, ub2, + x1, + x2, + lb2, + ub2, ) lb1, ub1 = MOIU.get_bounds(model, Float64, x1) if isinf(lb1) @@ -80,11 +91,7 @@ function _relax_complementarity_lower_bound!( @assert lb1 == 0.0 # ensure we follow MOI's convention # TODO: what should we do if ub1 is finite? end - idc = MOI.add_constraint( - model, - x1 * (x2 - lb2), - MOI.LessThan(relaxation.tau), - ) + idc = MOI.add_constraint(model, x1 * (x2 - lb2), MOI.LessThan(relaxation.tau)) return [idc] end @@ -92,7 +99,10 @@ end function _relax_complementarity_upper_bound!( model::MOI.ModelLike, relaxation::ScholtesRelaxation, - x1, x2, lb2, ub2, + x1, + x2, + lb2, + ub2, ) lb1, ub1 = MOIU.get_bounds(model, Float64, x1) if isinf(ub1) @@ -101,11 +111,7 @@ function _relax_complementarity_upper_bound!( @assert ub1 == 0.0 # ensure we follow MOI's convention # TODO: what should we do if lb1 is finite? end - idc = MOI.add_constraint( - model, - x1 * (x2 - ub2), - MOI.LessThan(relaxation.tau), - ) + idc = MOI.add_constraint(model, x1 * (x2 - ub2), MOI.LessThan(relaxation.tau)) return [idc] end @@ -113,19 +119,14 @@ end function _relax_complementarity_range!( model::MOI.ModelLike, relaxation::ScholtesRelaxation, - x1, x2, lb2, ub2, + x1, + x2, + lb2, + ub2, ) lb1, ub1 = MOIU.get_bounds(model, Float64, x1) - idc1 = MOI.add_constraint( - model, - x1 * (x2 - lb2), - MOI.LessThan(relaxation.tau), - ) - idc2 = MOI.add_constraint( - model, - x1 * (x2 - ub2), - MOI.LessThan(relaxation.tau), - ) + idc1 = MOI.add_constraint(model, x1 * (x2 - lb2), MOI.LessThan(relaxation.tau)) + idc2 = MOI.add_constraint(model, x1 * (x2 - ub2), MOI.LessThan(relaxation.tau)) return [idc1, idc2] end @@ -149,12 +150,9 @@ function _min_eps(a, b, eps) return MOI.ScalarNonlinearFunction( :-, Any[ - 1.0 * a + 1.0 * b , - MOI.ScalarNonlinearFunction( - :sqrt, - Any[(1.0 * a)^2 + (1.0 * b)^2 + eps^2], - ) - ] + 1.0*a+1.0*b, + MOI.ScalarNonlinearFunction(:sqrt, Any[(1.0*a)^2+(1.0*b)^2+eps^2]), + ], ) end @@ -162,12 +160,9 @@ function _max_eps(a, b, eps) return MOI.ScalarNonlinearFunction( :+, Any[ - 1.0 * a + 1.0 * b , - MOI.ScalarNonlinearFunction( - :sqrt, - Any[(1.0 * a)^2 + (1.0 * b)^2 + eps^2], - ) - ] + 1.0*a+1.0*b, + MOI.ScalarNonlinearFunction(:sqrt, Any[(1.0*a)^2+(1.0*b)^2+eps^2]), + ], ) end @@ -175,7 +170,10 @@ end function _relax_complementarity_lower_bound!( model::MOI.ModelLike, relaxation::FischerBurmeisterRelaxation, - x1, x2, lb2, ub2, + x1, + x2, + lb2, + ub2, ) lb1, ub1 = MOIU.get_bounds(model, Float64, x1) if isinf(lb1) @@ -196,7 +194,10 @@ end function _relax_complementarity_upper_bound!( model::MOI.ModelLike, relaxation::FischerBurmeisterRelaxation, - x1, x2, lb2, ub2, + x1, + x2, + lb2, + ub2, ) lb1, ub1 = MOIU.get_bounds(model, Float64, x1) if isinf(ub1) @@ -217,7 +218,10 @@ end function _relax_complementarity_range!( model::MOI.ModelLike, relaxation::FischerBurmeisterRelaxation, - x1, x2, lb2, ub2, + x1, + x2, + lb2, + ub2, ) lb1, ub1 = MOIU.get_bounds(model, Float64, x1) idc1 = MOI.add_constraint( @@ -252,13 +256,12 @@ end function _relax_complementarity_lower_bound!( model::MOI.ModelLike, relaxation::LiuFukushimaRelaxation, - x1, x2, lb2, ub2, + x1, + x2, + lb2, + ub2, ) - idc1 = MOI.add_constraint( - model, - x1 * (x2 - lb2), - MOI.LessThan(relaxation.epsilon^2), - ) + idc1 = MOI.add_constraint(model, x1 * (x2 - lb2), MOI.LessThan(relaxation.epsilon^2)) idc2 = MOI.add_constraint( model, (x1 + relaxation.epsilon) * (x2 - lb2 + relaxation.epsilon), @@ -276,13 +279,12 @@ end function _relax_complementarity_upper_bound!( model::MOI.ModelLike, relaxation::LiuFukushimaRelaxation, - x1, x2, lb2, ub2, + x1, + x2, + lb2, + ub2, ) - idc1 = MOI.add_constraint( - model, - x1 * (x2 - ub2), - MOI.LessThan(relaxation.epsilon^2), - ) + idc1 = MOI.add_constraint(model, x1 * (x2 - ub2), MOI.LessThan(relaxation.epsilon^2)) idc2 = MOI.add_constraint( model, (x1 - relaxation.epsilon) * (x2 - ub2 - relaxation.epsilon), @@ -325,20 +327,20 @@ function _kanzow_schwarz_relaxation(a, b, eps) return MOI.ScalarNonlinearFunction( :ifelse, Any[ - MOI.ScalarNonlinearFunction( - :>, - Any[1.0 * a + 1.0 * b, 2*eps], - ), - (a - eps) * (b - eps), - - 0.5 * ((a - eps)^2 + (b - eps)^2), - ] + MOI.ScalarNonlinearFunction(:>, Any[1.0*a+1.0*b, 2*eps]), + (a-eps)*(b-eps), + - 0.5*((a-eps)^2+(b-eps)^2), + ], ) end function _relax_complementarity_lower_bound!( model::MOI.ModelLike, relaxation::KanzowSchwarzRelaxation, - x1, x2, lb2, ub2, + x1, + x2, + lb2, + ub2, ) lb1, ub1 = MOIU.get_bounds(model, Float64, x1) if isinf(lb1) @@ -359,7 +361,10 @@ end function _relax_complementarity_upper_bound!( model::MOI.ModelLike, relaxation::KanzowSchwarzRelaxation, - x1, x2, lb2, ub2, + x1, + x2, + lb2, + ub2, ) lb1, ub1 = MOIU.get_bounds(model, Float64, x1) if isinf(ub1) @@ -375,4 +380,3 @@ function _relax_complementarity_upper_bound!( ) return [idc] end - diff --git a/src/vertical.jl b/src/vertical.jl index 860bbdc..985955a 100644 --- a/src/vertical.jl +++ b/src/vertical.jl @@ -1,9 +1,6 @@ -const VF = Union{ - MOI.VectorAffineFunction, - MOI.VectorQuadraticFunction, - MOI.VectorNonlinearFunction, -} +const VF = + Union{MOI.VectorAffineFunction,MOI.VectorQuadraticFunction,MOI.VectorNonlinearFunction} function has_complementarity(model::MOI.ModelLike) return any(MOI.get(model, MOI.ListOfConstraintTypesPresent())) do (F, S) @@ -17,13 +14,16 @@ end _is_single_variable(::MOI.AbstractScalarFunction) = false function _is_single_variable(func::MOI.ScalarAffineFunction) - return length(func.terms) == 1 && func.terms[1].coefficient == 1.0 && iszero(func.constant) + return length(func.terms) == 1 && + func.terms[1].coefficient == 1.0 && + iszero(func.constant) end function _is_single_variable(func::MOI.ScalarQuadraticFunction) - if (length(func.quadratic_terms) == 0 - && length(func.affine_terms) == 1 - && func.affine_terms[1].coefficient == 1.0 - && iszero(func.constant) + if ( + length(func.quadratic_terms) == 0 && + length(func.affine_terms) == 1 && + func.affine_terms[1].coefficient == 1.0 && + iszero(func.constant) ) return true else @@ -46,10 +46,10 @@ function _parse_complementarity_constraint(fun::MOI.AbstractVectorFunction, n_co cc_lhs = MOI.AbstractScalarFunction[] cc_rhs = MOI.VariableIndex[] - for i in 1:n_comp + for i = 1:n_comp # Parse LHS t1 = exprs[i] - t2 = exprs[i + n_comp] + t2 = exprs[i+n_comp] if _is_single_variable(t1) push!(cc_lhs, _get_variable(t1)) else @@ -62,7 +62,9 @@ function _parse_complementarity_constraint(fun::MOI.AbstractVectorFunction, n_co # The RHS should be a variable if we follow MOI's specs # TODO: we should decide if we should add support complementarity # between expressions (see Issue #2) - error("Right-hand-side should be a single variable in complementarity constraints.") + error( + "Right-hand-side should be a single variable in complementarity constraints.", + ) end push!(cc_rhs, _get_variable(t2)) end @@ -90,14 +92,14 @@ function reformulate_to_vertical!(model::MOI.ModelLike) for (F, S) in contypes # Parse only complementarity constraints if S == MOI.Complements - conindices = MOI.get(model, MOI.ListOfConstraintIndices{F, S}()) + conindices = MOI.get(model, MOI.ListOfConstraintIndices{F,S}()) for cidx in conindices fun = MOI.get(model, MOI.ConstraintFunction(), cidx) set = MOI.get(model, MOI.ConstraintSet(), cidx) n_comp = div(set.dimension, 2) if isa(fun, MOI.VectorOfVariables) append!(ind_cc1, fun.variables[1:n_comp]) - append!(ind_cc2, fun.variables[n_comp+1:end]) + append!(ind_cc2, fun.variables[(n_comp+1):end]) elseif isa(fun, VF) # Read each complementarity constraint and get corresponding indices cc_lhs, cc_rhs = _parse_complementarity_constraint(fun, n_comp) @@ -123,7 +125,9 @@ function reformulate_to_vertical!(model::MOI.ModelLike) end end else - error("Complementary constraints formulated with $(typeof(fun)) are not yet supported") + error( + "Complementary constraints formulated with $(typeof(fun)) are not yet supported", + ) end # We delete the complementarity constraints MOI.delete(model, cidx) diff --git a/test/instances.jl b/test/instances.jl index c949442..705589a 100644 --- a/test/instances.jl +++ b/test/instances.jl @@ -19,7 +19,7 @@ function fletcher_leyffer_ex2_model() @variable(model, z[1:2] >= 0) @objective(model, Min, z[1] + z[2]) @constraint(model, z[2]^2 >= 1) - @constraint(model, [z[1], z[2]] ∈ MOI.Complements(2)) + @constraint(model, [z[1], z[2]] ∈ MOI.Complements(2)) return model end @@ -61,8 +61,8 @@ end function design_centering_model() x0 = [0.0, 0.0, 1.0] y0 = [ - -1.000000000000073 0.2425356250359245 0; - 0 0.9701425001468117 -1.000000000026019 + -1.000000000000073 0.2425356250359245 0; + 0 0.9701425001468117 -1.000000000026019 ] l0 = [0.5, 0.5153882031999911, 0.4999999999777709] model = Model() @@ -73,18 +73,21 @@ function design_centering_model() @objective(model, Min, -pi*x[3]^2) # ... lower level solutions lie in body G @constraint(model, g1, -y[1, 1] - y[2, 1]^2 <= 0.0) - @constraint(model, g2, y[1, 2] / 4.0 + y[2, 2] <= 0.75) + @constraint(model, g2, y[1, 2] / 4.0 + y[2, 2] <= 0.75) @constraint(model, g3, -y[2, 3] <= 1.0) # ... first order conditions for 3 lower level problem @constraint(model, 1.0 + 2.0 * (y[1, 1] - x[1]) * l[1] == 0.0) @constraint(model, 2*y[2, 1] + 2.0 * (y[2, 1] - x[2]) * l[1] == 0.0) @constraint(model, -0.25 + 2.0 * (y[1, 2] - x[1]) * l[2] == 0.0) @constraint(model, -1.00 + 2.0 * (y[2, 2] - x[2]) * l[2] == 0.0) - @constraint(model, 0.00 + 2.0 * (y[1, 3] - x[1]) * l[3] == 0.0) - @constraint(model, 1.00 + 2.0 * (y[2, 3] - x[2]) * l[3] == 0.0) + @constraint(model, 0.00 + 2.0 * (y[1, 3] - x[1]) * l[3] == 0.0) + @constraint(model, 1.00 + 2.0 * (y[2, 3] - x[2]) * l[3] == 0.0) # complementarity - for k in 1:3 - @constraint(model, [-(y[1,k] - x[1])^2 - (y[2,k] - x[2])^2 + x[3]^2, l[k]] ∈ MOI.Complements(2)) + for k = 1:3 + @constraint( + model, + [-(y[1, k] - x[1])^2 - (y[2, k] - x[2])^2 + x[3]^2, l[k]] ∈ MOI.Complements(2) + ) end return model end @@ -123,8 +126,8 @@ function desilva_model() @variable(model, y[1:2]) @variable(model, 0.0 <= l[1:2]) @objective(model, Min, x[1]^2 - 2*x[1] + x[2]^2 - 2*x[2] + y[1]^2 + y[2]^2) - for i in 1:2 - @constraint(model, 2.0*y[i] - 2.0*x[i] + 2.0*(y[i] - 1.0) * l[i] == 0.0) + for i = 1:2 + @constraint(model, 2.0*y[i] - 2.0*x[i] + 2.0 * (y[i] - 1.0) * l[i] == 0.0) @constraint(model, [0.25 - (y[i] - 1.0)^2, l[i]] ∈ MOI.Complements(2)) end return model @@ -192,9 +195,13 @@ function hakonsen_model_broken() @variable(model, t[1:2] >= 0.0) @objective(model, Min, (x[1] * x[2] * l)^(1/3)) @constraint(model, prices[i=1:2], [(pL - p[i]), x[i]] ∈ MOI.Complements(2)) - @constraint(model, consum2[i=1:2], [(x[i] * (3.0 * p[i] * (1+t[i])) - 100.0 * pL), p[i]] ∈ MOI.Complements(2)) - @constraint(model, L*pL == sum(x[i] * p[i] for i in 1:2) + l*pL + G) - @constraint(model, revenue, sum(p[i] * t[i] * x[i] for i in 1:2) >= G) + @constraint( + model, + consum2[i=1:2], + [(x[i] * (3.0 * p[i] * (1+t[i])) - 100.0 * pL), p[i]] ∈ MOI.Complements(2) + ) + @constraint(model, L*pL == sum(x[i] * p[i] for i = 1:2) + l*pL + G) + @constraint(model, revenue, sum(p[i] * t[i] * x[i] for i = 1:2) >= G) return model end @@ -216,12 +223,12 @@ function qpec2_model() @variable(model, x[1:n], start=1.0) @variable(model, y[1:m] >= 0.0, start=1.0) @variable(model, s[1:n] >= 0.0) - @objective(model, Min, sum((x[i] + rr)^2 for i in 1:n) + sum((y[j] + ss)^2 for j in 1:m)) + @objective(model, Min, sum((x[i] + rr)^2 for i = 1:n) + sum((y[j] + ss)^2 for j = 1:m)) @constraint(model, [i=1:n], y[i] - x[i] >= 0.0) @constraint(model, [i=1:n], [(y[i] - x[i]), y[i]] ∈ MOI.Complements(2)) # This constraint is degenerate and should be replaced by y = 0 - @constraint(model, [i=n+1:m], [y[i], y[i]] ∈ MOI.Complements(2)) + @constraint(model, [i=(n+1):m], [y[i], y[i]] ∈ MOI.Complements(2)) return model end @@ -271,15 +278,25 @@ function water_net_model() reservoirs = [:NW, :E] consumers = [:CC, :W, :SW, :S, :SE, :N] arcs = [ - (:NW , :W), (:NW , :CC), (:NW , :N), - (:E , :N), (:E , :CC), (:E , :S), (:E , :SE), - (:CC , :W), (:CC , :SW), (:CC , :S), (:CC , :N), - (:S , :SE), (:S , :SW), (:SW , :W), + (:NW, :W), + (:NW, :CC), + (:NW, :N), + (:E, :N), + (:E, :CC), + (:E, :S), + (:E, :SE), + (:CC, :W), + (:CC, :SW), + (:CC, :S), + (:CC, :N), + (:S, :SE), + (:S, :SW), + (:SW, :W), ] - supply = Dict{Symbol, Float64}(:NW => 2.5, :E => 6.0) - wcost = Dict{Symbol, Float64}(:NW => 0.2, :E => 0.17) - pcost = Dict{Symbol, Float64}(:NW => 1.02, :E => 1.02) - demand = Dict{Symbol, Float64}( + supply = Dict{Symbol,Float64}(:NW => 2.5, :E => 6.0) + wcost = Dict{Symbol,Float64}(:NW => 0.2, :E => 0.17) + pcost = Dict{Symbol,Float64}(:NW => 1.02, :E => 1.02) + demand = Dict{Symbol,Float64}( :NW => 0.0, :E => 0.0, :CC => 1.212, @@ -289,35 +306,35 @@ function water_net_model() :SE => 0.252, :N => 0.456, ) - height = Dict{Symbol, Float64}( + height = Dict{Symbol,Float64}( :NW => 6.50, - :E => 3.25, + :E => 3.25, :CC => 3.02, - :W => 5.16, + :W => 5.16, :SW => 4.20, - :S => 1.50, + :S => 1.50, :SE => 0.00, - :N => 6.30, + :N => 6.30, ) - x = Dict{Symbol, Float64}( - :NW => 1200, - :E => 4000, - :CC => 2000, - :W => 750, - :SW => 900, - :S => 2000, - :SE => 4000, - :N => 3700, + x = Dict{Symbol,Float64}( + :NW => 1200, + :E => 4000, + :CC => 2000, + :W => 750, + :SW => 900, + :S => 2000, + :SE => 4000, + :N => 3700, ) - y = Dict{Symbol, Float64}( - :NW => 3600, - :E => 2200, - :CC => 2300, - :W => 2400, - :SW => 1200, - :S => 1000, - :SE => 900, - :N => 3500, + y = Dict{Symbol,Float64}( + :NW => 3600, + :E => 2200, + :CC => 2300, + :W => 2400, + :SW => 1200, + :S => 1000, + :SE => 900, + :N => 3500, ) dist = Dict((i, j) => sqrt((x[i] - x[j])^2 + (y[i] - y[j])^2) for (i, j) in arcs) @@ -350,8 +367,10 @@ function water_net_model() @variable(model, 0 <= s[i in reservoirs] <= supply[i], start=rr*supply[i]) @objective( - model, Min, - sum(s[i] * pcost[i] * (h[i] - height[i]) + s[i] * wcost[i] for i in reservoirs) / r + + model, + Min, + sum(s[i] * pcost[i] * (h[i] - height[i]) + s[i] * wcost[i] for i in reservoirs) / + r + dprc * sum(dist[(i, j)] * d[(i, j)]^cpow for (i, j) in arcs) + sum(qp[(i, j)] + qn[(i, j)] for (i, j) in arcs), ) @@ -367,7 +386,8 @@ function water_net_model() @constraint( model, loss[(i, j) in arcs], - h[i] - h[j] == hloss * dist[(i, j)] * (qp[(i, j)]^2 - qn[(i, j)]^2) / (d[(i, j)]^dpow), + h[i] - h[j] == + hloss * dist[(i, j)] * (qp[(i, j)]^2 - qn[(i, j)]^2) / (d[(i, j)]^dpow), ) # ... complementarity @constraint(model, [(i, j) in arcs], [qp[(i, j)], qn[(i, j)]] ∈ MOI.Complements(2)) diff --git a/test/runtests.jl b/test/runtests.jl index 7a182e2..b1d7fb6 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -43,9 +43,8 @@ function nonlinear_test_reformulated_model() return model end -expected_models = Dict( - Instances.fletcher_leyffer_ex1_model => fletcher_leyffer_ex1_nonlinear_model, -) +expected_models = + Dict(Instances.fletcher_leyffer_ex1_model => fletcher_leyffer_ex1_nonlinear_model) function test_model(model_func) model = model_func() @@ -110,4 +109,4 @@ end @test JuMP.objective_value(model) ≈ 0.5 atol=1e-7 @test JuMP.value.(model[:z]) ≈ [0.5, 0.5] atol=1e-7 -end \ No newline at end of file +end