| 1 /*! |
1 /*! |
| 2 Some convex analysis basics |
2 Some convex analysis basics |
| 3 */ |
3 */ |
| 4 |
4 |
| |
5 use crate::error::DynResult; |
| 5 use crate::euclidean::Euclidean; |
6 use crate::euclidean::Euclidean; |
| 6 use crate::instance::{DecompositionMut, Instance, InstanceMut}; |
7 use crate::instance::{DecompositionMut, Instance, InstanceMut}; |
| 7 use crate::linops::{IdOp, Scaled}; |
8 use crate::linops::{IdOp, Scaled}; |
| 8 use crate::mapping::{Mapping, Space}; |
9 use crate::mapping::{DifferentiableImpl, LipschitzDifferentiableImpl, Mapping, Space}; |
| 9 use crate::norms::*; |
10 use crate::norms::*; |
| 10 use crate::operator_arithmetic::{Constant, Weighted}; |
11 use crate::operator_arithmetic::{Constant, Weighted}; |
| 11 use crate::types::*; |
12 use crate::types::*; |
| 12 use serde::{Deserialize, Serialize}; |
13 use serde::{Deserialize, Serialize}; |
| 13 use std::marker::PhantomData; |
14 use std::marker::PhantomData; |
| 340 pub fn new() -> Self { |
341 pub fn new() -> Self { |
| 341 Norm222(PhantomData) |
342 Norm222(PhantomData) |
| 342 } |
343 } |
| 343 } |
344 } |
| 344 |
345 |
| 345 impl<Domain: Euclidean<F>, F: Float> Mapping<Domain> for Norm222<F> { |
346 impl<X: Euclidean<F>, F: Float> Mapping<X> for Norm222<F> { |
| 346 type Codomain = F; |
347 type Codomain = F; |
| 347 |
348 |
| 348 /// Compute the value of `self` at `x`. |
349 /// Compute the value of `self` at `x`. |
| 349 fn apply<I: Instance<Domain>>(&self, x: I) -> Self::Codomain { |
350 fn apply<I: Instance<X>>(&self, x: I) -> Self::Codomain { |
| 350 x.eval(|z| z.norm2_squared() / F::TWO) |
351 x.eval(|z| z.norm2_squared() / F::TWO) |
| 351 } |
352 } |
| 352 } |
353 } |
| 353 |
354 |
| 354 impl<Domain: Euclidean<F>, F: Float> ConvexMapping<Domain, F> for Norm222<F> { |
355 impl<X: Euclidean<F>, F: Float> ConvexMapping<X, F> for Norm222<F> { |
| 355 fn factor_of_strong_convexity(&self) -> F { |
356 fn factor_of_strong_convexity(&self) -> F { |
| 356 F::ONE |
357 F::ONE |
| 357 } |
358 } |
| 358 } |
359 } |
| 359 |
360 |
| 360 impl<Domain: Euclidean<F>, F: Float> Conjugable<Domain, F> for Norm222<F> { |
361 impl<X: Euclidean<F>, F: Float> Conjugable<X, F> for Norm222<F> { |
| 361 type Conjugate<'a> |
362 type Conjugate<'a> |
| 362 = Self |
363 = Self |
| 363 where |
364 where |
| 364 Self: 'a; |
365 Self: 'a; |
| 365 |
366 |
| 379 fn preconjugate(&self) -> Self::Preconjugate<'_> { |
380 fn preconjugate(&self) -> Self::Preconjugate<'_> { |
| 380 Self::new() |
381 Self::new() |
| 381 } |
382 } |
| 382 } |
383 } |
| 383 |
384 |
| 384 impl<Domain, F> Prox<Domain> for Norm222<F> |
385 impl<X, F> Prox<X> for Norm222<F> |
| 385 where |
386 where |
| 386 F: Float, |
387 F: Float, |
| 387 Domain: Euclidean<F, Output = Domain>, |
388 X: Euclidean<F, Output = X>, |
| 388 { |
389 { |
| 389 type Prox<'a> |
390 type Prox<'a> |
| 390 = Scaled<F> |
391 = Scaled<F> |
| 391 where |
392 where |
| 392 Self: 'a; |
393 Self: 'a; |
| 393 |
394 |
| 394 fn prox_mapping(&self, τ: F) -> Self::Prox<'_> { |
395 fn prox_mapping(&self, τ: F) -> Self::Prox<'_> { |
| 395 Scaled(F::ONE / (F::ONE + τ)) |
396 Scaled(F::ONE / (F::ONE + τ)) |
| 396 } |
397 } |
| 397 } |
398 } |
| |
399 |
| |
400 impl<X, F> DifferentiableImpl<X> for Norm222<F> |
| |
401 where |
| |
402 F: Float, |
| |
403 X: Euclidean<F, Output = X>, |
| |
404 { |
| |
405 type Derivative = X; |
| |
406 |
| |
407 fn differential_impl<I: Instance<X>>(&self, x: I) -> X { |
| |
408 x.own() |
| |
409 } |
| |
410 } |
| |
411 |
| |
412 impl<X, F> LipschitzDifferentiableImpl<X, L2> for Norm222<F> |
| |
413 where |
| |
414 F: Float, |
| |
415 X: Euclidean<F, Output = X>, |
| |
416 { |
| |
417 type FloatType = F; |
| |
418 |
| |
419 fn diff_lipschitz_factor(&self, _: L2) -> DynResult<Self::FloatType> { |
| |
420 Ok(F::ONE) |
| |
421 } |
| |
422 } |