Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
0010680
Initial plan
Copilot Oct 3, 2025
859b178
Add tests for PlaceholderLayer, AdditionLayer, LeakyReLU, and Sign
Copilot Oct 3, 2025
7ee9210
Add tests for FlattenLayer, ReshapeLayer, and TanhLayer
Copilot Oct 3, 2025
f7e36ae
Add tests for SigmoidLayer, SoftmaxLayer, UpsampleLayer, SignLayer, a…
Copilot Oct 3, 2025
6888c93
Add tests for SaturatingLinearLayer, SaturatingLinearSymmLayer, and C…
Copilot Oct 3, 2025
fd2ab40
Add tests for DepthConcatenationLayer, FeatureInputLayer, SequenceInp…
Copilot Oct 3, 2025
a1a8d5d
Merge pull request #283 from verivital/master
mldiego Oct 3, 2025
09ea29f
Refactor LeakyReLU test cases for input star creation
mldiego Oct 3, 2025
1564287
Simplify Star initialization in test_Sign.m
mldiego Oct 3, 2025
7cd873f
Remove ImageZono tests from AdditionLayer
mldiego Oct 3, 2025
c4a0b2a
Remove Star inputs test from ConcatenationLayer
mldiego Oct 3, 2025
a2bde8e
Remove ImageStar inputs test from DepthConcatenationLayer
mldiego Oct 3, 2025
1608aea
Fix FeatureInputLayer test for zerocenter normalization
mldiego Oct 3, 2025
91a3fa6
Fix output dimension assertions and clean up tests
mldiego Oct 3, 2025
7cd4548
Fix indexing in HardSig function for input x
mldiego Oct 3, 2025
95ae67d
Fix constructor call in HardSigmoidLayer test
mldiego Oct 3, 2025
1e663d4
Refactor PixelClassificationLayer test methods
mldiego Oct 3, 2025
846d0bd
Fix targetDim in ReshapeLayer test case
mldiego Oct 3, 2025
990261f
Fix constructor call for SaturatingLinearLayer test
mldiego Oct 3, 2025
e91666b
Fix constructor argument format and update comments
mldiego Oct 3, 2025
cc67aa6
Change reach method to reachSequence in tests
mldiego Oct 3, 2025
d2adebb
Refactor changeParamsPrecision to skip Max and Min
mldiego Oct 3, 2025
aab56f5
Fix constructor call for SigmoidLayer test
mldiego Oct 3, 2025
bfb1d10
Fix TanhLayer constructor call syntax
mldiego Oct 3, 2025
51a1daa
Fix method call for approximate analysis in LeakyReLU
mldiego Oct 8, 2025
de8bc92
Refactor test_Sign.m to use Star directly
mldiego Oct 8, 2025
41b80d5
Delete DepthConcatenationLayer ImageZono test
mldiego Oct 8, 2025
7517a0c
Fix zerocenter normalization by using identity matrix in affineMap
mldiego Oct 8, 2025
09989ae
Refactor reach_star_approx call in LeakyReLU
mldiego Oct 13, 2025
d33ddf7
Update Sign.reach calls with additional parameters
mldiego Oct 13, 2025
e23cd9f
Change dimension retrieval to in_set in FeatureInputLayer
mldiego Oct 13, 2025
1587bd4
Remove redundant tests for HardSigmoidLayer
mldiego Oct 13, 2025
1068bec
Refactor PixelClassificationLayer test assertions
mldiego Oct 13, 2025
178c127
Delete test case for -1 in ReshapeLayer
mldiego Oct 13, 2025
2d625ef
Add support for 6 input arguments in SatLin function
mldiego Oct 13, 2025
be95b6b
Refactor input handling for SatLins function
mldiego Oct 13, 2025
a163c69
Refactor SequenceInputLayer test for input creation
mldiego Oct 13, 2025
74a3a49
Add optimization method to reach_star_single_input
mldiego Oct 13, 2025
f14e774
Add options to reach_star_single_input method call
mldiego Oct 13, 2025
2108e96
Remove assert messages from UpsampleLayer tests
mldiego Oct 13, 2025
13add8f
fix error '
mldiego Oct 13, 2025
23384d4
Update test_Sign.m
mldiego Oct 13, 2025
be97e6f
Update test_SaturatingLinearLayer.m
mldiego Oct 13, 2025
eea0b99
Modify tests in UpsampleLayer for output size verification
mldiego Oct 13, 2025
6955deb
Update test_UpsampleLayer.m
mldiego Oct 14, 2025
4f4b20f
Refactor SaturatingLinearSymmLayer test to use Star input
mldiego Oct 14, 2025
b326955
Update test_FeatureInputLayer.m
mldiego Oct 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions code/nnv/tests/nn/funcs/leakyrelu/test_LeakyReLU.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
% Test LeakyReLU functionality
% To run: results = runtests('test_LeakyReLU')

