@@ -39,26 +39,37 @@ function bridge_constraint(
3939 f:: F ,
4040 s:: MOI.HyperRectangle ,
4141) 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)
5668 end
5769 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])
6071 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] )
6273end
6374
6475function MOI. supports_constraint (
@@ -97,33 +108,41 @@ function MOI.get(
97108) where {T,G,F}
98109 f = MOI. get (model, MOI. ConstraintFunction (), bridge. ci)
99110 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))
115112 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))
118115 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)
120129 end
121130 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
124144 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))
127146end
128147
129148function MOI. get (
0 commit comments