@@ -96,6 +96,114 @@ function get_inner_constraint(com, vars::MOI.VectorOfVariables, set::Union{Reifi
96
96
return init_constraint_struct (com, set. set, inner_internals)
97
97
end
98
98
99
+ """
100
+ get_bool_constraint_fct_set(T, constraint::BoolConstraint, lhs_fct, lhs_set, rhs_fct, rhs_set)
101
+
102
+ Create the fct and set of a [`BoolConstraint`](@ref) which combines the left hand side with the right hand side.
103
+ """
104
+ function get_bool_constraint_fct_set (T, constraint:: BoolConstraint , lhs_fct, lhs_set, rhs_fct, rhs_set)
105
+ BS = typeof_without_params (constraint. set)
106
+ fct = MOIU. operate (vcat, T, lhs_fct, rhs_fct)
107
+ set = BS {typeof(lhs_fct), typeof(rhs_fct)} (lhs_set, rhs_set)
108
+ return fct, set
109
+ end
110
+
111
+ function find_element_var_and_combine (T, constraint:: BoolConstraint , element_constraint, element_var)
112
+ lhs = constraint. lhs
113
+ rhs = constraint. rhs
114
+ if element_var in lhs. indices
115
+ if lhs isa BoolConstraint
116
+ fct, set = find_element_var_and_combine (T, lhs, element_constraint, element_var)
117
+ else
118
+ fct = MOIU. operate (vcat, T, lhs. fct, element_constraint. fct)
119
+ set = XNorSet {typeof(lhs.fct), typeof(element_constraint.fct)} (lhs. set, element_constraint. set)
120
+ end
121
+ fct, set = get_bool_constraint_fct_set (T, constraint, fct, set, rhs. fct, rhs. set)
122
+ else
123
+ if rhs isa BoolConstraint
124
+ fct, set = find_element_var_and_combine (T, rhs, element_constraint, element_var)
125
+ else
126
+ fct = MOIU. operate (vcat, T, element_constraint. fct, rhs. fct)
127
+ set = XNorSet {typeof(element_constraint.fct), typeof(rhs.fct)} (element_constraint. set, rhs. set)
128
+ end
129
+ fct, set = get_bool_constraint_fct_set (T, constraint, lhs. fct, lhs. set, fct, set)
130
+ end
131
+ return fct, set
132
+ end
133
+
134
+ function create_new_activator_constraint (model, activation_constraint:: ActivatorConstraint , fct, set)
135
+ com = model. inner
136
+ T = parametric_type (com)
137
+ ACS = typeof_without_params (activation_constraint. set)
138
+ A = get_activation_condition (activation_constraint. set)
139
+ if ACS == MOI. IndicatorSet
140
+ ACS = IndicatorSet
141
+ end
142
+ f = MOIU. eachscalar (activation_constraint. fct)
143
+
144
+ activator_fct = f[1 ]
145
+ fct = MOIU. operate (vcat, T, activator_fct, fct)
146
+ MOI. add_constraint (model, fct, ACS {A,typeof(fct)} (set))
147
+ end
148
+
149
+ """
150
+ move_element_constraint(model)
151
+
152
+ If there are element constraints which are only used inside of an indicator or reified constraint
153
+ => combine them with xnor and deactivate the previously added element constraint
154
+ this is to avoid filtering based on this element constraint when the inner constraint isn't active
155
+ For more see: https://github.com/Wikunia/ConstraintSolver.jl/pull/213#issuecomment-860954185
156
+ """
157
+ function move_element_constraint (model)
158
+ com = model. inner
159
+ T = parametric_type (com)
160
+ constraints = com. constraints
161
+ subscriptions = com. subscription
162
+ for element_cons in constraints
163
+ element_cons isa Element1DConstConstraint || continue
164
+ element_var = element_cons. indices[1 ]
165
+
166
+ # check if the element var only appears in indicator or reified constraints
167
+ only_inside = true
168
+ for constraint in constraints[subscriptions[element_var]]
169
+ # if not inside indicator, reified or OrConstraint and not the current constraint that we check
170
+ if ! (constraint isa ActivatorConstraint) && ! (constraint isa OrConstraint) && constraint. idx != element_cons. idx
171
+ only_inside = false
172
+ end
173
+ end
174
+ ! only_inside && continue
175
+ # check if at least once inside
176
+ only_inside = false
177
+ for constraint in constraints[subscriptions[element_var]]
178
+ if constraint isa ActivatorConstraint || constraint isa OrConstraint
179
+ only_inside = true
180
+ break
181
+ end
182
+ end
183
+ ! only_inside && continue
184
+
185
+ element_cons. is_deactivated = true
186
+ for constraint in constraints[subscriptions[element_var]]
187
+ constraint isa Element1DConstConstraint && continue
188
+ constraint. is_deactivated && continue
189
+ fct, set = nothing , nothing
190
+ if constraint isa ActivatorConstraint
191
+ if constraint. inner_constraint isa OrConstraint
192
+ inner_constraint = constraint. inner_constraint
193
+ fct, set = find_element_var_and_combine (T, inner_constraint, element_cons, element_var)
194
+ else
195
+ fct = MOIU. operate (vcat, T, constraint. inner_constraint. fct, element_cons. fct)
196
+ set = XNorSet {typeof(constraint.inner_constraint.fct), typeof(element_cons.fct)} (constraint. inner_constraint. set, element_cons. set)
197
+ end
198
+ create_new_activator_constraint (model, constraint, fct, set)
199
+ else # OrConstraint
200
+ fct, set = find_element_var_and_combine (T, constraint, element_cons, element_var)
201
+ MOI. add_constraint (model, fct, set)
202
+ end
203
+ end
204
+ end
205
+ end
206
+
99
207
function get_activator_internals (A, indices)
100
208
ActivatorConstraintInternals (A, indices[1 ] in indices[2 : end ], false , 0 )
101
209
end
0 commit comments