Line data Source code
1 : /*
2 : * File: SeparableSum.cpp
3 : * Author: Pantelis Sopasakis
4 : *
5 : * Created on October 30, 2015, 7:22 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 "SeparableSum.h"
22 : #include <iostream>
23 :
24 : /**
25 : * Constructs the sub-vector \c c_x which is defined by a given set of indexes.
26 : *
27 : * @param c_idx set of indexes
28 : * @param x original vector x
29 : * @param c_x sub-vector
30 : */
31 : void prepare_cx(std::vector<size_t> * c_idx, const Matrix& x, Matrix * c_x);
32 :
33 8 : SeparableSum::~SeparableSum() {
34 8 : }
35 :
36 4 : SeparableSum::SeparableSum(std::map<Function*, std::vector<size_t>*> fun_idx_map) :
37 4 : Function(), m_fun_idx_map(fun_idx_map) {
38 4 : }
39 :
40 1096 : void prepare_cx(std::vector<size_t> * c_idx, const Matrix& x, Matrix * c_x) {
41 1096 : size_t k = 0;
42 8883 : for (std::vector<size_t>::iterator idx_iterator = c_idx->begin();
43 5922 : idx_iterator != c_idx->end();
44 : ++idx_iterator) {
45 1865 : c_x -> set(k, 0, x.get(*idx_iterator, 0));
46 1865 : k++;
47 : }
48 1096 : }
49 :
50 1 : int SeparableSum::call(Matrix& x, double& f) {
51 : //LCOV_EXCL_START
52 : if (!x.isColumnVector()) throw std::invalid_argument("x must be a column-vector");
53 : //LCOV_EXCL_STOP
54 :
55 : /* sub-matrix */
56 1 : Matrix *c_x = NULL;
57 :
58 : /* initialization of result f(x) */
59 1 : f = 0.0;
60 :
61 :
62 : /* Invoke all functions */
63 9 : for (std::map<Function*, std::vector<size_t> * >::iterator map_iterator = m_fun_idx_map.begin()
64 6 : ; map_iterator != m_fun_idx_map.end()
65 : ; ++map_iterator) {
66 : /* current vector of indices*/
67 2 : std::vector<size_t> * c_idx = NULL;
68 :
69 : /* temporary value of sub-invocations */
70 : double f_temp;
71 :
72 : /* status of sub-invocations */
73 : int status;
74 :
75 : /* Pointer to current function */
76 2 : Function * c_fun = NULL;
77 2 : c_fun = map_iterator->first;
78 :
79 : /* Function indices */
80 2 : c_idx = map_iterator->second;
81 :
82 : /* initialize new sub-matrix */
83 2 : c_x = new Matrix(c_idx->size(), 1);
84 :
85 : /* iterator for the indices of c_fun */
86 2 : prepare_cx(c_idx, x, c_x);
87 :
88 : /* invoke sub-function on c_x, return f_temp */
89 2 : status = c_fun -> call(*c_x, f_temp);
90 : //LCOV_EXCL_START
91 : if (ForBESUtils::STATUS_OK != status) {
92 : delete c_x;
93 : c_x = NULL;
94 : return status;
95 : }
96 : //LCOV_EXCL_STOP
97 2 : f += f_temp;
98 : }
99 :
100 1 : if (c_x != NULL) {
101 1 : delete c_x;
102 1 : c_x = NULL;
103 : }
104 1 : return ForBESUtils::STATUS_OK;
105 : }
106 :
107 350 : int SeparableSum::call(Matrix& x, double& f, Matrix& grad) {
108 350 : Matrix *c_x = NULL;
109 350 : f = 0.0;
110 350 : Matrix *c_grad = NULL;
111 : /* Invoke all functions */
112 4200 : for (std::map<Function*, std::vector<size_t> * >::iterator map_iterator = m_fun_idx_map.begin()
113 2800 : ; map_iterator != m_fun_idx_map.end()
114 : ; ++map_iterator) {
115 1050 : std::vector<size_t> * c_idx = NULL;
116 : double f_temp;
117 : int status;
118 1050 : Function * c_fun = NULL;
119 1050 : c_fun = map_iterator->first;
120 1050 : c_idx = map_iterator->second;
121 1050 : c_x = new Matrix(c_idx->size(), 1);
122 1050 : prepare_cx(c_idx, x, c_x);
123 1050 : c_grad = new Matrix(c_idx->size(), 1);
124 1050 : status = c_fun -> call(*c_x, f_temp, *c_grad);
125 :
126 : //LCOV_EXCL_START
127 : if (!ForBESUtils::is_status_ok(status)) {
128 : delete c_x;
129 : c_x = NULL;
130 : delete c_grad;
131 : c_grad = NULL;
132 : return status;
133 : }
134 : //LCOV_EXCL_STOP
135 :
136 1050 : size_t k = 0;
137 1050 : std::vector<size_t>::iterator idx_iterator;
138 2800 : for (idx_iterator = c_idx->begin(); idx_iterator != c_idx->end(); ++idx_iterator) {
139 1750 : grad[*idx_iterator] = c_grad->get(k);
140 1750 : k++;
141 : }
142 :
143 1050 : f += f_temp;
144 : }
145 :
146 350 : if (c_x != NULL) {
147 350 : delete c_x;
148 350 : c_x = NULL;
149 : }
150 350 : if (c_grad != NULL) {
151 350 : delete c_grad;
152 350 : c_grad = NULL;
153 : }
154 350 : return ForBESUtils::STATUS_OK;
155 : }
156 :
157 1 : int SeparableSum::callProx(Matrix& x, double gamma, Matrix& prox) {
158 : //LCOV_EXCL_START
159 : if (!x.isColumnVector()) {
160 : throw std::invalid_argument("x must be a column-vector");
161 : }
162 : //LCOV_EXCL_STOP
163 :
164 1 : Matrix *c_x = NULL;
165 1 : Matrix *c_prox = NULL;
166 :
167 9 : for (std::map<Function*, std::vector<size_t> * >::iterator map_iterator = m_fun_idx_map.begin()
168 6 : ; map_iterator != m_fun_idx_map.end()
169 : ; ++map_iterator) {
170 2 : Function * c_fun = map_iterator->first;
171 2 : std::vector<size_t> * c_idx = map_iterator->second;
172 2 : c_x = new Matrix(c_idx->size(), 1);
173 2 : prepare_cx(c_idx, x, c_x);
174 :
175 2 : c_prox = new Matrix(c_idx->size(), 1);
176 2 : int status = c_fun -> callProx(*c_x, gamma, *c_prox);
177 : //LCOV_EXCL_START
178 : if (!ForBESUtils::is_status_ok(status)) {
179 : delete c_x;
180 : delete c_prox;
181 : return status;
182 : }
183 : //LCOV_EXCL_STOP
184 2 : size_t k = 0;
185 2 : std::vector<size_t>::iterator idx_iterator;
186 7 : for (idx_iterator = c_idx->begin(); idx_iterator != c_idx->end(); ++idx_iterator) {
187 5 : prox[*idx_iterator] = c_prox->get(k);
188 5 : k++;
189 : }
190 : }
191 1 : if (c_x != NULL) delete c_x;
192 1 : if (c_prox != NULL) delete c_prox;
193 1 : return ForBESUtils::STATUS_OK;
194 : }
195 :
196 1 : int SeparableSum::callProx(Matrix& x, double gamma, Matrix& prox, double& f_at_prox) {
197 : //LCOV_EXCL_START
198 : if (!x.isColumnVector()) {
199 : throw std::invalid_argument("x must be a column-vector");
200 : }
201 : //LCOV_EXCL_STOP
202 :
203 1 : Matrix *c_x = NULL;
204 1 : Matrix *c_prox = NULL;
205 :
206 1 : f_at_prox = 0.0;
207 1 : double f_at_prox_temp = 0.0;
208 9 : for (std::map<Function*, std::vector<size_t> * >::iterator map_iterator = m_fun_idx_map.begin()
209 6 : ; map_iterator != m_fun_idx_map.end()
210 : ; ++map_iterator) {
211 2 : Function * c_fun = map_iterator->first;
212 2 : std::vector<size_t> * c_idx = map_iterator->second;
213 2 : c_x = new Matrix(c_idx->size(), 1);
214 2 : prepare_cx(c_idx, x, c_x);
215 :
216 2 : c_prox = new Matrix(c_idx->size(), 1);
217 2 : int status = c_fun -> callProx(*c_x, gamma, *c_prox, f_at_prox_temp);
218 2 : f_at_prox += f_at_prox_temp;
219 :
220 : //LCOV_EXCL_START
221 : if (ForBESUtils::STATUS_OK != status) {
222 : delete c_x;
223 : delete c_prox;
224 : return status;
225 : }
226 : //LCOV_EXCL_STOP
227 :
228 2 : size_t k = 0;
229 2 : std::vector<size_t>::iterator idx_iterator;
230 7 : for (idx_iterator = c_idx->begin(); idx_iterator != c_idx->end(); ++idx_iterator) {
231 5 : prox[*idx_iterator] = c_prox->get(k);
232 5 : k++;
233 : }
234 : }
235 1 : if (c_x != NULL) delete c_x;
236 1 : if (c_prox != NULL) delete c_prox;
237 1 : return ForBESUtils::STATUS_OK;
238 : }
239 :
240 20 : int SeparableSum::callConj(Matrix& x, double& f_star) {
241 : //LCOV_EXCL_START
242 : if (!x.isColumnVector()) {
243 : throw std::invalid_argument("x must be a column-vector");
244 : }
245 : //LCOV_EXCL_STOP
246 20 : f_star = 0.0;
247 :
248 20 : std::map<Function*, std::vector<size_t> * >::iterator map_iterator;
249 20 : Function * c_fun = NULL;
250 20 : Matrix *c_x = NULL;
251 :
252 60 : for (map_iterator = m_fun_idx_map.begin(); map_iterator != m_fun_idx_map.end(); ++map_iterator) {
253 40 : std::vector<size_t> * c_idx = NULL;
254 40 : c_fun = map_iterator->first; // current function
255 40 : c_idx = map_iterator->second; // current index set I
256 40 : c_x = new Matrix(c_idx->size(), 1); // prepare current vector
257 40 : prepare_cx(c_idx, x, c_x);
258 :
259 : double f_star_temp;
260 40 : int status = c_fun -> callConj(*c_x, f_star_temp);
261 : //LCOV_EXCL_START
262 : if (!ForBESUtils::is_status_ok(status)) {
263 : delete c_x;
264 : c_x = NULL;
265 : return status;
266 : }
267 : //LCOV_EXCL_STOP
268 40 : f_star += f_star_temp;
269 : }
270 20 : if (c_x != NULL) {
271 20 : delete c_x;
272 20 : c_x = NULL;
273 : }
274 20 : return ForBESUtils::STATUS_UNDEFINED_FUNCTION;
275 : }
276 :
277 2 : FunctionOntologicalClass SeparableSum::category() {
278 2 : FunctionOntologicalClass meta("SeparableSum");
279 2 : meta.set_defines_f(true);
280 2 : meta.set_defines_grad(true);
281 2 : meta.set_defines_prox(true);
282 2 : meta.set_defines_conjugate(true);
283 2 : meta.add_superclass(FunctionOntologyRegistry::function());
284 2 : return meta;
285 3 : }
286 :
287 :
|