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

          Line data    Source code
       1             : /* 
       2             :  * File:   DistanceToBox.cpp
       3             :  * Author: Pantelis Sopasakis
       4             :  * 
       5             :  * Created on October 27, 2015, 6: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 "DistanceToBox.h"
      22             : #include <cmath>
      23             : 
      24             : void checkBounds(const Matrix* lb, const Matrix* ub);
      25             : 
      26           4 : void checkBounds(const Matrix* lb, const Matrix* ub) {
      27             :     //LCOV_EXCL_START
      28             :     if (lb == NULL || ub == NULL) {
      29             :         throw std::invalid_argument("LB and UB cannot be NULL");
      30             :     }
      31             :     if (lb->isEmpty()) {
      32             :         throw std::invalid_argument("Lower bound is not allowed to be empty");
      33             :     }
      34             :     if (ub->isEmpty()) {
      35             :         throw std::invalid_argument("Upper bound is not allowed to be empty");
      36             :     }
      37             :     if (!lb->isColumnVector() || !ub->isColumnVector()) {
      38             :         throw std::invalid_argument("UB and LB must be column vectors");
      39             :     }
      40             :     if (ub->getNcols() != lb->getNcols() || ub->getNrows() != lb->getNrows()) {
      41             :         throw std::invalid_argument("UB and LB and must be vectors of the same size");
      42             :     }
      43             :     if (lb->getType() != Matrix::MATRIX_DENSE || ub->getType() != Matrix::MATRIX_DENSE) {
      44             :         throw std::invalid_argument("UB and LB must be dense vectors - other types are not supported");
      45             :     }
      46             :     //LCOV_EXCL_STOP
      47           4 : }
      48             : 
      49             : /*
      50             :  * Constructors
      51             :  */
      52             : 
      53           3 : DistanceToBox::DistanceToBox(Matrix* lb, Matrix* ub, Matrix* weights) :
      54           3 : Function(), m_weights(weights), m_lb(lb), m_ub(ub) {
      55             :     //LCOV_EXCL_START
      56             :     if (!weights->isColumnVector() || weights->isEmpty() || weights->getNrows() != lb->getNrows()) {
      57             :         throw std::invalid_argument("Invalid size of weights");
      58             :     }
      59             :     //LCOV_EXCL_STOP
      60           3 :     checkBounds(lb, ub);
      61           3 :     m_is_weights_equal = false;
      62           3 :     m_is_bounds_uniform = false;
      63           3 :     m_weight = 0.0;
      64           3 :     m_uniform_lb = 0.0;
      65           3 :     m_uniform_ub = 0.0;
      66           3 : }
      67             : 
      68           1 : DistanceToBox::DistanceToBox(Matrix* lb, Matrix* ub, double weight) :
      69           1 : Function(), m_weight(weight), m_lb(lb), m_ub(ub) {
      70           1 :     m_weights = NULL;
      71           1 :     checkBounds(lb, ub);
      72           1 :     m_is_weights_equal = true;
      73           1 :     m_is_bounds_uniform = false;
      74           1 :     m_uniform_lb = 0.0;
      75           1 :     m_uniform_ub = 0.0;
      76           1 : }
      77             : 
      78           1 : DistanceToBox::DistanceToBox(double uniform_lb, double uniform_ub, double weight) :
      79           1 : Function(), m_weight(weight), m_uniform_lb(uniform_lb), m_uniform_ub(uniform_ub) {
      80           1 :     m_is_weights_equal = true;
      81           1 :     m_is_bounds_uniform = true;
      82           1 :     m_lb = NULL;
      83           1 :     m_ub = NULL;
      84           1 :     m_weights = NULL;
      85           1 : }
      86             : 
      87           6 : DistanceToBox::~DistanceToBox() {
      88             :     // nothing to delete
      89           6 : }
      90             : 
      91         104 : int DistanceToBox::compute_dx(const Matrix& x, const size_t n, Matrix& dx) const {
      92        1112 :     for (size_t i = 0; i < n; i++) {
      93        1008 :         if (x[i] < (m_is_bounds_uniform ? m_uniform_lb : m_lb->get(i))) {
      94           4 :             dx[i] = x[i] - (m_is_bounds_uniform ? m_uniform_lb : m_lb->get(i));
      95        1004 :         } else if (x[i] > (m_is_bounds_uniform ? m_uniform_ub : m_ub->get(i))) {
      96           4 :             dx[i] = x[i] - (m_is_bounds_uniform ? m_uniform_ub : m_ub->get(i));
      97             :         }
      98             :     }
      99         104 :     return ForBESUtils::STATUS_OK;
     100             : }
     101             : 
     102           3 : int DistanceToBox::compute_grad(Matrix& dx, const size_t n, Matrix& grad) const {
     103           3 :     if (!m_is_weights_equal) {
     104           6 :         for (size_t i = 0; i < n; i++) {
     105           4 :             grad.set(i, 0, m_weights->get(i, 0) * dx.get(i, 0));
     106             :         }
     107             :     } else {
     108           1 :         grad = m_weight * dx;
     109             :     }
     110           3 :     return ForBESUtils::STATUS_OK;
     111             : }
     112             : 
     113         104 : int DistanceToBox::compute_fun(const Matrix& dx, const size_t n, double& f) const {
     114         104 :     f = 0.0;
     115        1112 :     for (size_t i = 0; i < n; i++) {
     116        1008 :         f += (m_is_weights_equal ? m_weight : m_weights->get(i, 0)) * std::pow(dx.get(i, 0), 2);
     117             :     }
     118         104 :     f /= 2.0;
     119         104 :     return ForBESUtils::STATUS_OK;
     120             : }
     121             : 
     122           3 : int DistanceToBox::call(Matrix& x, double& f, Matrix& grad) {
     123           3 :     const size_t n = x.getNrows(); // input dimension
     124           3 :     Matrix dx(n, 1); // dx : n-by-1 (all zeros)
     125           3 :     compute_dx(x, n, dx); // compute d(x)
     126           3 :     compute_grad(dx, n, grad); // compute the gradient
     127           3 :     compute_fun(dx, n, f); // compute f(x)
     128           3 :     return ForBESUtils::STATUS_OK; // OK
     129             : }
     130             : 
     131         101 : int DistanceToBox::call(Matrix& x, double& f) {
     132         101 :     const size_t n = x.getNrows(); // input dimension
     133         101 :     Matrix dx(n, 1); // dx : n-by-1 (all zeros)
     134         101 :     compute_dx(x, n, dx); // compute d(x)
     135         101 :     compute_fun(dx, n, f); // compute f(x)
     136         101 :     return ForBESUtils::STATUS_OK; // OK
     137             : }
     138             : 
     139           4 : FunctionOntologicalClass DistanceToBox::category() {
     140           4 :     FunctionOntologicalClass distToBox("DistanceToBox");
     141           4 :     distToBox.set_defines_f(true);
     142           4 :     distToBox.set_defines_grad(true);
     143           4 :     distToBox.add_superclass(FunctionOntologyRegistry::distance());
     144           4 :     return distToBox;
     145           3 : }
     146             : 

Generated by: LCOV version 1.10