| 232 config: &InsertionConfig<F>, |
232 config: &InsertionConfig<F>, |
| 233 ) -> F |
233 ) -> F |
| 234 where |
234 where |
| 235 M: MinMaxMapping<Domain, F>; |
235 M: MinMaxMapping<Domain, F>; |
| 236 |
236 |
| 237 /// Convert bound on the regulariser to a bond on the Radon norm |
237 /// Convert bound on the regulariser to a bound on the Radon norm |
| 238 fn radon_norm_bound(&self, b: F) -> F; |
238 fn radon_norm_bound(&self, b: F) -> F; |
| |
239 |
| |
240 /// Returns true if $v$ is within the pointwise range of the subdifferential |
| |
241 fn subdiff_range(&self) -> Bounds<F>; |
| 239 } |
242 } |
| 240 |
243 |
| 241 #[replace_float_literals(F::cast_from(literal))] |
244 #[replace_float_literals(F::cast_from(literal))] |
| 242 impl<F: Float + ToNalgebraRealField, const N: usize> RegTerm<Loc<N, F>, F> |
245 impl<F: Float + ToNalgebraRealField, const N: usize> RegTerm<Loc<N, F>, F> |
| 243 for NonnegRadonRegTerm<F> |
246 for NonnegRadonRegTerm<F> |
| 384 *dest = F::to_nalgebra_mixed(β); |
387 *dest = F::to_nalgebra_mixed(β); |
| 385 } |
388 } |
| 386 // Solve finite-dimensional subproblem. |
389 // Solve finite-dimensional subproblem. |
| 387 let inner_tolerance = ε * config.inner.tolerance_mult; |
390 let inner_tolerance = ε * config.inner.tolerance_mult; |
| 388 let inner_it = config.inner.iterator_options.stop_target(inner_tolerance); |
391 let inner_it = config.inner.iterator_options.stop_target(inner_tolerance); |
| 389 stats.inner_iters += |
392 stats.inner_iters += l1squared_nonneg(&y, &g_na, τα, &mut x, &config.inner, inner_it); |
| 390 l1squared_nonneg(&y, &g_na, τα, 1.0, &mut x, &config.inner, inner_it); |
|
| 391 |
393 |
| 392 // Update masses of μ based on solution of finite-dimensional subproblem. |
394 // Update masses of μ based on solution of finite-dimensional subproblem. |
| 393 μ.set_masses_dvector(&x); |
395 μ.set_masses_dvector(&x); |
| 394 } |
396 } |
| 395 } |
397 } |
| 414 |
416 |
| 415 return { |
417 return { |
| 416 μ.both_matching(radon_μ).all(|(α, rα, x)| { |
418 μ.both_matching(radon_μ).all(|(α, rα, x)| { |
| 417 let v = -d.apply(x); // TODO: observe ad hoc negation here, after minus_τv |
419 let v = -d.apply(x); // TODO: observe ad hoc negation here, after minus_τv |
| 418 // switch to τv. |
420 // switch to τv. |
| 419 let (l1, u1) = match α.partial_cmp(&0.0).unwrap_or(Equal) { |
421 let (l1, u1) = match α.total_cmp(&0.0) { |
| 420 Greater => (τα, τα), |
422 Greater => (τα, τα), |
| 421 _ => (F::NEG_INFINITY, τα), |
423 _ => (F::NEG_INFINITY, τα), |
| 422 // Less should not happen; treated as Equal |
424 // Less should not happen; treated as Equal |
| 423 }; |
425 }; |
| 424 let (l2, u2) = match rα.partial_cmp(&0.0).unwrap_or(Equal) { |
426 let (l2, u2) = match rα.total_cmp(&0.0) { |
| 425 Greater => (slack, slack), |
427 Greater => (slack, slack), |
| 426 Equal => (-slack, slack), |
428 Equal => (-slack, slack), |
| 427 Less => (-slack, -slack), |
429 Less => (-slack, -slack), |
| 428 }; |
430 }; |
| 429 // TODO: both fail. |
431 // TODO: both fail. |
| 462 w(z) - w(y) |
464 w(z) - w(y) |
| 463 } |
465 } |
| 464 |
466 |
| 465 fn radon_norm_bound(&self, b: F) -> F { |
467 fn radon_norm_bound(&self, b: F) -> F { |
| 466 b / self.α() |
468 b / self.α() |
| |
469 } |
| |
470 |
| |
471 fn subdiff_range(&self) -> Bounds<F> { |
| |
472 Bounds(F::NEG_INFINITY, self.α()) |
| 467 } |
473 } |
| 468 } |
474 } |
| 469 |
475 |
| 470 #[replace_float_literals(F::cast_from(literal))] |
476 #[replace_float_literals(F::cast_from(literal))] |
| 471 impl<F: Float + ToNalgebraRealField, const N: usize> RegTerm<Loc<N, F>, F> for RadonRegTerm<F> { |
477 impl<F: Float + ToNalgebraRealField, const N: usize> RegTerm<Loc<N, F>, F> for RadonRegTerm<F> { |
| 642 let g_na = DVector::from_vec(g); |
648 let g_na = DVector::from_vec(g); |
| 643 // Solve finite-dimensional subproblem. |
649 // Solve finite-dimensional subproblem. |
| 644 let inner_tolerance = ε * config.inner.tolerance_mult; |
650 let inner_tolerance = ε * config.inner.tolerance_mult; |
| 645 let inner_it = config.inner.iterator_options.stop_target(inner_tolerance); |
651 let inner_it = config.inner.iterator_options.stop_target(inner_tolerance); |
| 646 stats.inner_iters += |
652 stats.inner_iters += |
| 647 l1squared_unconstrained(&y, &g_na, τα, 1.0, &mut x, &config.inner, inner_it); |
653 l1squared_unconstrained(&y, &g_na, τα, &mut x, &config.inner, inner_it); |
| 648 |
654 |
| 649 // Update masses of μ based on solution of finite-dimensional subproblem. |
655 // Update masses of μ based on solution of finite-dimensional subproblem. |
| 650 μ.set_masses_dvector(&x); |
656 μ.set_masses_dvector(&x); |
| 651 } |
657 } |
| 652 } |
658 } |