@@ -9,12 +9,17 @@ function Base.getindex(model::LinQuadOptimizer, index::CI)
99 return constrdict (model, index)[index]
1010end
1111
12- function delete_constraint_name (model:: LinQuadOptimizer , index)
12+ # Internal function: delete the constraint name.
13+ function delete_constraint_name (model:: LinQuadOptimizer , index:: CI )
1314 if haskey (model. constraint_names, index)
1415 name = model. constraint_names[index]
15- delete! (model. constraint_names_rev, name)
16+ reverse_map = model. constraint_names_rev[name]
17+ if index in reverse_map
18+ pop! (reverse_map, index)
19+ end
1620 delete! (model. constraint_names, index)
1721 end
22+ return
1823end
1924
2025"""
99104 Get constraint names
100105=#
101106
102- function MOI. get (model:: LinQuadOptimizer , :: MOI.ConstraintName , index:: MOI.ConstraintIndex )
107+ function MOI. get (model:: LinQuadOptimizer , :: MOI.ConstraintName , index:: CI )
103108 if haskey (model. constraint_names, index)
104109 return model. constraint_names[index]
105110 else
106111 return " "
107112 end
108113end
109- function MOI. supports (:: LinQuadOptimizer , :: MOI.ConstraintName , :: Type{<:MOI.ConstraintIndex} )
114+ function MOI. supports (
115+ :: LinQuadOptimizer , :: MOI.ConstraintName , :: Type{<:MOI.ConstraintIndex} )
110116 return true
111117end
118+
119+ # The rules for MOI are:
120+ # - Allow setting duplicate variable names
121+ # - Throw an error on get if the name is a duplicate
122+ # So we need to store two things.
123+ # 1. a mapping from ConstraintIndex -> Name
124+ # 2. a reverse mapping from Name -> set of ConstraintIndex's with that name
112125function MOI. set (model:: LinQuadOptimizer , :: MOI.ConstraintName ,
113126 index:: MOI.ConstraintIndex , name:: String )
114- if haskey (model. constraint_names_rev, name)
115- if model. constraint_names_rev[name] != index
116- error (" Duplicate constraint name: $(name) " )
117- end
118- elseif name != " "
119- if haskey (model. constraint_names, index)
120- # we're renaming an existing constraint
121- old_name = model. constraint_names[index]
122- delete! (model. constraint_names_rev, old_name)
123- end
127+ if haskey (model. constraint_names, index)
128+ # This constraint already has a name, we must be changing it.
129+ current_name = model. constraint_names[index]
130+ # Remove `index` from the set of current name.
131+ pop! (model. constraint_names_rev[current_name], index)
132+ end
133+ if name != " "
134+ # We're changing the name to something non-default, so store it.
124135 model. constraint_names[index] = name
125- model. constraint_names_rev[name] = index
136+ if ! haskey (model. constraint_names_rev, name)
137+ model. constraint_names_rev[name] = Set {MOI.ConstraintIndex} ()
138+ end
139+ push! (model. constraint_names_rev[name], index)
140+ else
141+ # We're changing the name to the default, so we don't store it. Note
142+ # that if `model.constraint_names` doesn't have a key `index`, this does
143+ # nothing.
144+ delete! (model. constraint_names, index)
126145 end
127146 return
128147end
@@ -131,24 +150,32 @@ end
131150 Get constraint by name
132151=#
133152
134- function MOI. get (model :: LinQuadOptimizer , :: Type{<:MOI.ConstraintIndex} ,
135- name:: String )
153+ function MOI. get (
154+ model :: LinQuadOptimizer , :: Type{<:MOI.ConstraintIndex} , name:: String )
136155 if haskey (model. constraint_names_rev, name)
137- return model. constraint_names_rev[name]
138- else
139- return nothing
156+ if length (model. constraint_names_rev[name]) == 1
157+ return first (model. constraint_names_rev[name])
158+ elseif length (model. constraint_names_rev[name]) > 1
159+ error (" Cannot get constraint because the name $(name) is a duplicate." )
160+ end
140161 end
162+ return nothing
141163end
142164
143165# this covers the type-stable get(m, ConstraintIndex{F,S}, name)::CI{F,S} case
144- function MOI. get (model:: LinQuadOptimizer , :: Type{MOI.ConstraintIndex{F,S}} ,
166+ function MOI. get (model:: LinQuadOptimizer , :: Type{MOI.ConstraintIndex{F,S}} ,
145167 name:: String ) where F where S
146- if haskey (model. constraint_names_rev, name) &&
147- isa (model. constraint_names_rev[name], MOI. ConstraintIndex{F,S})
148- return model. constraint_names_rev[name]:: MOI.ConstraintIndex{F,S}
149- else
150- return nothing
168+ if haskey (model. constraint_names_rev, name)
169+ if length (model. constraint_names_rev[name]) == 1
170+ index = first (model. constraint_names_rev[name])
171+ if isa (index, MOI. ConstraintIndex{F, S})
172+ return index:: MOI.ConstraintIndex{F, S}
173+ end
174+ elseif length (model. constraint_names_rev[name]) > 1
175+ error (" Cannot get constraint because the name $(name) is a duplicate." )
176+ end
151177 end
178+ return nothing
152179end
153180
154181
0 commit comments