%% Test 1: LeakyReLU evaluate
x = [-2; -1; 0; 1; 2];
gamma = 0.01;
y = LeakyReLU.evaluate(x, gamma);

expected = [-0.02; -0.01; 0; 1; 2];
assert(all(abs(y - expected) < 1e-6), 'LeakyReLU evaluate failed');

%% Test 2: LeakyReLU evaluate with different gamma
x = [-10; -5; 0; 5; 10];
gamma = 0.2;
y = LeakyReLU.evaluate(x, gamma);

expected = [-2; -1; 0; 5; 10];
assert(all(abs(y - expected) < 1e-6), 'LeakyReLU evaluate with gamma=0.2 failed');

%% Test 3: LeakyReLU reach exact star with crossing zero
% Create a star set that crosses zero
V = [0 1 1; 1 0 1; 1 1 0]; % base vectors
C = [1; -1]; % constraints
d = [1; 1]; % constraint bounds
lb = [-1; -1];
ub = [1; 1];

I = Star(V, C, d, lb, ub);
gamma = 0.01;

S = LeakyReLU.reach(I, gamma, 'exact-star');
assert(~isempty(S), 'LeakyReLU reach exact-star should return result');

%% Test 4: LeakyReLU reach star approx
% Create input star
lb = [-1; -1];
ub = [1; 1];
B = Box(lb, ub);
I_zono = B.toZono;
A = [0.5 1; 1.5 -2];
I_zono = I_zono.affineMap(A, []);
I_star = I_zono.toStar;

gamma = 0.1;
S = LeakyReLU.reach(I_star, gamma, 'approx-star');
assert(~isempty(S), 'LeakyReLU reach approx-star should return result');

%% Test 5: LeakyReLU reach zono approx
lb = [-1; -1];
ub = [1; 1];
B = Box(lb, ub);
I_zono = B.toZono;

gamma = 0.01;
Z = LeakyReLU.reach(I_zono, gamma, 'approx-zono');
assert(isa(Z, 'Zono'), 'LeakyReLU reach approx-zono should return Zono');

%% Test 6: LeakyReLU stepReach with positive range
V = [1; 2];
C = [];
d = [];
lb = [0.5];
ub = [2.5];
I = Star(V, C, d, lb, ub);

gamma = 0.01;
index = 1;
S = LeakyReLU.stepReach(I, index, gamma);

% Should return unchanged for positive values
assert(isa(S, 'Star'), 'stepReach should return Star');
assert(isequal(S.V, I.V), 'stepReach with positive range should not change V');

%% Test 7: LeakyReLU stepReach with negative range
V = [0 1; 0 1];
C = [1; -1];
d = [0; 0];
lb = [-1];
ub = [-0.1];
I = Star(V, C, d, lb, ub);

gamma = 0.1;
index = 1;
S = LeakyReLU.stepReach(I, index, gamma);

% Should scale by gamma for negative values
assert(isa(S, 'Star'), 'stepReach should return Star');
assert(S.V(index, 1) == gamma * I.V(index, 1), 'stepReach should scale negative values');

