Line data Source code
1 : /*
2 : * File: Norm1.cpp
3 : * Author: Pantelis Sopasakis
4 : *
5 : * Created on October 30, 2015, 4:05 PM
6 : *
7 : * ForBES is free software: you can redistribute it and/or modify
8 : * it under the terms of the GNU Lesser General Public License as published by
9 : * the Free Software Foundation, either version 3 of the License, or
10 : * (at your option) any later version.
11 : *
12 : * ForBES is distributed in the hope that it will be useful,
13 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : * GNU Lesser General Public License for more details.
16 : *
17 : * You should have received a copy of the GNU Lesser General Public License
18 : * along with ForBES. If not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include "Norm1.h"
22 : #include <cmath>
23 :
24 4 : Norm1::Norm1() : Norm() {
25 4 : m_mu = 1.0;
26 4 : }
27 :
28 14 : Norm1::Norm1(double mu) : Norm(), m_mu(mu) {
29 14 : if (mu <= 0) {
30 0 : throw std::invalid_argument("Parameter mu must be positive");
31 : }
32 14 : }
33 :
34 29 : Norm1::~Norm1() {
35 29 : }
36 :
37 4 : int Norm1::call(Matrix& x, double& f) {
38 : //LCOV_EXCL_START
39 : if (!x.isColumnVector()) {
40 : throw std::invalid_argument("x must be a column-vector");
41 : }
42 : //LCOV_EXCL_STOP
43 4 : f = 0.0;
44 69 : for (size_t i = 0; i < x.getNrows(); i++) {
45 65 : f += std::abs(x[i]);
46 : }
47 4 : f *= m_mu;
48 4 : return ForBESUtils::STATUS_OK;
49 : }
50 :
51 1 : int Norm1::callProx(Matrix& x, double gamma, Matrix& prox) {
52 : //LCOV_EXCL_START
53 : if (!x.isColumnVector()) {
54 : throw std::invalid_argument("x must be a column-vector");
55 : }
56 : //LCOV_EXCL_STOP
57 1 : double gm = gamma * m_mu;
58 11 : for (size_t i = 0; i < x.getNrows(); i++) {
59 : double xi;
60 10 : xi = x[i];
61 10 : if (xi >= gm) {
62 4 : prox[i] = xi - gm;
63 6 : } else if (xi <= -gm) {
64 2 : prox[i] = xi + gm;
65 : }
66 : }
67 1 : return ForBESUtils::STATUS_OK;
68 : }
69 :
70 57736 : int Norm1::callProx(Matrix& x, double gamma, Matrix& prox, double& f_at_prox) {
71 : //LCOV_EXCL_START
72 : if (!x.isColumnVector()) {
73 : throw std::invalid_argument("x must be a column-vector");
74 : }
75 : //LCOV_EXCL_STOP
76 57736 : double gm = gamma * m_mu;
77 57736 : f_at_prox = 0.0;
78 346485 : for (size_t i = 0; i < x.getNrows(); i++) {
79 : double pi;
80 288749 : double xi = x[i];
81 288749 : if (xi >= gm) {
82 78471 : pi = xi - gm;
83 210278 : } else if (xi <= -gm) {
84 42150 : pi = xi + gm;
85 : } else {
86 168128 : pi = 0.0;
87 : }
88 288749 : prox[i] = pi;
89 288749 : f_at_prox += std::abs(pi);
90 : }
91 57736 : f_at_prox *= m_mu;
92 57736 : return ForBESUtils::STATUS_OK;
93 : }
94 :
95 46 : int Norm1::dualNorm(Matrix& x, double& norm) {
96 : //LCOV_EXCL_START
97 : if (!x.isColumnVector()) {
98 : throw std::invalid_argument("x must be a column-vector");
99 : }
100 : //LCOV_EXCL_STOP
101 46 : norm = std::abs(x[0]);
102 182 : for (size_t i = 1; i < x.getNrows(); i++) {
103 136 : double absi = std::abs(x[i]);
104 136 : if (absi > norm) {
105 49 : norm = absi;
106 : }
107 : }
108 46 : norm /= m_mu;
109 46 : return ForBESUtils::STATUS_OK;
110 : }
111 :
112 3 : FunctionOntologicalClass Norm1::category() {
113 3 : return FunctionOntologyRegistry::norm();
114 24 : }
115 :
116 :
117 :
118 :
119 :
|