Skip to content

Commit 761adbd

Browse files
committed
overload functions (rewrite a lot of functions); rename functions; now use :hull
1 parent 9d2bd9d commit 761adbd

File tree

12 files changed

+656
-377
lines changed

12 files changed

+656
-377
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "DisjunctiveProgramming"
22
uuid = "0d27d021-0159-4c7d-b4a7-9ccb5d9366cf"
33
authors = ["hdavid16 <[email protected]>"]
4-
version = "0.1.7"
4+
version = "0.2.0"
55

66
[deps]
77
IntervalArithmetic = "d1acc4aa-44c8-5952-acd4-ba5d80a2a253"

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ NOTES:
2424
- It is assumed that the disjuncts belonging to a disjunction are proper disjunctions (mutually exclussive) and only one of them will be selected (`XOR`).
2525

2626
The valid key-word arguments for the `@disjunction` macro are:
27-
- `reformulation::Symbol`: `:big_m` for [Big-M Reformulation](https://optimization.mccormick.northwestern.edu/index.php/Disjunctive_inequalities#Big-M_Reformulation), `:convex_hull` for [Convex-Hull Reformulation](https://optimization.mccormick.northwestern.edu/index.php/Disjunctive_inequalities#Convex-Hull_Reformulation)
27+
- `reformulation::Symbol`: `:big_m` for [Big-M Reformulation](https://optimization.mccormick.northwestern.edu/index.php/Disjunctive_inequalities#Big-M_Reformulation), `:hull` for [Hull Reformulation](https://optimization.mccormick.northwestern.edu/index.php/Disjunctive_inequalities#Convex-Hull_Reformulation)
2828
- `M`: Big-M value used when `reformulation = :big_m`.
29-
- `ϵ`: epsilon tolerance for the perspective function proposed by [Furman, et al. [2020]](https://link.springer.com/article/10.1007/s10589-020-00176-0). Only used when `reformulation = :convex_hull`.
29+
- `ϵ`: epsilon tolerance for the perspective function proposed by [Furman, et al. [2020]](https://link.springer.com/article/10.1007/s10589-020-00176-0). Only used when `reformulation = :hull`.
3030
- `name::Symbol`: Name for the disjunction (also name for indicator variable used on that disjunction). If not passed (`name = missing`), a symbolic name will be generated with the prefix `disj`. The mutual exclussion constraint on the binary indicator variables can be accessed with `model[Symbol("XOR(disj_$name)")]`.
3131

32-
When a disjunction is defined using the `@disjunction` macro, the disjunctions are reformulated to algebraic constraints via either Big-M or Convex-Hull reformulations. For the Convex-Hull reformulation, disaggregated variables are generated by adding the suffix `_$name$i` to the original variables, where `i` is the index of the disjunct in that disjunction. Bounding constraints are applied to the disaggregated variables and can be accessed with `model[Symbol("$<original var>_$name$i_lb")]` and `model[Symbol("$<original var>_$name$i_ub")]` for the lower bound and upper bound constraints, respectively. The aggregation constraint can be accessed with `model[Symbol("$<original var>_aggregation")]`. For Big-M reformulations, the user may provide an `M` object that represents the BigM value(s). The `M` object can be a `Number` that is applied to all constraints in the disjuncts, or a `Vector`/`Tuple` of values that are used for each of the disjuncts. For Convex-Hull reformulations, the user may provide an `ϵ` value for the perspective function (default is `ϵ = 1e-6`). The `ϵ` object can be a `Number` that is applied to all perspective functions, or a `Vector`/`Tuple` of values that are used for each of the disjuncts.
32+
When a disjunction is defined using the `@disjunction` macro, the disjunctions are reformulated to algebraic constraints via either Big-M or Hull reformulations. For the Hull reformulation, disaggregated variables are generated by adding the suffix `_$name$i` to the original variables, where `i` is the index of the disjunct in that disjunction. Bounding constraints are applied to the disaggregated variables and can be accessed with `model[Symbol("$<original var>_$name$i_lb")]` and `model[Symbol("$<original var>_$name$i_ub")]` for the lower bound and upper bound constraints, respectively. The aggregation constraint can be accessed with `model[Symbol("$<original var>_aggregation")]`. For Big-M reformulations, the user may provide an `M` object that represents the BigM value(s). The `M` object can be a `Number` that is applied to all constraints in the disjuncts, or a `Vector`/`Tuple` of values that are used for each of the disjuncts. For Hull reformulations, the user may provide an `ϵ` value for the perspective function (default is `ϵ = 1e-6`). The `ϵ` object can be a `Number` that is applied to all perspective functions, or a `Vector`/`Tuple` of values that are used for each of the disjuncts.
3333

3434
For empty disjuncts, use `nothing` for their positional argument (e.g., `@disjunction(m, x <= 1, nothing, reformulation = :big_m)`).
3535

@@ -51,7 +51,7 @@ The example below is from the [Northwestern University Process Optimization Open
5151

5252
To perform the Big-M reformulation, `:big_m` is passed to the `reformulation` keyword argument. If nothing is passed to the keyword argument `M`, tight Big-M values will be inferred from the variable bounds using IntervalArithmetic.jl. If `x` is not bounded, Big-M values must be provided for either the whole system (e.g., `M = 10`) or for each of the constraint arrays in the example (e.g., `M = (10,10)`).
5353

54-
To perform the Convex-Hull reformulation, `reformulation = :convex_hull`. Variables must have bounds for the reformulation to work.
54+
To perform the Hull reformulation, `reformulation = :hull`. Variables must have bounds for the reformulation to work.
5555

5656
```julia
5757
using JuMP

examples/ex3.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ m = Model()
1313
3 exp(x)
1414
5 x
1515
end,
16-
reformulation=:convex_hull,
16+
reformulation=:hull,
1717
name=:z
1818
)
1919
print(m)
@@ -22,7 +22,6 @@ print(m)
2222
# Subject to
2323
# XOR(disj_z) : z[1] + z[2] == 1.0 <- XOR constraint
2424
# x_aggregation : x - x_z1 - x_z2 == 0.0 <- aggregation of disaggregated variables
25-
# disj_z[1,2] : -x_z1 - 3 z[1] <= 0.0 <- convex-hull reformulation of 2nd constraint if 1st disjunct (named disj_z[1,2] to indicate 1st disjunct, 2nd constraint)
2625
# x_z1_lb : -5 z[1] - x_z1 <= 0.0 <- lower-bound constraint on disaggregated variable x_z1 (x in 1st disjunct)
2726
# x_z1_ub : -10 z[1] + x_z1 <= 0.0 <- upper-bound constraint on disaggregated variable x_z1 (x in 1st disjunct)
2827
# x_z2_lb : -5 z[2] - x_z2 <= 0.0 <- lower-bound constraint on disaggregated variable x_z2 (x in 2nd disjunct)

src/DisjunctiveProgramming.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ export @disjunction, @proposition
88
include("constraint.jl")
99
include("logic.jl")
1010
include("utils.jl")
11-
include("big_M.jl")
12-
include("convex_hull.jl")
11+
include("bigm.jl")
12+
include("hull.jl")
1313
include("reformulate.jl")
1414
include("macros.jl")
1515

src/big_M.jl

Lines changed: 0 additions & 45 deletions
This file was deleted.

src/bigm.jl

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# function big_m_reformulation!(constr, bin_var, i, k, M)
2+
# if ismissing(k)
3+
# ref = constr
4+
# elseif k isa CartesianIndex
5+
# ref = constr[k]
6+
# else
7+
# ref = constr[k...]
8+
# end
9+
# if ismissing(M)
10+
# M = apply_interval_arithmetic(ref)
11+
# # @warn "No M value passed for $ref. M = $M was inferred from the variable bounds."
12+
# elseif !ismissing(k) && !isa(M,Real)
13+
# M = M[k]
14+
# end
15+
# if ref isa NonlinearConstraintRef
16+
# nonlinear_bigM(ref, bin_var, M, i)
17+
# elseif ref isa ConstraintRef
18+
# linear_bigM(ref, bin_var, M, i)
19+
# end
20+
# end
21+
22+
function big_m_reformulation!(constr::ConstraintRef, bin_var, M, i, j, k)
23+
M = get_reform_param(M, i, j, k; constr)
24+
linear_bigM(constr, bin_var, M, i)
25+
end
26+
function big_m_reformulation!(constr::NonlinearConstraintRef, bin_var, M, i, j, k)
27+
M = get_reform_param(M, i, j, k; constr)
28+
nonlinear_bigM(constr, bin_var, M, i)
29+
end
30+
big_m_reformulation!(constr::AbstractArray, bin_var, M, i, j, k) =
31+
big_m_reformulation(constr[k], bin_var, M, i, j, k)
32+
33+
function linear_bigM(ref, bin_var, M, i)
34+
bin_var_ref = ref.model[bin_var][i]
35+
add_to_function_constant(ref, -M)
36+
set_normalized_coefficient(ref, bin_var_ref , M)
37+
end
38+
39+
function nonlinear_bigM(ref, bin_var, M, i)
40+
#create symbolic variables (using Symbolics.jl)
41+
for var_ref in ref.model[:gdp_variable_refs]
42+
var_sym = Symbol(var_ref)
43+
eval(:(Symbolics.@variables($var_sym)[1]))
44+
end
45+
bin_var_sym = Symbol("$bin_var[$i]")
46+
λ = Num(Symbolics.Sym{Float64}(bin_var_sym))
47+
48+
#parse ref
49+
op, lhs, rhs = parse_NLconstraint(ref)
50+
replace_Symvars!(lhs, ref.model) #convert JuMP variables into Symbolic variables
51+
gx = eval(lhs) #convert the LHS of the constraint into a Symbolic expression
52+
gx = gx - M*(1-λ) #add bigM
53+
54+
#update constraint
55+
replace_NLconstraint(ref, gx, op, rhs)
56+
end

0 commit comments

Comments
 (0)