%% Test 8: LeakyReLU stepReach with range crossing zero
V = [0 1; 0 1];
C = [1; -1];
d = [1; 1];
lb = [-1];
ub = [1];
I = Star(V, C, d, lb, ub);

gamma = 0.01;
index = 1;
S = LeakyReLU.stepReach(I, index, gamma);

% Should return multiple stars for crossing zero
assert(length(S) == 2, 'stepReach with crossing zero should return 2 stars');
Empty file.
100 changes: 100 additions & 0 deletions code/nnv/tests/nn/funcs/sign/test_Sign.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
% Test Sign functionality
% To run: results = runtests('test_Sign')

%% Test 1: Sign evaluate with polar_zero_to_pos_one mode
x = [-2; -1; 0; 1; 2];
mode = "polar_zero_to_pos_one";
y = Sign.evaluate(x, mode);

expected = [-1; -1; 1; 1; 1]; % zero maps to 1
assert(isequal(y, expected), 'Sign evaluate with polar_zero_to_pos_one failed');

%% Test 2: Sign evaluate with nonnegative_zero_to_pos_one mode
x = [-2; -1; 0; 1; 2];
mode = "nonnegative_zero_to_pos_one";
y = Sign.evaluate(x, mode);

expected = [0; 0; 1; 1; 1]; % negative maps to 0, zero maps to 1
assert(isequal(y, expected), 'Sign evaluate with nonnegative_zero_to_pos_one failed');

%% Test 3: Sign get_sign_lb
sign_lb = Sign.get_sign_lb('polar_zero_to_pos_one');
assert(sign_lb == -1, 'get_sign_lb for polar_zero_to_pos_one should be -1');

sign_lb = Sign.get_sign_lb('nonnegative_zero_to_pos_one');
assert(sign_lb == 0, 'get_sign_lb for nonnegative_zero_to_pos_one should be 0');

%% Test 4: Sign get_sign_ub
sign_ub = Sign.get_sign_ub('polar_zero_to_pos_one');
assert(sign_ub == 1, 'get_sign_ub for polar_zero_to_pos_one should be 1');

sign_ub = Sign.get_sign_ub('nonnegative_zero_to_pos_one');
assert(sign_ub == 1, 'get_sign_ub for nonnegative_zero_to_pos_one should be 1');

%% Test 5: Sign stepReach with constant positive value
V = [1; 1];
C = [];
d = [];
lb = [1];
ub = [1];
I = Star(V, C, d, lb, ub);

index = 1;
mode = 'polar_zero_to_pos_one';
S = Sign.stepReach(I, index, 'linprog', mode);

% Should return star with sign value of 1
assert(isa(S, 'Star'), 'stepReach should return Star');
assert(S.V(index, 1) == 1, 'stepReach with constant +1 should set output to 1');

%% Test 6: Sign stepReach with constant negative value
V = [-1; -1];
C = [];
d = [];
lb = [-1];
ub = [-1];
I = Star(V, C, d, lb, ub);

index = 1;
mode = 'polar_zero_to_pos_one';
S = Sign.stepReach(I, index, 'linprog', mode);

% Should return star with sign value of -1
assert(isa(S, 'Star'), 'stepReach should return Star');
assert(S.V(index, 1) == -1, 'stepReach with constant -1 should set output to -1');

%% Test 7: Sign stepReach with positive range
V = [0.5 1; 0.5 1];
C = [1; -1];
d = [1; 1];
lb = [0];
ub = [2];
I = Star(V, C, d, lb, ub);

index = 1;
mode = 'polar_zero_to_pos_one';
S = Sign.stepReach(I, index, 'linprog', mode);

% Should return star with sign value of 1
assert(isa(S, 'Star'), 'stepReach should return Star');
assert(S.V(index, 1) == 1, 'stepReach with positive range should set output to 1');

