Skip to content

Commit 3742375

Browse files
committed
Various minor minor functionality tweaks and backwards compatibility fixes
1 parent f087e9f commit 3742375

File tree

4 files changed

+80
-21
lines changed

4 files changed

+80
-21
lines changed

inst/bootridge.m

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2285,7 +2285,7 @@
22852285
%! m = 30;
22862286
%! x = linspace (-1, 1, m).';
22872287
%! X = x; % No intercept provided
2288-
%! randn ('twister', 123);
2288+
%! randn ('seed', 123);
22892289
%! y = 1.0 + 0.8 * x + 0.1 * randn (m,1);
22902290
%! S = bootridge (y, X, [], 200, 0.05, [], 1.1, 777);
22912291
%! % Check expected fields and sizes
@@ -2309,7 +2309,7 @@
23092309
%! m = 28;
23102310
%! x = linspace (-1.5, 1.5, m).';
23112311
%! X = [ones(m,1), x]; % Explicit intercept is first column
2312-
%! randn ('twister', 123);
2312+
%! randn ('seed', 123);
23132313
%! y = 3.0 + 0.4 * x + 0.15 * randn (m,1);
23142314
%! % Contrast to extract only the slope (second coefficient)
23152315
%! L = [0; 1];
@@ -2330,7 +2330,7 @@
23302330
%! x = linspace (-2, 2, m).';
23312331
%! X = [ones(m,1), g, x];
23322332
%! beta = [1.0; 0.7; -0.2];
2333-
%! randn ('twister', 123);
2333+
%! randn ('seed', 123);
23342334
%! y = X * beta + 0.25 * randn (m, 1);
23352335
%! categor = 2; % column 2 is categorical (excludes intercept)
23362336
%! S = bootridge (y, X, categor, 100, 0.05, [], 1, 2024);
@@ -2347,7 +2347,7 @@
23472347
%! x = linspace (-1, 1, m).';
23482348
%! X = [ones(m,1), x];
23492349
%! B = [2.0, -1.0; 0.5, 0.8];
2350-
%! randn ('twister', 123);
2350+
%! randn ('seed', 123);
23512351
%! Y = X * B + 0.2 * randn (m, 2);
23522352
%! S1 = bootridge (Y, X, [], 100, 0.10, [], 1, 42);
23532353
%! S2 = bootridge (Y, X, [], 100, 0.10, [], 2, 42);

