Line data Source code
1 : /*
2 : * File: TestSumOfNorm2.cpp
3 : * Author: chung
4 : *
5 : * Created on Feb 29, 2016, 5:18:46 PM
6 : */
7 :
8 : #include "TestSumOfNorm2.h"
9 : #include "SumOfNorm2.h"
10 :
11 :
12 1 : CPPUNIT_TEST_SUITE_REGISTRATION(TestSumOfNorm2);
13 :
14 6 : TestSumOfNorm2::TestSumOfNorm2() {
15 6 : }
16 :
17 12 : TestSumOfNorm2::~TestSumOfNorm2() {
18 12 : }
19 :
20 6 : void TestSumOfNorm2::setUp() {
21 6 : }
22 :
23 6 : void TestSumOfNorm2::tearDown() {
24 6 : }
25 :
26 1 : void TestSumOfNorm2::testCall() {
27 1 : const size_t k = 2;
28 1 : const double mu = 1.0;
29 1 : const double tolerance = 1e-8;
30 1 : Norm * f0 = new SumOfNorm2(k);
31 1 : Norm * f = new SumOfNorm2(mu, k);
32 1 : Matrix x(4, 1);
33 1 : double f_val = -1.0;
34 :
35 1 : _ASSERT(f->category().defines_f());
36 1 : int status = f->call(x, f_val);
37 1 : _ASSERT(ForBESUtils::is_status_ok(status));
38 1 : _ASSERT_NUM_EQ(0.00, f_val, tolerance);
39 :
40 1 : x[0] = -1.0;
41 1 : x[1] = 1.0;
42 1 : x[2] = 2.0;
43 1 : x[3] = -1.0;
44 :
45 1 : const double correct_val = 3.65028153987288;
46 1 : status = f->call(x, f_val);
47 1 : _ASSERT(ForBESUtils::is_status_ok(status));
48 1 : _ASSERT_NUM_EQ(correct_val, f_val, tolerance);
49 :
50 1 : status = f0->call(x, f_val);
51 1 : _ASSERT(ForBESUtils::is_status_ok(status));
52 1 : _ASSERT_NUM_EQ(correct_val, f_val, tolerance);
53 :
54 1 : delete f;
55 1 : delete f0;
56 1 : }
57 :
58 1 : void TestSumOfNorm2::testDualNorm() {
59 1 : const size_t k = 3;
60 1 : const size_t n = 12;
61 1 : const double mu = 1.0;
62 1 : const double tolerance = 1e-8;
63 :
64 : double x_data[n] = {
65 : 1, -2, -1,
66 : 2, -1, 1,
67 : 0, 1, 3,
68 : 2, 1.5, 0.5
69 1 : };
70 :
71 1 : const double correct_val = 10.6107669025311;
72 1 : const double correct_val_dual = 3.16227766016838;
73 :
74 1 : Norm * son = new SumOfNorm2(mu, k);
75 :
76 1 : int status = -1;
77 :
78 1 : Matrix x = MatrixFactory::ShallowVector(x_data, n, static_cast<size_t> (0));
79 : double f_val;
80 1 : _ASSERT(son->category().defines_f());
81 1 : status = son->call(x, f_val);
82 1 : _ASSERT(ForBESUtils::is_status_ok(status));
83 1 : _ASSERT_NUM_EQ(correct_val, f_val, tolerance);
84 :
85 : double f_val_dual;
86 1 : _ASSERT(son->category().defines_conjugate());
87 1 : status = son->dualNorm(x, f_val_dual);
88 1 : _ASSERT(ForBESUtils::is_status_ok(status));
89 1 : _ASSERT_NUM_EQ(correct_val_dual, f_val_dual, tolerance);
90 :
91 1 : delete son;
92 1 : }
93 :
94 1 : void TestSumOfNorm2::testProx() {
95 1 : const size_t k = 3;
96 1 : const size_t n = 12;
97 1 : const double mu = 1.0;
98 1 : const double gamma = 0.8;
99 :
100 : double v_data[n] = {
101 : -1, 1, -1,
102 : 3, -1, 1,
103 : 1, -1.5, 2,
104 : -2, 1.5, 0.5
105 1 : };
106 :
107 1 : Norm * son = new SumOfNorm2(mu, k);
108 :
109 1 : Matrix prox(n, 1);
110 2 : Matrix v = MatrixFactory::ShallowVector(v_data, n, static_cast<size_t> (0));
111 : int status;
112 1 : _ASSERT(son->category().defines_prox());
113 1 : status = son->callProx(v, gamma, prox);
114 :
115 :
116 1 : _ASSERT(ForBESUtils::is_status_ok(status));
117 :
118 : double prox_correct_data[] = {
119 : -0.538119784648299,
120 : 0.538119784648299,
121 : -0.538119784648299,
122 : 2.276372773013367,
123 : -0.758790924337789,
124 : 0.758790924337789,
125 : 0.702887458916717,
126 : -1.054331188375075,
127 : 1.405774917833434,
128 : -1.372428367557811,
129 : 1.029321275668358,
130 : 0.343107091889453
131 1 : };
132 :
133 2 : Matrix prox_correct = MatrixFactory::ShallowVector(prox_correct_data, n, 0);
134 1 : _ASSERT_EQ(prox_correct, prox);
135 :
136 2 : delete son;
137 1 : }
138 :
139 1 : void TestSumOfNorm2::testFaultyDims() {
140 1 : const size_t k = 3;
141 1 : const size_t n = 16;
142 1 : const double gamma = 0.8;
143 :
144 1 : Norm * son = new SumOfNorm2(k);
145 :
146 1 : Matrix x(n, 1);
147 : double val;
148 :
149 1 : _ASSERT_EXCEPTION(son->call(x, val), std::invalid_argument);
150 1 : _ASSERT_EXCEPTION(son->dualNorm(x, val), std::invalid_argument);
151 :
152 2 : Matrix prox(n, 1);
153 1 : _ASSERT_EXCEPTION(son->callProx(x, gamma, prox), std::invalid_argument);
154 :
155 2 : delete son;
156 :
157 1 : }
158 :
159 1 : void TestSumOfNorm2::testFunAtProx() {
160 1 : const size_t k = 3;
161 1 : const size_t n = 9;
162 1 : const double mu = 3.5;
163 1 : const double gamma = 0.8;
164 :
165 :
166 1 : Function * son = new SumOfNorm2(mu, k);
167 :
168 1 : Matrix prox(n, 1);
169 2 : Matrix v = MatrixFactory::MakeRandomMatrix(n, 1, 0.0, 2.0);
170 : int status;
171 1 : double f_at_prox = 0.0;
172 1 : double f_at_prox2 = 0.0;
173 1 : _ASSERT(son->category().defines_prox());
174 1 : status = son->callProx(v, gamma, prox, f_at_prox);
175 1 : _ASSERT(ForBESUtils::is_status_ok(status));
176 :
177 1 : status = son->call(prox, f_at_prox2);
178 1 : _ASSERT(ForBESUtils::is_status_ok(status));
179 1 : _ASSERT_NUM_EQ(f_at_prox, f_at_prox2, 1e-7);
180 :
181 2 : delete son;
182 1 : }
183 :
184 1 : void TestSumOfNorm2::testVerification() {
185 : /**
186 : * Verify SumOfNorm2 by comparing to SumOfNorm2(mu, k=1) with Norm1(mu)
187 : */
188 :
189 1 : const size_t n = 50;
190 1 : const double mu = 0.857;
191 1 : Norm * norm1 = new Norm1(mu);
192 1 : Norm * son = new SumOfNorm2(mu, 1);
193 1 : const double gamma = 0.975;
194 :
195 1 : double f1 = -1.0;
196 1 : double f2 = -2.0;
197 : int status;
198 :
199 1 : Matrix x = MatrixFactory::MakeRandomMatrix(n, 1, -0.5, 1.5);
200 :
201 : /* Check values */
202 1 : status = norm1->call(x, f1);
203 1 : _ASSERT(ForBESUtils::is_status_ok(status));
204 1 : status = son->call(x, f2);
205 1 : _ASSERT(ForBESUtils::is_status_ok(status));
206 1 : _ASSERT_NUM_EQ(f1, f2, 1e-8);
207 :
208 :
209 : /* Check dual norm values */
210 1 : double dual_norm_1 = -1.0;
211 1 : double dual_norm_2 = -2.0;
212 1 : status = norm1->dualNorm(x, dual_norm_1);
213 1 : _ASSERT(ForBESUtils::is_status_ok(status));
214 1 : status = son->dualNorm(x, dual_norm_2);
215 1 : _ASSERT(ForBESUtils::is_status_ok(status));
216 1 : _ASSERT_NUM_EQ(dual_norm_1, dual_norm_2, 1e-8);
217 :
218 : /* Check proximals */
219 2 : Matrix prox1(n, 1);
220 2 : Matrix prox2(n, 1);
221 : double f_at_prox_1;
222 : double f_at_prox_2;
223 1 : status = norm1->callProx(x, gamma, prox1, f_at_prox_1);
224 1 : _ASSERT(ForBESUtils::is_status_ok(status));
225 1 : status = son->callProx(x, gamma, prox2, f_at_prox_2);
226 1 : _ASSERT(ForBESUtils::is_status_ok(status));
227 1 : _ASSERT_EQ(prox1, prox2);
228 1 : _ASSERT_NUM_EQ(f_at_prox_1, f_at_prox_2, 1e-8);
229 :
230 1 : delete norm1;
231 2 : delete son;
232 4 : }
|