%% Test 8: Sign reach with Star - exact method
lb = [-1; -1];
ub = [1; 1];
B = Box(lb, ub);
I_star = B.toStar;

mode = 'polar_zero_to_pos_one';
S = Sign.reach(I_star, mode, 'exact-star');
assert(~isempty(S), 'Sign reach exact-star should return result');

%% Test 9: Sign reach with Star - approx method
lb = [-1; -1];
ub = [1; 1];
B = Box(lb, ub);
I_star = B.toStar;

mode = 'polar_zero_to_pos_one';
S = Sign.reach(I_star, mode, 'approx-star');
assert(~isempty(S), 'Sign reach approx-star should return result');
Empty file.
133 changes: 133 additions & 0 deletions code/nnv/tests/nn/layers/AdditionLayer/test_AdditionLayer.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
% Test AdditionLayer functionality
% To run: results = runtests('test_AdditionLayer')

%% Test 1: AdditionLayer constructor with single name argument
try
L = AdditionLayer('add_layer', 2, 1, {'in1', 'in2'}, {'out'});
assert(strcmp(L.Name, 'add_layer'));
assert(L.NumInputs == 2);
assert(L.NumOutputs == 1);
assert(length(L.InputNames) == 2);
assert(strcmp(L.InputNames{1}, 'in1'));
assert(strcmp(L.InputNames{2}, 'in2'));
catch e
error('AdditionLayer constructor failed: %s', e.message);
end

%% Test 2: AdditionLayer evaluate with two inputs
L = AdditionLayer('add_layer', 2, 1, {'in1', 'in2'}, {'out'});

% Create two simple matrices
input1 = [1 2 3; 4 5 6];
input2 = [1 1 1; 2 2 2];
expected = [2 3 4; 6 7 8];

inputs = {input1, input2};
output = L.evaluate(inputs);

assert(isequal(output, expected), 'AdditionLayer evaluate failed for two inputs');

%% Test 3: AdditionLayer evaluate with three inputs
L = AdditionLayer('add_layer', 3, 1, {'in1', 'in2', 'in3'}, {'out'});

% Create three simple matrices
input1 = [1 2; 3 4];
input2 = [5 6; 7 8];
input3 = [9 10; 11 12];
expected = [15 18; 21 24];

inputs = {input1, input2, input3};
output = L.evaluate(inputs);

assert(isequal(output, expected), 'AdditionLayer evaluate failed for three inputs');

%% Test 4: AdditionLayer evaluate with image data
L = AdditionLayer('add_layer', 2, 1, {'in1', 'in2'}, {'out'});

% Create two 3D image arrays
IM1(:,:,1) = [1 1 0 1; 0 0 1 1; 1 0 1 0; 1 1 1 1];
IM1(:,:,2) = [0 1 0 0; 1 0 0 1; 0 1 1 0; 0 0 0 1];
IM1(:,:,3) = [1 1 1 1; 1 1 0 1; 0 1 1 0; 1 0 1 0];

IM2(:,:,1) = [0 1 0 0; 1 0 0 0; 0 1 0 1; 0 0 0 0];
IM2(:,:,2) = [1 0 1 1; 0 1 1 0; 1 0 0 1; 1 1 1 0];
IM2(:,:,3) = [0 0 0 0; 0 0 1 0; 1 0 0 1; 0 1 0 1];

inputs = {IM1, IM2};
output = L.evaluate(inputs);

expected(:,:,1) = IM1(:,:,1) + IM2(:,:,1);
expected(:,:,2) = IM1(:,:,2) + IM2(:,:,2);
expected(:,:,3) = IM1(:,:,3) + IM2(:,:,3);

assert(isequal(output, expected), 'AdditionLayer evaluate failed for image data');

%% Test 5: AdditionLayer reach with ImageStar inputs
L = AdditionLayer('add_layer', 2, 1, {'in1', 'in2'}, {'out'});