inst/randtest.m

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,15 @@
4040
% regression coefficients, or with @cor for the correlation coefficient.
4141
% The default value of FUNC is @mldivide.
4242
%
43+
% If function evaluations cannot be vectorized and the parallel computing
44+
% toolbox (Matlab) or Parallel package (Octave) is installed and loaded,
45+
% then the function evaluations will be automatically accelerated by
46+
% parallel processing on platforms with multiple processors. In GNU
47+
% Octave, the maximum number of workers used can be set by the user
48+
% before running randtest, for example, for 2 workers with the command:
49+
%
50+
% setenv ('OMP_NUM_THREADS', '2')
51+
%
4352
% 'PVAL = randtest (X, Y, NREPS, FUNC, SEED)' initialises the Mersenne
4453
% Twister random number generator using an integer SEED value so that
4554
% the results of 'randtest' results are reproducible when the
@@ -90,16 +99,24 @@
9099
% Check if we have parallel processing capabilities
91100
PARALLEL = false; % Default
92101
if (ISOCTAVE)
102+
%%% OCTAVE %%%
93103
software = pkg ('list');
94104
names = cellfun (@(S) S.name, software, 'UniformOutput', false);
95105
status = cellfun (@(S) S.loaded, software, 'UniformOutput', false);
96106
index = find (~ cellfun (@isempty, regexpi (names, '^parallel')));
97107
if ( (~ isempty (index)) && (logical (status{index})) )
98108
PARALLEL = true;
109+
% Set ncpus manually through environmental variable, for example:
110+
% setenv ('OMP_NUM_THREADS', '4')
111+
% It is optimal to set this to the number of physical cores, which will be
112+
% different to the number of logical cores when hyperthreading is enabled.
113+
% This can improve performance by reducing parallel overheads.
114+
ncpus = nproc ('overridable');
99115
end
100116
else
117+
%%% MATLAB %%%
101118
try
102-
pool = gcp ('nocreate');
119+
pool = gcp ('nocreate');
103120
PARALLEL = ~ isempty (pool);
104121
catch
105122
% Do nothing
@@ -206,7 +223,7 @@
206223
else
207224
if (PARALLEL)
208225
if (ISOCTAVE)
209-
STATS = parcellfun (inf, func, num2cell (repmat(x, 1, nreps), 1), ...
226+
STATS = parcellfun (ncpus, func, num2cell (repmat(x, 1, nreps), 1), ...
210227
num2cell (Y, 1));
211228
else
212229
STATS = zeros (1, nreps);

inst/randtest2.m

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,11 @@
7676
% after sampling cannot be vectorized. If the parallel computing toolbox
7777
% (Matlab) or Parallel package (Octave) is installed and loaded, then the
7878
% function evaluations will be automatically accelerated by parallel
79-
% processing on platforms with multiple processors.
79+
% processing on platforms with multiple processors. In GNU Octave, the
80+
% maximum number of workers used can be set by the user before running
81+
% randtest2, for example, for 2 workers with the command:
82+
%
83+
% setenv ('OMP_NUM_THREADS', '2')
8084
%
8185
% '[PVAL, STAT] = randtest2 (...)' also returns the test statistic.
8286
%
@@ -129,16 +133,24 @@
129133
% Check if we have parallel processing capabilities
130134
PARALLEL = false; % Default
131135
if (ISOCTAVE)
136+
%%% OCTAVE %%%
132137
software = pkg ('list');
133138
names = cellfun (@(S) S.name, software, 'UniformOutput', false);
134139
status = cellfun (@(S) S.loaded, software, 'UniformOutput', false);
135140
index = find (~ cellfun (@isempty, regexpi (names, '^parallel')));
136141
if ( (~ isempty (index)) && (logical (status{index})) )
137142
PARALLEL = true;
143+
% Set ncpus manually through environmental variable, for example:
144+
% setenv ('OMP_NUM_THREADS', '4')
145+
% It is optimal to set this to the number of physical cores, which will be
146+
% different to the number of logical cores when hyperthreading is enabled.
147+
% This can improve performance by reducing parallel overheads.
148+
ncpus = nproc ('overridable');
138149
end
139150
else
151+
%%% MATLAB %%%
140152
try
141-
pool = gcp ('nocreate');
153+
pool = gcp ('nocreate');
142154
PARALLEL = ~ isempty (pool);
143155
catch
144156
% Do nothing
@@ -355,7 +367,7 @@
355367
else
356368
if (PARALLEL)
357369
if (ISOCTAVE)
358-
STATS = pararrayfun (inf, @(b) func (vertcat (X{:,b}), ...
370+
STATS = pararrayfun (ncpus, @(b) func (vertcat (X{:,b}), ...
359371
vertcat (Y{:,b})), 1:nreps);
360372
else
361373
STATS = zeros (1, nreps);

test/test_script.m

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -490,14 +490,12 @@
490490
'no' 'no' 'yes' 'no' 'no' 'no' 'no' 'no' 'yes'}';
491491
babble = [4.6 4.4 3.9 5.6 5.1 5.5 3.9 3.5 3.7...
492492
5.6 4.7 5.9 6.0 5.4 6.6 5.8 5.3 5.7]';
493-
494493
STATS = bootlm (babble, {sugar, milk}, 'model', 'full', 'display', 'off', ...
495494
'varnames', {'sugar', 'milk'});
496495
% bootlm:test:8
497496
% Unbalanced three-way design (3x2x2). The data is from a study of the
498497
% effects of three different drugs, biofeedback and diet on patient blood
499498
% pressure, adapted* from Maxwell, Delaney and Kelly (2018): Ch 8, Table 12
500-
501499
drug = {'X' 'X' 'X' 'X' 'X' 'X' 'X' 'X' 'X' 'X' 'X' 'X' ...
502500
'X' 'X' 'X' 'X' 'X' 'X' 'X' 'X' 'X' 'X' 'X' 'X';
503501
'Y' 'Y' 'Y' 'Y' 'Y' 'Y' 'Y' 'Y' 'Y' 'Y' 'Y' 'Y' ...
@@ -764,39 +762,71 @@
764762
pval7 = randtest2 (X, Y, false, [], @(A, B) log (var (A) ./ var (B)), 1);
765763

766764
% bootridge:test:1
765+
% Basic functionality: univariate, intercept auto-add, field shapes
767766
m = 30;
768767
x = linspace (-1, 1, m).';
769-
X = x;
770-
randn (123);
768+
X = x; % No intercept provided
769+
randn ('seed', 123);
771770
y = 1.0 + 0.8 * x + 0.1 * randn (m,1);
772771
S = bootridge (y, X, [], 200, 0.05, [], 1.1, 777);
773-
% bootridge:test:2
772+
% Check expected fields and sizes
773+
assert (isfield (S, 'coefficient'));
774+
assert (~ isfield (S, 'estimate'));
775+
assert (size (S.coefficient, 2) == 1);
776+
assert (size (S.coefficient, 1) == 2); % intercept + slope
777+
assert (isfinite (S.lambda) && (S.lambda > 0));
778+
assert (isfinite (S.df_lambda) && (S.df_lambda > 0) && ...
779+
(S.df_lambda <= m));
780+
assert (all (S.CI_lower(:) <= S.coefficient(:) + eps));
781+
assert (all (S.CI_upper(:) + eps >= S.coefficient(:)));
782+
assert (isfinite (S.Sigma_Y_hat) && (S.Sigma_Y_hat > 0));
783+
assert (iscell (S.Sigma_Beta) && (numel (S.Sigma_Beta) == 1));
784+
assert (all (size (S.Sigma_Beta{1}) == [2, 2]));
785+
assert (S.nboot == 200);
786+
assert (S.Deff == 1.1);
787+
% Hypothesis matrix L: return linear estimate instead of coefficients
774788
m = 28;
775789
x = linspace (-1.5, 1.5, m).';
776-
X = [ones(m,1), x];
777-
rng('default');
790+
X = [ones(m,1), x]; % Explicit intercept is first column
791+
randn ('seed', 123);
778792
y = 3.0 + 0.4 * x + 0.15 * randn (m,1);
793+
% Contrast to extract only the slope (second coefficient)
779794
L = [0; 1];
780795
S = bootridge (y, X, [], 100, 0.10, L, 1, 99);
781-
% bootridge:test:3
796+
assert (~ isfield (S, 'coefficient'));
797+
assert (isfield (S, 'estimate'));
798+
assert (all (size (S.estimate) == [1, 1]));
799+
assert (all (size (S.CI_lower) == [1, 1]));
800+
assert (all (size (S.CI_upper) == [1, 1]));
801+
assert (all (size (S.BF10 ) == [1, 1]));
802+
assert (iscell (S.prior) && all (size (S.prior) == [1, 1]));
803+
% Categorical predictor supplied via CATEGOR (no scaling)
782804
m = 36;
805+
% Two-level factor coded as centered +/-0.5 (column 2), plus a continuous
783806
g = repmat ([ -0.5; 0.5 ], 18, 1);
784807
x = linspace (-2, 2, m).';
785808
X = [ones(m,1), g, x];
786809
beta = [1.0; 0.7; -0.2];
787-
rng('default');
810+
randn ('seed', 123);
788811
y = X * beta + 0.25 * randn (m, 1);
789-
categor = 2;
812+
categor = 2; % column 2 is categorical (excludes intercept)
790813
S = bootridge (y, X, categor, 100, 0.05, [], 1, 2024);
791-
% bootridge:test:4
814+
assert (isfield (S, 'coefficient'));
815+
assert (size (S.coefficient, 1) == 3);
816+
assert (isfinite (S.lambda) && (S.lambda > 0));
817+
% Check CI bracketing for all coefficients
818+
assert (all (S.CI_lower(:) <= S.coefficient(:) + eps));
819+
assert (all (S.CI_upper(:) + eps >= S.coefficient(:)));
820+
% Multivariate outcomes and Deff scaling: Sigma_Y_hat should scale by Deff
792821
m = 32;
793822
x = linspace (-1, 1, m).';
794823
X = [ones(m,1), x];
795824
B = [2.0, -1.0; 0.5, 0.8];
796-
rng('default');
825+
randn ('seed', 123);
797826
Y = X * B + 0.2 * randn (m, 2);
798827
S1 = bootridge (Y, X, [], 100, 0.10, [], 1, 42);
799828
S2 = bootridge (Y, X, [], 100, 0.10, [], 2, 42);
829+
assert (all (size (S1.Sigma_Y_hat) == [2, 2]));
800830

801831
% credint:test:1
802832
heights = [183, 192, 182, 183, 177, 185, 188, 188, 182, 185].';

0 commit comments

Comments
 (0)