@@ -39,26 +39,37 @@ function bridge_constraint(
39
39
f:: F ,
40
40
s:: MOI.HyperRectangle ,
41
41
) where {T,G,F}
42
- lower = MOI. Utilities. operate (- , T, f, s. lower)
43
- upper = MOI. Utilities. operate (- , T, s. upper, f)
44
- if any (! isfinite, s. lower)
45
- indices = [i for (i, l) in enumerate (s. lower) if isfinite (l)]
46
- lower = MOI. Utilities. eachscalar (lower)[indices]
47
- end
48
- if any (! isfinite, s. upper)
49
- indices = [i for (i, u) in enumerate (s. upper) if isfinite (u)]
50
- upper = MOI. Utilities. eachscalar (upper)[indices]
51
- end
52
- free_indices = Int[]
53
- for (i, (l, u)) in enumerate (zip (s. lower, s. upper))
54
- if ! isfinite (l) && ! isfinite (u)
55
- push! (free_indices, i)
42
+ N = MOI. dimension (s)
43
+ g_vec = Vector {MOI.Utilities.scalar_type(G)} (undef, 2 * MOI. dimension (s))
44
+ rows_to_keep = fill (true , length (g_vec))
45
+ free_rows = Int[]
46
+ scalars = MOI. Utilities. eachscalar (f)
47
+ for (i, fi) in enumerate (scalars)
48
+ if ! isfinite (s. lower[i])
49
+ rows_to_keep[i] = false
50
+ # It doesn't really matter what goes here. We're going to drop it
51
+ # when we vectorize the function
52
+ g_vec[i] = fi
53
+ elseif iszero (s. lower[i])
54
+ g_vec[i] = fi
55
+ else
56
+ g_vec[i] = MOI. Utilities. operate (- , T, fi, s. lower[i])
57
+ end
58
+ if ! isfinite (s. upper[i])
59
+ rows_to_keep[N+ i] = false
60
+ g_vec[N+ i] = fi
61
+ elseif iszero (s. upper[i])
62
+ g_vec[N+ i] = MOI. Utilities. operate (- , T, fi)
63
+ else
64
+ g_vec[N+ i] = MOI. Utilities. operate (- , T, s. upper[i], fi)
65
+ end
66
+ if ! isfinite (s. lower[i]) && ! isfinite (s. upper[i])
67
+ push! (free_rows, i)
56
68
end
57
69
end
58
- free_rows = MOI. Utilities. eachscalar (f)[free_indices]
59
- g = MOI. Utilities. operate (vcat, T, lower, upper)
70
+ g = MOI. Utilities. vectorize (g_vec[rows_to_keep])
60
71
ci = MOI. add_constraint (model, g, MOI. Nonnegatives (MOI. output_dimension (g)))
61
- return SplitHyperRectangleBridge {T,G,F} (ci, s, free_rows)
72
+ return SplitHyperRectangleBridge {T,G,F} (ci, s, scalars[ free_rows] )
62
73
end
63
74
64
75
function MOI. supports_constraint (
@@ -97,33 +108,41 @@ function MOI.get(
97
108
) where {T,G,F}
98
109
f = MOI. get (model, MOI. ConstraintFunction (), bridge. ci)
99
110
f_s = MOI. Utilities. eachscalar (f)
100
- s = bridge. set
101
- func = Vector {eltype(f_s)} (undef, MOI. dimension (s))
102
-
103
- lower_indices = [i for (i, l) in enumerate (s. lower) if isfinite (l)]
104
- for (i, index) in enumerate (lower_indices)
105
- func[index] = MOI. Utilities. operate (+ , T, f_s[i], s. lower[index])
106
- end
107
-
108
- upper_indices = [i for (i, u) in enumerate (s. upper) if isfinite (u)]
109
- for (j, index) in enumerate (upper_indices)
110
- i = length (lower_indices) + j
111
- if ! (index in lower_indices)
112
- func[index] = MOI. Utilities. operate (- , T, s. upper[index], f_s[i])
113
- end
114
- end
111
+ func = Vector {eltype(f_s)} (undef, MOI. dimension (bridge. set))
115
112
free_s = MOI. Utilities. eachscalar (bridge. free_rows)
116
- free_indices = Int[]
117
- for (i , (l, u)) in enumerate (zip (s . lower, s . upper))
113
+ n_free_rows, n_f_rows, upper_bound_rows = 0 , 0 , Int[]
114
+ for (row , (l, u)) in enumerate (zip (bridge . set . lower, bridge . set . upper))
118
115
if ! isfinite (l) && ! isfinite (u)
119
- push! (free_indices, i)
116
+ n_free_rows += 1
117
+ func[row] = free_s[n_free_rows]
118
+ elseif iszero (l)
119
+ n_f_rows += 1
120
+ func[row] = f_s[n_f_rows]
121
+ elseif isfinite (l)
122
+ n_f_rows += 1
123
+ func[row] = MOI. Utilities. operate (+ , T, f_s[n_f_rows], l)
124
+ else
125
+ @assert isfinite (u)
126
+ # This row exists only as u - f, but we don't know where it starts
127
+ # yet because we need to count all the `f - l` rows first.
128
+ push! (upper_bound_rows, row)
120
129
end
121
130
end
122
- for (i, index) in enumerate (free_indices)
123
- func[index] = free_s[i]
131
+ for (row, (l, u)) in enumerate (zip (bridge. set. lower, bridge. set. upper))
132
+ if ! isfinite (u)
133
+ continue
134
+ end
135
+ n_f_rows += 1
136
+ if ! (row in upper_bound_rows)
137
+ continue
138
+ end
139
+ func[row] = if iszero (bridge. set. upper[row])
140
+ MOI. Utilities. operate (- , T, f_s[n_f_rows])
141
+ else
142
+ MOI. Utilities. operate (- , T, bridge. set. upper[row], f_s[n_f_rows])
143
+ end
124
144
end
125
- g = MOI. Utilities. operate (vcat, T, func... )
126
- return MOI. Utilities. convert_approx (F, g)
145
+ return MOI. Utilities. convert_approx (F, MOI. Utilities. vectorize (func))
127
146
end
128
147
129
148
function MOI. get (
0 commit comments