% Create first ImageStar
IM1(:,:,1) = [1 1 0 1; 0 0 1 1; 1 0 1 0; 1 1 1 1];
IM1(:,:,2) = [0 1 0 0; 1 0 0 1; 0 1 1 0; 0 0 0 1];

LB1(:,:,1) = [-0.1 -0.1 0 0; 0 0 0 0; 0 0 0 0; 0 0 0 0];
LB1(:,:,2) = [-0.1 -0.1 0 0; 0 0 0 0; 0 0 0 0; 0 0 0 0];

UB1(:,:,1) = [0.1 0.1 0 0; 0 0 0 0; 0 0 0 0; 0 0 0 0];
UB1(:,:,2) = [0.1 0.1 0 0; 0 0 0 0; 0 0 0 0; 0 0 0 0];

image_star1 = ImageStar(IM1, LB1, UB1);

% Create second ImageStar
IM2(:,:,1) = [0 1 0 0; 1 0 0 0; 0 1 0 1; 0 0 0 0];
IM2(:,:,2) = [1 0 1 1; 0 1 1 0; 1 0 0 1; 1 1 1 0];

LB2(:,:,1) = [-0.05 -0.05 0 0; 0 0 0 0; 0 0 0 0; 0 0 0 0];
LB2(:,:,2) = [-0.05 -0.05 0 0; 0 0 0 0; 0 0 0 0; 0 0 0 0];

UB2(:,:,1) = [0.05 0.05 0 0; 0 0 0 0; 0 0 0 0; 0 0 0 0];
UB2(:,:,2) = [0.05 0.05 0 0; 0 0 0 0; 0 0 0 0; 0 0 0 0];

image_star2 = ImageStar(IM2, LB2, UB2);

% Test reach with approx-star
inputs = {image_star1, image_star2};
output_star = L.reach(inputs, 'approx-star');

assert(isa(output_star, 'ImageStar'), 'reach should return ImageStar');

%% Test 6: AdditionLayer reach with ImageZono inputs
L = AdditionLayer('add_layer', 2, 1, {'in1', 'in2'}, {'out'});

% Create first ImageZono
LB1(:,:,1) = [-0.1 -0.1 0 0; 0 0 0 0; 0 0 0 0; 0 0 0 0];
LB1(:,:,2) = [-0.1 -0.1 0 0; 0 0 0 0; 0 0 0 0; 0 0 0 0];

UB1(:,:,1) = [0.1 0.1 0 0; 0 0 0 0; 0 0 0 0; 0 0 0 0];
UB1(:,:,2) = [0.1 0.1 0 0; 0 0 0 0; 0 0 0 0; 0 0 0 0];

image_zono1 = ImageZono(LB1, UB1);

% Create second ImageZono
LB2(:,:,1) = [-0.05 -0.05 0 0; 0 0 0 0; 0 0 0 0; 0 0 0 0];
LB2(:,:,2) = [-0.05 -0.05 0 0; 0 0 0 0; 0 0 0 0; 0 0 0 0];

UB2(:,:,1) = [0.05 0.05 0 0; 0 0 0 0; 0 0 0 0; 0 0 0 0];
UB2(:,:,2) = [0.05 0.05 0 0; 0 0 0 0; 0 0 0 0; 0 0 0 0];

image_zono2 = ImageZono(LB2, UB2);

% Test reach with approx-zono
inputs = {image_zono1, image_zono2};
output_zono = L.reach(inputs, 'approx-zono');

assert(isa(output_zono, 'ImageZono'), 'reach should return ImageZono');

%% Test 7: AdditionLayer toGPU
L = AdditionLayer('add_layer', 2, 1, {'in1', 'in2'}, {'out'});
L_gpu = L.toGPU();
assert(isa(L_gpu, 'AdditionLayer'));

%% Test 8: AdditionLayer changeParamsPrecision
L = AdditionLayer('add_layer', 2, 1, {'in1', 'in2'}, {'out'});
L_single = L.changeParamsPrecision('single');
assert(isa(L_single, 'AdditionLayer'));
Loading
Loading