LCOV - code coverage report
Current view: top level - source - SumOfNorm2.cpp (source / functions) Hit Total Coverage
Test: LibForBES Unit Tests Lines: 81 82 98.8 %
Date: 2016-04-18 Functions: 11 11 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* 
       2             :  * File:   SumOfNorm2.cpp
       3             :  * Author: Pantelis Sopasakis
       4             :  * 
       5             :  * Created on November 6, 2015, 1:23 AM
       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 <algorithm>
      22             : #include <complex>
      23             : 
      24             : #include "SumOfNorm2.h"
      25             : #include "MatrixFactory.h"
      26             : #include "Norm2.h"
      27             : 
      28           2 : SumOfNorm2::SumOfNorm2(size_t k) : Norm(), m_partition_length(k) {
      29           2 :     m_mu = 1.0;
      30           2 :     m_norm2 = new Norm2();
      31           2 : }
      32             : 
      33           5 : SumOfNorm2::SumOfNorm2(double mu, size_t k) : Norm(), m_mu(mu), m_partition_length(k) {
      34           5 :     m_norm2 = new Norm2();
      35           5 : }
      36             : 
      37          21 : SumOfNorm2::~SumOfNorm2() {
      38           7 :     if (m_norm2 != NULL) {
      39           7 :         delete m_norm2;
      40           7 :         m_norm2 = NULL;
      41             :     }
      42          14 : }
      43             : 
      44           7 : int SumOfNorm2::call(Matrix& x, double& f) {
      45           7 :     f = 0.0;
      46           7 :     const size_t n = x.getNrows();
      47           7 :     if (n % m_partition_length != 0) {
      48           1 :         throw std::invalid_argument("Given vector cannot be partitioned");
      49             :     }
      50             :     /* number of chunks */
      51           6 :     const size_t n_chunks = n / m_partition_length;
      52           6 :     int status = ForBESUtils::STATUS_OK;
      53          69 :     for (size_t j = 0; j < n_chunks && status == ForBESUtils::STATUS_OK; j++) {
      54             :         double f_temp;
      55          63 :         Matrix x_part = MatrixFactory::ShallowVector(x, m_partition_length, j * m_partition_length);
      56          63 :         status = m_norm2->call(x_part, f_temp);
      57          63 :         f += f_temp;
      58          63 :     }
      59           6 :     f *= m_mu;
      60           6 :     return status;
      61             : }
      62             : 
      63           2 : int SumOfNorm2::callProx(Matrix& v, double gamma, Matrix& prox) {
      64           2 :     const size_t n = v.getNrows();
      65           2 :     if (n % m_partition_length != 0) {
      66           1 :         throw std::invalid_argument("Given vector cannot be partitioned");
      67             :     }
      68             : 
      69           1 :     const size_t n_chunks = n / m_partition_length;
      70           1 :     Matrix v_part = MatrixFactory::ShallowVector();
      71             : 
      72           1 :     int status = ForBESUtils::STATUS_OK;
      73           5 :     for (size_t j = 0; j < n_chunks && status == ForBESUtils::STATUS_OK; j++) {
      74             :         double norm_temp;
      75           4 :         v_part = MatrixFactory::ShallowVector(v, m_partition_length, j * m_partition_length);
      76           4 :         Matrix prox_part = MatrixFactory::ShallowVector(prox, m_partition_length, j * m_partition_length);
      77           4 :         status = m_norm2->call(v_part, norm_temp);
      78           4 :         double factor = 1 - (gamma * m_mu / norm_temp);
      79          16 :         for (size_t i = 0; i < m_partition_length; i++) {
      80          12 :             prox_part[i] = factor * v_part[i];
      81             :         }
      82           4 :     }
      83           1 :     return status;
      84             : }
      85             : 
      86           2 : int SumOfNorm2::callProx(Matrix& v, double gamma, Matrix& prox, double& f_at_prox) {
      87           2 :     const size_t n = v.getNrows();
      88           2 :     if (n % m_partition_length != 0) {
      89           0 :         throw std::invalid_argument("Given vector cannot be partitioned");
      90             :     }
      91             : 
      92           2 :     f_at_prox = 0.0;
      93           2 :     const size_t n_chunks = n / m_partition_length;
      94           2 :     Matrix v_part = MatrixFactory::ShallowVector();
      95             : 
      96           2 :     int status = ForBESUtils::STATUS_OK;
      97          55 :     for (size_t j = 0; j < n_chunks && status == ForBESUtils::STATUS_OK; j++) {
      98             :         double norm_temp;
      99          53 :         v_part = MatrixFactory::ShallowVector(v, m_partition_length, j * m_partition_length);
     100          53 :         Matrix prox_part = MatrixFactory::ShallowVector(prox, m_partition_length, j * m_partition_length);
     101          53 :         status = m_norm2->call(v_part, norm_temp);
     102          53 :         double factor = std::max<double>(0.0, 1.0 - (gamma * m_mu / norm_temp));
     103         112 :         for (size_t i = 0; i < m_partition_length; i++) {
     104          59 :             prox_part[i] = factor * v_part[i];
     105             :         }
     106          53 :         f_at_prox += std::abs(factor * norm_temp);
     107          53 :     }
     108           2 :     f_at_prox *= m_mu;
     109           2 :     return status;
     110             : }
     111             : 
     112           5 : FunctionOntologicalClass SumOfNorm2::category() {
     113           5 :     FunctionOntologicalClass meta("SumOfNorm2");
     114           5 :     meta.set_defines_f(true);
     115           5 :     meta.set_defines_conjugate(true);
     116           5 :     meta.set_defines_prox(true);
     117           5 :     meta.add_superclass(FunctionOntologyRegistry::norm());
     118           5 :     return meta;
     119             : }
     120             : 
     121           3 : int SumOfNorm2::dualNorm(Matrix& x, double& norm) {
     122             :     /* this implementation is very much similar to #call */
     123           3 :     norm = 0.0;
     124           3 :     const size_t n = x.getNrows();
     125           3 :     if (n % m_partition_length != 0) {
     126           1 :         throw std::invalid_argument("Given vector cannot be partitioned");
     127             :     }
     128             :     /* number of chunks */
     129           2 :     const size_t n_chunks = n / m_partition_length;
     130          56 :     for (size_t j = 0; j < n_chunks; j++) {
     131             :         double f_temp;
     132          54 :         Matrix x_part = MatrixFactory::ShallowVector(x, m_partition_length, j * m_partition_length);
     133          54 :         m_norm2->call(x_part, f_temp);
     134          54 :         norm = std::max(norm, f_temp);
     135          54 :     }
     136           2 :     norm /= m_mu;
     137           2 :     return ForBESUtils::STATUS_OK;
     138           3 : }
     139             : 
     140             : 

Generated by: LCOV version 1.10