4
4
# in the LICENSE.md file or at https://opensource.org/licenses/MIT.
5
5
6
6
"""
7
- Computes a set of constraints which could not be satisfied when trying to minimize the total violations.
7
+ compute_minimum_unsatisfied_constraints!(o::Optimizer)
8
+
9
+ Computes a set of constraints which could not be satisfied when trying to
10
+ minimize the total violations.
8
11
9
12
Given the problem:
10
13
```
11
14
(P) min_x c^⊤ x
12
- s.t. F(x) ∈ S_i ∀ i in 1…m
15
+ s.t. F(x) ∈ S_i ∀ i in 1…m
13
16
```
14
-
15
- the analysis uses a feasibility relaxation based on slack variables and indicator constraints:
17
+ the analysis uses a feasibility relaxation based on slack variables and
18
+ indicator constraints:
16
19
```
17
20
(M) min_{x, z} ∑_i z_i
18
- s.t. z_i = 0 → F(x) ∈ S_i ∀ i in 1…m
19
- z ∈ {0,1}ᵐ
21
+ s.t. z_i = 0 → F(x) ∈ S_i ∀ i in 1…m
22
+ z ∈ {0,1}ᵐ
20
23
```
21
24
22
- If (P) is infeasible, (M) has an optimal value above 1.
23
- All constraints with `z = 1` had to be violated.
25
+ If (P) is infeasible, (M) has an optimal value above 1. All constraints with
26
+ `z = 1` had to be violated.
24
27
"""
25
28
function compute_minimum_unsatisfied_constraints! (o:: Optimizer )
26
29
if o. conflict_status != MOI. COMPUTE_CONFLICT_NOT_CALLED
@@ -34,21 +37,17 @@ function compute_minimum_unsatisfied_constraints!(o::Optimizer)
34
37
end
35
38
# first transform all variable bound constraints to constraint bounds
36
39
for (F, S) in MOI. get (o, MOI. ListOfConstraintTypesPresent ())
40
+ if ! (F == MOI. VariableIndex && S <: BOUNDS )
41
+ continue
42
+ end
37
43
sname = replace (string (S), " MathOptInterface." => " " , " {Float64}" => " " )
38
- if Tuple{F,S} <: Tuple{MOI.VariableIndex,BOUNDS}
39
- for (idx, c_index) in
40
- enumerate (MOI. get (o, MOI. ListOfConstraintIndices {F,S} ()))
41
- s = MOI. get (o, MOI. ConstraintSet (), c_index)
42
- MOI. delete (o, c_index)
43
- vi = MOI. VariableIndex (c_index. value)
44
- ci_new = MOI. add_constraint (o, 1.0 * vi, s)
45
- MOI. set (
46
- o,
47
- MOI. ConstraintName (),
48
- ci_new,
49
- " varcons_$(c_index. value) _$sname " ,
50
- )
51
- end
44
+ for ci in MOI. get (o, MOI. ListOfConstraintIndices {F,S} ())
45
+ set = MOI. get (o, MOI. ConstraintSet (), ci)
46
+ MOI. delete (o, ci)
47
+ x = MOI. VariableIndex (ci. value)
48
+ ci_new = MOI. add_constraint (o, 1.0 * x, set)
49
+ name = " varcons_$(x. value) _$sname "
50
+ MOI. set (o, MOI. ConstraintName (), ci_new, name)
52
51
end
53
52
end
54
53
# we need names for all constraints
@@ -80,31 +79,38 @@ function compute_minimum_unsatisfied_constraints!(o::Optimizer)
80
79
if st != MOI. OPTIMAL
81
80
error (" Unexpected status $st when computing conflicts" )
82
81
end
83
- o . conflict_status = if MOI. get (o, MOI. ObjectiveValue ()) > 0
84
- MOI. CONFLICT_FOUND
82
+ if MOI. get (o, MOI. ObjectiveValue ()) > 0
83
+ o . conflict_status = MOI. CONFLICT_FOUND
85
84
else
86
- MOI. NO_CONFLICT_EXISTS
85
+ o . conflict_status = MOI. NO_CONFLICT_EXISTS
87
86
end
88
87
return
89
88
end
90
89
91
90
"""
92
- Model attribute representing whether why the Minimum Unsatisfiable Constraint analysis terminated.
91
+ UnsatisfiableSystemStatus() <: MOI.AbstractModelAttribute
92
+
93
+ Model attribute representing whether why the Minimum Unsatisfiable Constraint
94
+ analysis terminated.
93
95
"""
94
96
struct UnsatisfiableSystemStatus <: MOI.AbstractModelAttribute end
95
97
96
- attribute_value_type (:: UnsatisfiableSystemStatus ) = MOI. ConflictStatusCode
98
+ MOI . attribute_value_type (:: UnsatisfiableSystemStatus ) = MOI. ConflictStatusCode
97
99
98
100
MOI. get (o:: Optimizer , :: UnsatisfiableSystemStatus ) = o. conflict_status
99
101
100
102
"""
101
- Attribute representing whether the constraint could be satisfied in the Minimum Unsatisfiable Constraint analysis.
103
+ ConstraintSatisfiabilityStatus() <: MOI.AbstractModelAttribute
102
104
103
- Note that this is different from a constraint belonging to an Irreducible Infeasible Subsystem.
105
+ Attribute representing whether the constraint could be satisfied in the Minimum
106
+ Unsatisfiable Constraint analysis.
107
+
108
+ Note that this is different from a constraint belonging to an Irreducible
109
+ Infeasible Subsystem.
104
110
"""
105
111
struct ConstraintSatisfiabilityStatus <: MOI.AbstractConstraintAttribute end
106
112
107
- function attribute_value_type (:: ConstraintSatisfiabilityStatus )
113
+ function MOI . attribute_value_type (:: ConstraintSatisfiabilityStatus )
108
114
return MOI. ConflictParticipationStatusCode
109
115
end
110
116
@@ -113,8 +119,11 @@ function MOI.get(
113
119
:: ConstraintSatisfiabilityStatus ,
114
120
index:: MOI.ConstraintIndex{MOI.VariableIndex} ,
115
121
)
116
- o. conflict_status == MOI. CONFLICT_FOUND || error (" no conflict" )
117
- # we cannot determine whether variable constraint (integer, binary, variable bounds) participate
122
+ if o. conflict_status != MOI. CONFLICT_FOUND
123
+ return MOI. NOT_IN_CONFLICT
124
+ end
125
+ # We cannot determine whether variable constraint (integer, binary, variable
126
+ # bounds) participate.
118
127
return MOI. MAYBE_IN_CONFLICT
119
128
end
120
129
@@ -123,15 +132,13 @@ function MOI.get(
123
132
:: ConstraintSatisfiabilityStatus ,
124
133
index:: MOI.ConstraintIndex ,
125
134
)
126
- o. conflict_status == MOI. CONFLICT_FOUND || error (" no conflict" )
127
- c_name = MOI. get (o, MOI. ConstraintName (), index)
128
- slack_name = " $(c_name) _master"
129
- ptr = SCIPfindVar (o, slack_name)
130
- if ptr == C_NULL
131
- error (
132
- " No constraint name corresponds to the index $index - name $c_name " ,
133
- )
135
+ MOI. throw_if_not_valid (o, index)
136
+ if o. conflict_status != MOI. CONFLICT_FOUND
137
+ return MOI. NOT_IN_CONFLICT
134
138
end
139
+ c_name = MOI. get (o, MOI. ConstraintName (), index)
140
+ ptr = SCIPfindVar (o, " $(c_name) _master" )
141
+ @assert ptr != C_NULL
135
142
sol = SCIPgetBestSol (o)
136
143
slack_value = SCIPgetSolVal (o, sol, ptr)
137
144
return slack_value > 0.5 ? MOI. IN_CONFLICT : MOI. NOT_IN_CONFLICT
0 commit comments