@@ -30,158 +30,91 @@ REFERENCE
3030 theorem, matrix geometric means and semidefinite optimization" by Hamza
3131 Fawzi and James Saunderson (arXiv:1512.03401)
3232"""
33- mutable struct GeometricMeanHypoCone
34- A:: AbstractExpr
35- B:: AbstractExpr
33+ struct GeometricMeanHypoConeSquare <: MOI.AbstractVectorSet
3634 t:: Rational
37- size :: Tuple{ Int,Int}
35+ side_dimension :: Int
3836 fullhyp:: Bool
3937
40- function GeometricMeanHypoCone (
41- A:: AbstractExpr ,
42- B:: AbstractExpr ,
38+ function GeometricMeanHypoConeSquare (
4339 t:: Rational ,
40+ side_dimension:: Int ,
4441 fullhyp:: Bool = true ,
4542 )
46- if size (A) != size (B)
47- throw (DimensionMismatch (" A and B must be the same size" ))
48- end
49- n = size (A)[1 ]
50- if size (A) != (n, n)
51- throw (DimensionMismatch (" A and B must be square" ))
52- end
5343 if t < 0 || t > 1
5444 throw (DomainError (t, " t must be in the range [0, 1]" ))
5545 end
56- return new (A, B, t, (n, n), fullhyp)
57- end
58-
59- function GeometricMeanHypoCone (
60- A:: Value ,
61- B:: AbstractExpr ,
62- t:: Rational ,
63- fullhyp:: Bool = true ,
64- )
65- return GeometricMeanHypoCone (constant (A), B, t, fullhyp)
66- end
67-
68- function GeometricMeanHypoCone (
69- A:: AbstractExpr ,
70- B:: Value ,
71- t:: Rational ,
72- fullhyp:: Bool = true ,
73- )
74- return GeometricMeanHypoCone (A, constant (B), t, fullhyp)
46+ return new (t, side_dimension, fullhyp)
7547 end
48+ end
7649
77- function GeometricMeanHypoCone (
78- A:: Value ,
79- B:: Value ,
80- t:: Rational ,
81- fullhyp:: Bool = true ,
82- )
83- return GeometricMeanHypoCone (constant (A), constant (B), t, fullhyp)
84- end
50+ MOI. dimension (set:: GeometricMeanHypoConeSquare ) = 3 * set. side_dimension^ 2
8551
86- function GeometricMeanHypoCone (
87- A:: Union{AbstractExpr,Value} ,
88- B:: Union{AbstractExpr,Value} ,
89- t:: Integer ,
90- fullhyp:: Bool = true ,
91- )
92- return GeometricMeanHypoCone (A, B, t // 1 , fullhyp)
93- end
52+ function head (io:: IO , :: GeometricMeanHypoConeSquare )
53+ return print (io, " GeometricMeanHypoConeSquare" )
9454end
9555
96- mutable struct GeometricMeanHypoConeConstraint <: Constraint
97- T:: AbstractExpr
98- cone:: GeometricMeanHypoCone
99-
100- function GeometricMeanHypoConeConstraint (
101- T:: AbstractExpr ,
102- cone:: GeometricMeanHypoCone ,
103- )
104- if size (T) != cone. size
105- throw (DimensionMismatch (" T must be size $(cone. size) " ))
56+ function GenericConstraint (func:: Tuple , set:: GeometricMeanHypoConeSquare )
57+ for f in func
58+ n = LinearAlgebra. checksquare (f)
59+ if n != set. side_dimension
60+ throw (
61+ DimensionMismatch (
62+ " Matrix of side dimension `$n ` does not match set of side dimension `$(set. side_dimension) `" ,
63+ ),
64+ )
10665 end
107- return new (T, cone)
108- end
109-
110- function GeometricMeanHypoConeConstraint (
111- T:: Value ,
112- cone:: GeometricMeanHypoCone ,
113- )
114- return GeometricMeanHypoConeConstraint (constant (T), cone)
11566 end
67+ return GenericConstraint (vcat (vec .(func)... ), set)
11668end
11769
118- function iscomplex (c:: GeometricMeanHypoConeConstraint )
119- return iscomplex (c. T) || iscomplex (c. cone)
120- end
121-
122- iscomplex (c:: GeometricMeanHypoCone ) = iscomplex (c. A) || iscomplex (c. B)
123-
124- function head (io:: IO , :: GeometricMeanHypoConeConstraint )
125- return print (io, " ∈(GeometricMeanHypoCone)" )
126- end
127-
128- function Base. in (T, cone:: GeometricMeanHypoCone )
129- return GeometricMeanHypoConeConstraint (T, cone)
130- end
131-
132- function AbstractTrees. children (constraint:: GeometricMeanHypoConeConstraint )
133- return (
134- constraint. T,
135- constraint. cone. A,
136- constraint. cone. B,
137- constraint. cone. t,
138- )
70+ function _get_matrices (c:: GenericConstraint{GeometricMeanHypoConeSquare} )
71+ n = c. set. side_dimension
72+ d = n^ 2
73+ T = reshape (c. child[1 : d], n, n)
74+ A = reshape (c. child[d.+ (1 : d)], n, n)
75+ B = reshape (c. child[2 d.+ (1 : d)], n, n)
76+ return T, A, B
13977end
14078
14179# For t ∈ [0,1] the t-weighted matrix geometric mean is matrix concave (arxiv:1512.03401).
14280# So if A and B are convex sets, then T ⪯ A #_t B will be a convex set.
143- function vexity (constraint:: GeometricMeanHypoConeConstraint )
144- A = vexity (constraint. cone. A)
145- B = vexity (constraint. cone. B)
146- T = vexity (constraint. T)
147-
148- # NOTE: can't say A == NotDcp() because the NotDcp constructor prints a
149- # warning message.
150- if typeof (A) == ConvexVexity || typeof (A) == NotDcp
151- return NotDcp ()
152- elseif typeof (B) == ConvexVexity || typeof (B) == NotDcp
153- return NotDcp ()
154- end
155- vex = - ConcaveVexity () + T
156- if vex == ConcaveVexity ()
81+ function vexity (constraint:: GenericConstraint{GeometricMeanHypoConeSquare} )
82+ T, A, B = _get_matrices (constraint)
83+ if vexity (A) in (ConvexVexity (), NotDcp ()) ||
84+ vexity (B) in (ConvexVexity (), NotDcp ())
15785 return NotDcp ()
15886 end
159- return vex
87+ return - ConcaveVexity () + vexity (T)
16088end
16189
16290function _add_constraint! (
16391 context:: Context ,
164- constraint:: GeometricMeanHypoConeConstraint ,
92+ constraint:: GenericConstraint{GeometricMeanHypoConeSquare} ,
16593)
166- A = constraint. cone. A
167- B = constraint. cone. B
168- t = constraint. cone. t
169- T = constraint. T
170- fullhyp = constraint. cone. fullhyp
94+ T, A, B = _get_matrices (constraint)
95+ t = constraint. set. t
96+ fullhyp = constraint. set. fullhyp
17197
17298 is_complex =
17399 sign (A) == ComplexSign () ||
174100 sign (B) == ComplexSign () ||
175101 sign (T) == ComplexSign ()
102+ n = size (A, 1 )
176103 if is_complex
177- make_temporary = () -> HermitianSemidefinite (size (A)[ 1 ] )
104+ make_temporary = () -> HermitianSemidefinite (n )
178105 else
179- make_temporary = () -> Semidefinite (size (A)[ 1 ] )
106+ make_temporary = () -> Semidefinite (n )
180107 end
181108
182109 if fullhyp && t != 0 && t != 1
183110 W = make_temporary ()
184- add_constraint! (context, W in GeometricMeanHypoCone (A, B, t, false ))
111+ add_constraint! (
112+ context,
113+ GenericConstraint (
114+ (W, A, B),
115+ GeometricMeanHypoConeSquare (t, n, false ),
116+ ),
117+ )
185118 add_constraint! (context, W ⪰ T)
186119 else
187120 p = t. num
@@ -206,13 +139,19 @@ function _add_constraint!(
206139 if t < 1 / 2
207140 add_constraint! (
208141 context,
209- Z in GeometricMeanHypoCone (A, B, 2 * t, false ),
142+ GenericConstraint (
143+ (Z, A, B),
144+ GeometricMeanHypoConeSquare (2 * t, n, false ),
145+ ),
210146 )
211147 add_constraint! (context, [A T; T' Z] ⪰ 0 )
212148 else
213149 add_constraint! (
214150 context,
215- Z in GeometricMeanHypoCone (A, B, 2 * t - 1 , false ),
151+ GenericConstraint (
152+ (Z, A, B),
153+ GeometricMeanHypoConeSquare (2 * t - 1 , n, false ),
154+ ),
216155 )
217156 add_constraint! (context, [B T; T' Z] ⪰ 0 )
218157 end
@@ -221,7 +160,10 @@ function _add_constraint!(
221160 Z = make_temporary ()
222161 add_constraint! (
223162 context,
224- Z in GeometricMeanHypoCone (A, T, (2 * p - q) // p, false ),
163+ GenericConstraint (
164+ (Z, A, T),
165+ GeometricMeanHypoConeSquare ((2 * p - q) // p, n, false ),
166+ ),
225167 )
226168 add_constraint! (context, [Z T; T B] ⪰ 0 )
227169 elseif t < 1 / 2
@@ -231,18 +173,28 @@ function _add_constraint!(
231173 l = floor (Int, log2 (q))
232174 add_constraint! (
233175 context,
234- X in GeometricMeanHypoCone (A, B, p // (2 ^ l), false ),
176+ GenericConstraint (
177+ (X, A, B),
178+ GeometricMeanHypoConeSquare (p // (2 ^ l), n, false ),
179+ ),
235180 )
236181 add_constraint! (
237182 context,
238- T in GeometricMeanHypoCone (A, X, (2 ^ l) // q, false ),
183+ GenericConstraint (
184+ (T, A, X),
185+ GeometricMeanHypoConeSquare ((2 ^ l) // q, n, false ),
186+ ),
239187 )
240188 else
241189 # println("geom_mean_hypocone p=$p q=$q else")
242190 add_constraint! (
243191 context,
244- T in GeometricMeanHypoCone (B, A, 1 - t, false ),
192+ GenericConstraint (
193+ (T, B, A),
194+ GeometricMeanHypoConeSquare (1 - t, n, false ),
195+ ),
245196 )
246197 end
247198 end
199+ return
248200end
0 commit comments