| 139 for<'b> H::Conjugate<'b>: Prox<Y>, |
139 for<'b> H::Conjugate<'b>: Prox<Y>, |
| 140 Plot: Plotter<P::ReturnMapping, S, DiscreteMeasure<U, F>>, |
140 Plot: Plotter<P::ReturnMapping, S, DiscreteMeasure<U, F>>, |
| 141 { |
141 { |
| 142 // Check parameters |
142 // Check parameters |
| 143 ensure!( |
143 ensure!( |
| 144 config.τ0 > 0.0 |
144 config.τ0 > 0.0 && config.σp0 > 0.0, |
| 145 && config.τ0 < 1.0 |
145 //&& config.τ0 < 1.0 && config.σp0 < 1.0 |
| 146 && config.σp0 > 0.0 |
|
| 147 && config.σp0 < 1.0 |
|
| 148 && config.σd0 >= 0.0 |
|
| 149 && config.σp0 * config.σd0 <= 1.0, |
|
| 150 "Invalid step length parameters" |
146 "Invalid step length parameters" |
| 151 ); |
147 ); |
| 152 |
148 |
| 153 // Initialise iterates |
149 // Initialise iterates |
| 154 let mut μ = μ0.unwrap_or_else(|| DiscreteMeasure::new()); |
150 let mut μ = μ0.unwrap_or_else(|| DiscreteMeasure::new()); |
| 158 let nKz = opKz.opnorm_bound(L2, L2)?; |
154 let nKz = opKz.opnorm_bound(L2, L2)?; |
| 159 let is_fb = nKz == 0.0; |
155 let is_fb = nKz == 0.0; |
| 160 let idOpZ = IdOp::new(); |
156 let idOpZ = IdOp::new(); |
| 161 let opKz_adj = opKz.adjoint(); |
157 let opKz_adj = opKz.adjoint(); |
| 162 let (l, l_z) = Pair(prox_penalty, &idOpZ).step_length_bound_pair(&f)?; |
158 let (l, l_z) = Pair(prox_penalty, &idOpZ).step_length_bound_pair(&f)?; |
| 163 // We need to satisfy |
159 |
| 164 // |
160 let (τ, σ_p, σ_d) = if is_fb { |
| 165 // τσ_dM(1-σ_p L_z)/(1 - τ L) + [σ_p L_z + σ_pσ_d‖K_z‖^2] < 1 |
161 (config.τ0 / l, config.σp0 / l_z, 0.0) |
| 166 // ^^^^^^^^^^^^^^^^^^^^^^^^^ |
162 } else { |
| 167 // with 1 > σ_p L_z and 1 > τ L. |
163 ensure!( |
| 168 // |
164 //config.τ0 < 1.0 && |
| 169 // To do so, we first solve σ_p and σ_d from standard PDPS step length condition |
165 config.σp0 < 1.0 && config.σd0 > 0.0 && config.σp0 * config.σd0 <= 1.0, |
| 170 // ^^^^^ < 1. then we solve τ from the rest. |
166 "Invalid step length parameters" |
| 171 // If opKZ is the zero operator, then we set σ_d = 0 for τ to be calculated correctly below. |
167 ); |
| 172 let σ_d = if is_fb { 0.0 } else { config.σd0 / nKz }; |
168 let σ_d = config.σd0 / nKz; |
| 173 let σ_p = config.σp0 / (l_z + config.σd0 * nKz); |
169 let σ_p = config.σp0 / (l_z + config.σd0 * nKz); |
| 174 // Observe that = 1 - ^^^^^^^^^^^^^^^^^^^^^ = 1 - σ_{p,0} |
170 let φ = 1.0 - config.σp0; |
| 175 // We get the condition τσ_d M (1-σ_p L_z) < (1-σ_{p,0})*(1-τ L) |
171 let a = 1.0 - σ_p * l_z; |
| 176 // ⟺ τ [ σ_d M (1-σ_p L_z) + (1-σ_{p,0}) L ] < (1-σ_{p,0}) |
172 let τ = config.τ0 * φ / (σ_d * bigM * a + φ * l); |
| 177 let φ = 1.0 - config.σp0; |
173 (τ, σ_p, σ_d) |
| 178 let a = 1.0 - σ_p * l_z; |
174 }; |
| 179 let τ = config.τ0 * φ / (σ_d * bigM * a + φ * l); |
175 |
| 180 // Acceleration is not currently supported |
176 // Acceleration is not currently supported |
| 181 // let γ = dataterm.factor_of_strong_convexity(); |
177 // let γ = dataterm.factor_of_strong_convexity(); |
| 182 let ω = 1.0; |
178 let ω = 1.0; |
| 183 |
179 |
| 184 // We multiply tolerance by τ for FB since our subproblems depending on tolerances are scaled |
180 // We multiply tolerance by τ for FB since our subproblems depending on tolerances are scaled |