Skip to content

Commit

Permalink
(Issue #145) Update tests and path management toward MATLAB CI.
Browse files Browse the repository at this point in the history
pounders.m and its tests often add folders to the MATLAB path but do so using
relative paths, which can influence from where you can call the code.  The
changes here adopt a different path strategy using paths relative to the file
that is adding to the path.  This is related to Issue #127.  A second goal is
to make it so that users don't have to add too many paths.

Confirmed that the full test suite can be run as detailed in its inline
documentation.  This includes creating an HTML coverage report.  Confirmed that
changes to the path made by tests are not present upon termination.  Ran each
single test individually with a clean MATLAB environment to confirm that they
run through with and only with the documented path requirements.  Confirmed
that they leave the path as found upon entry.
  • Loading branch information
jared321 committed Apr 25, 2024
1 parent 9be1da3 commit ba4fbb1
Show file tree
Hide file tree
Showing 9 changed files with 106 additions and 5 deletions.
31 changes: 30 additions & 1 deletion pounders/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,41 @@ xk_in [int] Index of point in X representing approximate minimizer

## Testing

To fully test the MATLAB implementation of POUNDERs:
### MATLAB
To run tests of MATLAB-based POUNDERs, users must have an up-to-date BenDFO
clone installed and add
* /path/to/BenDFO/data
* /path/to/BenDFO/m
to their MATLAB path. They should also ensure that the `minq` submodule in
their IBCDFO clone is at the latest version.

Note that some code in POUNDERs and its tests automatically alter the MATLAB
path. While the POUNDERs tests will reset the path to its original state if
all tests pass, the path might remain altered if a test fails.

The MATLAB implementation of POUNDERs contains a single test case
```
/path/to/IBCDFO/pounders/m/tests/Testpounders.m
```
which calls individual tests such as `test_bmpts.m`.

To fully test the MATLAB implementation of POUNDERs without coverage:

1. change to the `pounders/m/tests` directory
2. open MATLAB, and
3. execute `runtests` from the prompt.

To fully test the MATLAB implementation of POUNDERs with coverage:

1. change to the `pounders/m` directory
2. open MATLAB, and
3. execute `runtests("IncludeSubfolders", true, "ReportCoverageFor", pwd)`

Users can also run each test function individually as usual if so desired.
Please refer to the inline documentation of each test or test case for more
information on how to run the test.

### Python
To fully test the Python implementation of POUNDERs:

1. navigate to the `ibcdfo_pypkg` directory
Expand Down
14 changes: 13 additions & 1 deletion pounders/m/pounders.m
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@
combinemodels = Options.combinemodels;
else
% Use least-squares hfun by default
addpath('../general_h_funs/');
[here_path, ~, ~] = fileparts(mfilename('fullpath'));
addpath(fullfile(here_path, 'general_h_funs'));
hfun = @(F)sum(F.^2);
combinemodels = @leastsquares;
end
Expand Down Expand Up @@ -89,6 +90,17 @@
eta_1 = Options.eta_1;
printf = Options.printf;
delta_inact = Options.delta_inact;

if spsolver == 2 % Arnold Neumaier's minq5
[here_path, ~, ~] = fileparts(mfilename('fullpath'));
minq_path = fullfile(here_path, '..', '..', 'minq');
addpath(fullfile(minq_path, 'm', 'minq5'));
elseif spsolver == 3 % Arnold Neumaier's minq8
[here_path, ~, ~] = fileparts(mfilename('fullpath'));
minq_path = fullfile(here_path, '..', '..', 'minq');
addpath(fullfile(minq_path, 'm', 'minq8'));
end

% 0. Check inputs
[flag, X_0, np_max, F0, Low, Upp, xk_in] = ...
checkinputss(Ffun, X_0, n, Model.np_max, nf_max, g_tol, delta, nfs, m, Prior.F_init, Prior.xk_in, Low, Upp);
Expand Down
17 changes: 17 additions & 0 deletions pounders/m/tests/Testpounders.m
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
% To run this test, you must first install a BenDFO clone and add
% /path/to/BenDFO/data
% /path/to/BenDFO/m
% to the MATLAB path.
%
% From MATLAB and the directory containing this file, execute
% >> runtests
%
% If you would like to run this from a different folder that includes these
% tests as a subfolder, then from that folder execute
% >> runtests("IncludeSubfolders", true)
%
% To execute the test suite with coverage enabled and to generate an HTML-format
% coverage report, execute from /path/to/IBCDFO/pounders/m
% >> runtests("IncludeSubfolders", true, "ReportCoverageFor", pwd)
%

classdef Testpounders < matlab.unittest.TestCase
methods (Test)

Expand Down
12 changes: 12 additions & 0 deletions pounders/m/tests/benchmark_pounders.m
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
% This wrapper tests various algorithms against the Benchmark functions from the
% More and Wild SIOPT paper "Benchmarking derivative-free optimization algorithms"
%
% To run this test, you must first install a BenDFO clone and add
% /path/to/BenDFO/data
% /path/to/BenDFO/m
% to the MATLAB path.

function [] = benchmark_pounders()

[here_path, ~, ~] = fileparts(mfilename('fullpath'));
oldpath = addpath(fullfile(here_path, '..'));
addpath(fullfile(here_path, '..', 'general_h_funs'));

load dfo.dat;

ensure_still_solve_problems = 0;
Expand Down Expand Up @@ -100,6 +110,8 @@
if ~ensure_still_solve_problems
writematrix(solved, './benchmark_results/solved.txt');
end

path(oldpath);
end

function [fvec] = calfun_wrapper(x, struct, probtype)
Expand Down
5 changes: 5 additions & 0 deletions pounders/m/tests/test_bmpts.m
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
% This tests bmpts.m when it notes that:
% "Geometry points need to be coordinate directions!"

[here_path, ~, ~] = fileparts(mfilename('fullpath'));
oldpath = addpath(fullfile(here_path, '..'));

nf_max = 100;
g_tol = 1e-13;

Expand Down Expand Up @@ -34,3 +37,5 @@
Prior.nfs = nfs;

[X, F, hf, flag, xk_best] = pounders(objective, X_0, n, nf_max, g_tol, delta_0, m, Low, Upp, Prior);

path(oldpath);
15 changes: 12 additions & 3 deletions pounders/m/tests/test_bounds_and_sp1.m
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,18 @@
% - the handling of bounds
% - printing
% - Using starting points in X0 and F0
%
% To run this test, you must first install a BenDFO clone and add
% /path/to/BenDFO/data
% /path/to/BenDFO/m
% to the MATLAB path.

function [] = test_bounds_and_sp1()

[here_path, ~, ~] = fileparts(mfilename('fullpath'));
oldpath = addpath(fullfile(here_path, '..'));
addpath(fullfile(here_path, '..', 'general_h_funs'));

nf_max = 100;
g_tol = 1e-13;
factor = 10;
Expand Down Expand Up @@ -82,10 +91,10 @@
end

% Test success without last (optional) arguments to pounders
minq_location = '../../../../minq/m/minq5/';
addpath(minq_location);

[X, F, hF, flag, xk_best] = pounders(objective, X_0, n, nf_max, g_tol, delta_0, m, Low, Upp);

path(oldpath);

assert(flag == 0, "Test didn't complete");
end

Expand Down
6 changes: 6 additions & 0 deletions pounders/m/tests/test_emittance_opt.m
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
[here_path, ~, ~] = fileparts(mfilename('fullpath'));
oldpath = addpath(fullfile(here_path, '..'));
addpath(fullfile(here_path, '..', 'general_h_funs'));

% Adjust these:
n = 4; % Number of parameters to be optimized
X_0 = rand(1, n); % starting parameters for the optimizer
Expand Down Expand Up @@ -30,6 +34,8 @@

[Xout, Fouf, hFout, flag, xk_best] = pounders(@call_beamline_simulation, X_0, n, nf_max, g_tol, delta_0, m, Low, Upp, Prior, Options);

path(oldpath);

assert(flag >= 0, 'pounders crashed');

assert(hFout(xk_best) == min(hFout), 'The minimum emittance is not at xk_best');
Expand Down
5 changes: 5 additions & 0 deletions pounders/m/tests/test_failing_objective.m
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

function [] = test_failing_objective()

[here_path, ~, ~] = fileparts(mfilename('fullpath'));
oldpath = addpath(fullfile(here_path, '..'));

spsolver = 1;

nf_max = 1000;
Expand All @@ -29,3 +32,5 @@
% Intentionally not passing a function for an objective
[X, F, hF, flag, xk_best] = pounders(X_0, X_0, n, nf_max, g_tol, delta_0, m, Low, Upp, [], [], Model);
assert(flag == -1, "Should have failed");

path(oldpath);
6 changes: 6 additions & 0 deletions pounders/m/tests/test_one_m_pounders.m
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
% So this is not how pounders is intended to be used, but can be a comparison
% method.

[here_path, ~, ~] = fileparts(mfilename('fullpath'));
oldpath = addpath(fullfile(here_path, '..'));
addpath(fullfile(here_path, '..', 'general_h_funs'));

Ffun = @(x) ((1 - x(1)).^2) + (100 * ((x(2) - (x(1)^2)).^2)); % Rosenbrock
X_0 = [-1.2, 1];

Expand Down Expand Up @@ -36,5 +40,7 @@
Model.np_max = np_max;
[X, F, hf, flag, xkin] = pounders(Ffun, X_0, n, nf_max, g_tol, delta_0, m, Low, Upp, Prior, Options, Model);

path(oldpath);

assert(flag == 0, "We should solve this within 200 evaluations");
assert(norm(X(xkin, :) - ones(1, 2)) <= g_tol * 10, "We should be within 10*gtol of the known optimum [1,1]");

0 comments on commit ba4fbb1

Please sign in to comment.