4 #include "sopt/config.h"
17 return (x - x.mean()).matrix().stableNorm() / std::sqrt(x.size());
26 template <
typename SCALAR>
27 typename std::enable_if<std::is_arithmetic<SCALAR>::value or is_complex<SCALAR>::value,
30 auto const normalized = std::abs(x);
31 return normalized < threshhold ? SCALAR(0) : (x * (SCALAR(1) - threshhold / normalized));
36 template <
typename SCALAR>
39 SCALAR
operator()(
const SCALAR &value)
const {
return std::max(value, SCALAR(0)); }
42 template <
typename SCALAR>
45 SCALAR
operator()(SCALAR
const &value)
const {
return std::max(value, SCALAR(0)); }
46 std::complex<SCALAR>
operator()(std::complex<SCALAR>
const &value)
const {
52 template <
typename SCALAR>
53 using SoftThreshhold = decltype(std::bind(soft_threshhold<SCALAR>, std::placeholders::_1,
59 Eigen::CwiseUnaryOp<const details::ProjectPositiveQuadrant<typename T::Scalar>,
const T>
62 using UnaryOp = Eigen::CwiseUnaryOp<const Projector, const T>;
63 return UnaryOp(input.derived(), Projector());
68 Eigen::CwiseUnaryOp<const details::SoftThreshhold<typename T::Scalar>,
const T>
soft_threshhold(
69 Eigen::DenseBase<T>
const &input,
73 return Eigen::CwiseUnaryOp<const details::SoftThreshhold<typename T::Scalar>,
const T>{
74 input.derived(), std::bind(soft_threshhold<Scalar>, std::placeholders::_1, Real(threshhold))};
81 template <
typename T0,
typename T1>
82 typename std::enable_if<std::is_arithmetic<typename T0::Scalar>::value and
83 std::is_arithmetic<typename T1::Scalar>::value,
86 const T0,
const T1>>::type
87 soft_threshhold(Eigen::DenseBase<T0>
const &input, Eigen::DenseBase<T1>
const &threshhold) {
88 if (input.size() != threshhold.size())
89 SOPT_THROW(
"Threshhold and input should have the same size");
90 return {input.derived(), threshhold.derived(), soft_threshhold<typename T0::Scalar>};
97 template <
typename T0,
typename T1>
98 typename std::enable_if<
99 is_complex<typename T0::Scalar>::value and std::is_arithmetic<typename T1::Scalar>::value,
100 Eigen::CwiseBinaryOp<
102 decltype(std::declval<const T1>().template cast<typename T0::Scalar>())>>::type
103 soft_threshhold(Eigen::DenseBase<T0>
const &input, Eigen::DenseBase<T1>
const &threshhold) {
104 if (input.size() != threshhold.size())
105 SOPT_THROW(
"Threshhold and input should have the same size: ")
106 << threshhold.size() <<
" vs " << input.size();
108 auto const func = [](Complex
const &x, Complex
const &t) -> Complex {
111 return {input.derived(), threshhold.derived().template cast<Complex>(), func};
115 template <
typename T0,
typename T1>
117 Eigen::ArrayBase<T1>
const &weights) {
118 if (weights.size() == 1)
return input.cwiseAbs().sum() * std::abs(weights(0));
119 return (input * weights).cwiseAbs().sum();
122 template <
typename T0,
typename T1>
124 Eigen::MatrixBase<T1>
const &weight) {
125 return l1_norm(input.array(), weight.array());
128 template <
typename T0>
130 return input.cwiseAbs().sum();
133 template <
typename T0>
139 template <
typename T0,
typename T1>
141 Eigen::ArrayBase<T1>
const &weights) {
142 if (weights.size() == 1)
return input.matrix().stableNorm() * std::abs(weights(0));
143 return (input * weights).matrix().stableNorm();
146 template <
typename T0,
typename T1>
148 Eigen::MatrixBase<T1>
const &weights) {
149 return l2_norm(input.derived().array(), weights.derived().array());
152 template <
typename T0>
154 typename T0::PlainObject w(1);
159 template <
typename T0>
161 typename T0::PlainObject w(1);
163 return l2_norm(input.derived().array(), w.array());
167 template <
typename T0,
typename T1>
169 Eigen::ArrayBase<T1>
const &weights) {
170 const auto size = input.size() / 2;
171 if (weights.size() == 1)
172 return (input.segment(0, size).square() + input.segment(size, size).square())
177 std::abs(weights(0));
179 ((input.segment(0, size).square() + input.segment(size, size).square()).cwiseAbs().sqrt() *
185 template <
typename T0,
typename T1>
187 Eigen::MatrixBase<T1>
const &weights) {
188 return tv_norm(input.derived().array(), weights.derived().array());
191 template <
typename T0>
193 typename T0::PlainObject w(1);
198 template <
typename T0>
200 typename T0::PlainObject w(1);
202 return tv_norm(input.derived().array(), w.array());
std::complex< SCALAR > operator()(std::complex< SCALAR > const &value) const
SCALAR operator()(SCALAR const &value) const
Expression to create projection onto positive orthant.
SCALAR operator()(const SCALAR &value) const
Computes inner-most element type.
t_int gcd(t_int a, t_int b)
Greatest common divisor.
decltype(std::bind(soft_threshhold< SCALAR >, std::placeholders::_1, typename real_type< SCALAR >::type(1))) SoftThreshhold
Helper template type alias to instantiate soft_threshhold that takes an Eigen object.
real_type< typename T0::Scalar >::type tv_norm(Eigen::ArrayBase< T0 > const &input, Eigen::ArrayBase< T1 > const &weights)
Computes weighted TV norm.
real_type< typename T::Scalar >::type standard_deviation(Eigen::ArrayBase< T > const &x)
Computes the standard deviation of a vector.
Eigen::CwiseUnaryOp< const details::ProjectPositiveQuadrant< typename T::Scalar >, const T > positive_quadrant(Eigen::DenseBase< T > const &input)
Expression to create projection onto positive quadrant.
int t_int
Root of the type hierarchy for signed integers.
std::enable_if< std::is_arithmetic< SCALAR >::value or is_complex< SCALAR >::value, SCALAR >::type soft_threshhold(SCALAR const &x, typename real_type< SCALAR >::type const &threshhold)
abs(x) < threshhold ? 0: x - sgn(x) * threshhold
real_type< typename T0::Scalar >::type l1_norm(Eigen::ArrayBase< T0 > const &input, Eigen::ArrayBase< T1 > const &weights)
Computes weighted L1 norm.
real_type< typename T0::Scalar >::type l2_norm(Eigen::ArrayBase< T0 > const &input, Eigen::ArrayBase< T1 > const &weights)
Computes weighted L2 norm.