|
| 1 | +% From MATLAB and the directory containing this file, execute |
| 2 | +% >> runtests |
| 3 | +% |
| 4 | +% If you would like to run this from a different folder that includes these |
| 5 | +% tests as a subfolder, then from that folder execute |
| 6 | +% >> runtests("IncludeSubfolders", true) |
| 7 | +% |
| 8 | +% To execute the test suite with coverage enabled and to generate an HTML-format |
| 9 | +% coverage report, execute from /path/to/IBCDFO/pounders/m |
| 10 | +% >> runtests("IncludeSubfolders", true, "ReportCoverageFor", pwd) |
| 11 | +% |
| 12 | + |
| 13 | +classdef Testcreatesquareddifffrommeanfunctions < matlab.unittest.TestCase |
| 14 | + properties |
| 15 | + n |
| 16 | + m |
| 17 | + F |
| 18 | + Cres |
| 19 | + Gres |
| 20 | + Hres |
| 21 | + end |
| 22 | + |
| 23 | + methods (TestMethodSetup) |
| 24 | + |
| 25 | + function setup(testCase) |
| 26 | + % Test problem 1 setup |
| 27 | + % - Here and in tests *_bar refers to an average of * |
| 28 | + testCase.n = 2; |
| 29 | + testCase.m = 3; |
| 30 | + testCase.F = [3.3; -1.1; 4.4]; |
| 31 | + % F_bar = 2.2; |
| 32 | + % F_bar_sqr = 4.84; |
| 33 | + % Delta_F = F - F_bar = [1.1; -3.3; 2.2]; |
| 34 | + % F_sum = 16.94; |
| 35 | + |
| 36 | + testCase.Cres = testCase.F; |
| 37 | + |
| 38 | + testCase.Gres = [[1.1 0.3 2.2] |
| 39 | + [2.2 0.3 1.4]]; |
| 40 | + % G_bar = [1.2 1.3]; |
| 41 | + |
| 42 | + testCase.Hres = zeros([testCase.n testCase.n testCase.m]); |
| 43 | + testCase.Hres(:, :, 1) = [[1.2 -2.3] |
| 44 | + [-2.3 3.4]]; |
| 45 | + testCase.Hres(:, :, 2) = [[-1.4 3.2] |
| 46 | + [3.2 -2.1]]; |
| 47 | + testCase.Hres(:, :, 3) = [[3.5 1.8] |
| 48 | + [1.8 -2.5]]; |
| 49 | + end |
| 50 | + |
| 51 | + end |
| 52 | + |
| 53 | + methods (Test) |
| 54 | + |
| 55 | + function badArguments(testCase) |
| 56 | + testCase.verifyError( ... |
| 57 | + @()create_squared_diff_from_mean_functions([]), ... |
| 58 | + 'MATLAB:validators:mustBeNonempty' ... |
| 59 | + ); |
| 60 | + |
| 61 | + testCase.verifyError( ... |
| 62 | + @()create_squared_diff_from_mean_functions([1.1 2.2]), ... |
| 63 | + 'MATLAB:validators:mustBeScalarOrEmpty' ... |
| 64 | + ); |
| 65 | + |
| 66 | + for bad = ["bad", 1j, 1.0 - 2.0 * 1j] |
| 67 | + testCase.verifyError( ... |
| 68 | + @()create_squared_diff_from_mean_functions(bad), ... |
| 69 | + 'MATLAB:validators:mustBeReal' ... |
| 70 | + ); |
| 71 | + end |
| 72 | + |
| 73 | + for bad = [inf -inf nan] |
| 74 | + testCase.verifyError( ... |
| 75 | + @()create_squared_diff_from_mean_functions(bad), ... |
| 76 | + 'MATLAB:validators:mustBeFinite' ... |
| 77 | + ); |
| 78 | + testCase.verifyError( ... |
| 79 | + @()create_squared_diff_from_mean_functions([bad]), ... |
| 80 | + 'MATLAB:validators:mustBeFinite' ... |
| 81 | + ); |
| 82 | + end |
| 83 | + end |
| 84 | + |
| 85 | + function confirmImmutable(testCase) |
| 86 | + % Construct using variable declared in this scope & collect results |
| 87 | + alpha = 1.2; |
| 88 | + [hfun, combinemodels] = ... |
| 89 | + create_squared_diff_from_mean_functions(alpha); |
| 90 | + hF = hfun(testCase.F); |
| 91 | + [G, H] = combinemodels(testCase.Cres, ... |
| 92 | + testCase.Gres, ... |
| 93 | + testCase.Hres); |
| 94 | + |
| 95 | + % Alter same construction variable & confirm that it yields |
| 96 | + % different results |
| 97 | + alpha = -2.3 * alpha; |
| 98 | + [hfun_2, combinemodels_2] = ... |
| 99 | + create_squared_diff_from_mean_functions(alpha); |
| 100 | + hF_2 = hfun_2(testCase.F); |
| 101 | + [G_2, H_2] = combinemodels_2(testCase.Cres, ... |
| 102 | + testCase.Gres, ... |
| 103 | + testCase.Hres); |
| 104 | + testCase.assertNotEqual(hF, hF_2); |
| 105 | + testCase.assertFalse(isequal(G, G_2)); |
| 106 | + testCase.assertFalse(isequal(H, H_2)); |
| 107 | + |
| 108 | + % Confirm that changes to actual alpha argument used to construct |
| 109 | + % hfun and combinemodels do not alter those functions. This check |
| 110 | + % is motivated by technical subtleties seen with Python. |
| 111 | + hF_new = hfun(testCase.F); |
| 112 | + [G_new, H_new] = combinemodels(testCase.Cres, ... |
| 113 | + testCase.Gres, ... |
| 114 | + testCase.Hres); |
| 115 | + testCase.assertEqual(hF, hF_new); |
| 116 | + testCase.assertTrue(isequal(G, G_new)); |
| 117 | + testCase.assertTrue(isequal(H, H_new)); |
| 118 | + end |
| 119 | + |
| 120 | + function testFunctions(testCase) |
| 121 | + % Handworked intermediate results for test problem 1 |
| 122 | + H_bar = [[1.1 0.9] |
| 123 | + [0.9 -0.4]]; |
| 124 | + H_JmGJmG = [[3.64 1.82] |
| 125 | + [1.82 3.64]]; |
| 126 | + H_GG = [[2.88 3.12] |
| 127 | + [3.12 3.38]]; |
| 128 | + H_FH = [[27.28 -18.26] |
| 129 | + [-18.26 10.34]]; |
| 130 | + |
| 131 | + % Include |
| 132 | + % - Negative and positive |
| 133 | + % - What look like integer and double literals |
| 134 | + % - The special case of alpha = 0.0 |
| 135 | + for alpha = [-1.1 -5 0.0 2.3 4] |
| 136 | + [hfun, combinemodels] = ... |
| 137 | + create_squared_diff_from_mean_functions(alpha); |
| 138 | + |
| 139 | + % Check F = F_bar = 0.0 super-duper special case |
| 140 | + F = zeros([10 1]); |
| 141 | + [G, H] = combinemodels(F, ... |
| 142 | + testCase.Gres, ... |
| 143 | + testCase.Hres); |
| 144 | + testCase.assertEqual(size(G), [testCase.n 1]); |
| 145 | + testCase.assertEqual(size(H), [testCase.n testCase.n]); |
| 146 | + testCase.assertTrue(isequal(H, H')); |
| 147 | + |
| 148 | + testCase.assertEqual(0.0, hfun(F)); |
| 149 | + |
| 150 | + testCase.assertEqual(G, zeros(size(G))); |
| 151 | + |
| 152 | + H_f = H_JmGJmG - alpha * H_GG; |
| 153 | + max_abs_err = max(abs(H - H_f), [], "all"); |
| 154 | + testCase.assertTrue(max_abs_err <= 35.0 * eps); |
| 155 | + |
| 156 | + % Check F - F_bar = 0 with F_bar != 0 special cases |
| 157 | + for F_bar = [-10.1 3.3] |
| 158 | + F = F_bar * ones([6 1]); |
| 159 | + hF = hfun(F); |
| 160 | + [G, H] = combinemodels(F, ... |
| 161 | + testCase.Gres, ... |
| 162 | + testCase.Hres); |
| 163 | + testCase.assertEqual(size(G), [testCase.n 1]); |
| 164 | + testCase.assertEqual(size(H), [testCase.n testCase.n]); |
| 165 | + testCase.assertTrue(isequal(H, H')); |
| 166 | + |
| 167 | + abs_err = abs(hF + alpha * F_bar^2); |
| 168 | + testCase.assertEqual(0.0, abs_err); |
| 169 | + |
| 170 | + grad_f = -2.0 * alpha * F_bar * [1.2; 1.3]; |
| 171 | + abs_err = max(abs(G - grad_f)); |
| 172 | + testCase.assertTrue(abs_err <= 130.0 * eps); |
| 173 | + |
| 174 | + H_f = H_JmGJmG - alpha * (H_GG + 2.0 * F_bar * H_bar); |
| 175 | + max_abs_err = max(abs(H - H_f), [], "all"); |
| 176 | + testCase.assertTrue(max_abs_err <= 195.0 * eps); |
| 177 | + end |
| 178 | + |
| 179 | + % Check generic test problem |
| 180 | + hF = hfun(testCase.F); |
| 181 | + [G, H] = combinemodels(testCase.Cres, ... |
| 182 | + testCase.Gres, ... |
| 183 | + testCase.Hres); |
| 184 | + testCase.assertEqual(size(G), [testCase.n 1]); |
| 185 | + testCase.assertEqual(size(H), [testCase.n testCase.n]); |
| 186 | + testCase.assertTrue(isequal(H, H')); |
| 187 | + |
| 188 | + hF_expected = 16.94 - alpha * 4.84; |
| 189 | + abs_err = abs(hF - hF_expected); |
| 190 | + testCase.assertTrue(abs_err <= 20.0 * eps); |
| 191 | + |
| 192 | + grad_f = [10.12; 9.02] - alpha * [5.28; 5.72]; |
| 193 | + abs_err = max(abs(G - grad_f)); |
| 194 | + testCase.assertTrue(abs_err <= 35.0 * eps); |
| 195 | + |
| 196 | + H_f = H_JmGJmG + H_FH - alpha * (H_GG + 2.0 * 2.2 * H_bar); |
| 197 | + max_abs_err = max(abs(H - H_f), [], "all"); |
| 198 | + testCase.assertTrue(max_abs_err <= 70.0 * eps); |
| 199 | + end |
| 200 | + end |
| 201 | + |
| 202 | + end |
| 203 | +end |
0 commit comments