""" Module 05: Progressive Integration Tests Tests that Module 05 (Dense/Networks) works correctly AND that the entire foundation stack works. DEPENDENCY CHAIN: 01_setup → 02_tensor → 03_activations → 04_layers → 05_dense This is the FOUNDATION MILESTONE - everything should work together for neural networks! """ import numpy as np import sys from pathlib import Path # Add project root to path sys.path.insert(0, str(Path(__file__).parent.parent.parent)) class TestEntireFoundationStack: """Test that the complete foundation stack (01→05) works together.""" def test_setup_foundation_intact(self): """Verify Module 01 (Setup) foundation is solid.""" # Environment assert sys.version_info >= (3, 8), "Foundation broken: Python version" # Project structure project_root = Path(__file__).parent.parent.parent assert (project_root / "modules").exists(), "Foundation broken: Module structure" # Dependencies import numpy as np assert np.__version__ is not None, "Foundation broken: Numpy" def test_tensor_foundation_intact(self): """Verify Module 02 (Tensor) foundation is solid.""" try: from tinytorch.core.tensor import Tensor # Basic tensor functionality t = Tensor([1, 2, 3]) assert t.shape == (3,), "Foundation broken: Tensor creation" # Multi-dimensional tensors t2 = Tensor(np.random.randn(4, 5)) assert t2.shape == (4, 5), "Foundation broken: Multi-dim tensors" except ImportError: assert True, "Tensor foundation not implemented yet" def test_activation_foundation_intact(self): """Verify Module 03 (Activations) foundation is solid.""" try: from tinytorch.core.activations import ReLU, Sigmoid from tinytorch.core.tensor import Tensor relu = ReLU() sigmoid = Sigmoid() x = Tensor(np.array([-1, 0, 1])) # Activations should work with tensors h = relu(x) y = sigmoid(h) assert h.shape == x.shape, "Foundation broken: ReLU" assert y.shape == x.shape, "Foundation broken: Sigmoid" except ImportError: assert True, "Activation foundation not implemented yet" def test_layer_foundation_intact(self): """Verify Module 04 (Layers) foundation is solid.""" try: from tinytorch.core.layers import Layer # Layer base class should exist layer = Layer() assert hasattr(layer, 'forward'), "Foundation broken: Layer interface" assert callable(layer), "Foundation broken: Layer callable" except ImportError: assert True, "Layer foundation not implemented yet" class TestDenseNetworkCapability: """Test that Module 05 enables full neural network capability.""" def test_dense_layer_creation(self): """Test Dense layer works with the foundation.""" try: from tinytorch.core.layers import Dense from tinytorch.core.tensor import Tensor # Create Dense layer layer = Dense(10, 5) # Should have proper weights and bias assert hasattr(layer, 'weights'), "Dense broken: No weights" assert layer.weights.shape == (10, 5), "Dense broken: Wrong weight shape" # Should work with tensor input x = Tensor(np.random.randn(32, 10)) output = layer(x) assert output.shape == (32, 5), "Dense broken: Wrong output shape" except ImportError: assert True, "Dense layer not implemented yet" def test_multi_layer_network(self): """Test building multi-layer networks.""" try: from tinytorch.core.layers import Dense from tinytorch.core.activations import ReLU, Sigmoid from tinytorch.core.tensor import Tensor # Build 3-layer network for XOR hidden = Dense(2, 4, use_bias=True) output = Dense(4, 1, use_bias=True) relu = ReLU() sigmoid = Sigmoid() # XOR inputs X = Tensor(np.array([[0, 0], [0, 1], [1, 0], [1, 1]], dtype=np.float32)) # Forward pass through complete network h = hidden(X) # Dense transformation h_act = relu(h) # Non-linear activation out = output(h_act) # Output transformation predictions = sigmoid(out) # Output activation assert predictions.shape == (4, 1), "Multi-layer network broken" assert np.all(predictions.data >= 0), "Network output invalid" assert np.all(predictions.data <= 1), "Network output invalid" except ImportError: assert True, "Multi-layer networks not ready yet" class TestXORProblemSolution: """Test that the foundation can solve the XOR problem.""" def test_xor_network_architecture(self): """Test XOR network architecture is possible.""" try: from tinytorch.core.layers import Dense from tinytorch.core.activations import ReLU, Sigmoid from tinytorch.core.tensor import Tensor # XOR problem setup X = Tensor(np.array([[0, 0], [0, 1], [1, 0], [1, 1]], dtype=np.float32)) y_target = np.array([[0], [1], [1], [0]], dtype=np.float32) # Network: 2 -> 4 -> 1 (sufficient for XOR) hidden = Dense(2, 4, use_bias=True) output = Dense(4, 1, use_bias=True) relu = ReLU() sigmoid = Sigmoid() # Forward pass h = hidden(X) h_relu = relu(h) out = output(h_relu) predictions = sigmoid(out) # Network should produce valid outputs assert predictions.shape == (4, 1), "XOR network architecture broken" # Test network capacity (parameter count) hidden_params = 2 * 4 + 4 # weights + bias output_params = 4 * 1 + 1 # weights + bias total_params = hidden_params + output_params # XOR requires at least 9 parameters theoretically assert total_params >= 9, "XOR network has insufficient capacity" except ImportError: assert True, "XOR network not ready yet" def test_nonlinear_problem_solvability(self): """Test that non-linear problems are now solvable.""" try: from tinytorch.core.layers import Dense from tinytorch.core.activations import ReLU from tinytorch.core.tensor import Tensor # Create network that can solve non-linear problems layer1 = Dense(2, 10) relu = ReLU() layer2 = Dense(10, 1) # Test various non-linear patterns patterns = [ np.array([[0, 0], [0, 1], [1, 0], [1, 1]]), # XOR pattern np.array([[1, 1], [1, 0], [0, 1], [0, 0]]), # Inverse XOR ] for pattern in patterns: X = Tensor(pattern.astype(np.float32)) # Network should handle any pattern h = layer1(X) h_nonlinear = relu(h) output = layer2(h_nonlinear) assert output.shape[0] == 4, "Pattern processing broken" except ImportError: assert True, "Non-linear problem solving not ready yet" class TestFoundationMilestoneReadiness: """Test that we're ready for Foundation Milestone achievements.""" def test_mnist_mlp_architecture_possible(self): """Test we can build MNIST MLP architecture.""" try: from tinytorch.core.layers import Dense from tinytorch.core.activations import ReLU, Softmax from tinytorch.core.tensor import Tensor # MNIST MLP: 784 -> 128 -> 64 -> 10 layer1 = Dense(784, 128) layer2 = Dense(128, 64) layer3 = Dense(64, 10) relu = ReLU() softmax = Softmax() # Simulated MNIST batch x = Tensor(np.random.randn(32, 784)) # 32 images, flattened # Forward pass through MLP h1 = relu(layer1(x)) # 32 x 128 h2 = relu(layer2(h1)) # 32 x 64 logits = layer3(h2) # 32 x 10 probs = softmax(logits) # 32 x 10 assert probs.shape == (32, 10), "MNIST MLP architecture broken" # Softmax should sum to 1 across classes prob_sums = np.sum(probs.data, axis=1) assert np.allclose(prob_sums, 1.0), "Softmax probabilities broken" except ImportError: assert True, "MNIST MLP not ready yet" def test_classification_capability(self): """Test basic classification capability.""" try: from tinytorch.core.layers import Dense from tinytorch.core.activations import ReLU, Softmax from tinytorch.core.tensor import Tensor # Simple classifier: features -> hidden -> classes feature_layer = Dense(20, 10) classifier = Dense(10, 3) # 3 classes relu = ReLU() softmax = Softmax() # Batch of features features = Tensor(np.random.randn(16, 20)) # Classification pipeline h = relu(feature_layer(features)) logits = classifier(h) class_probs = softmax(logits) # Should produce valid class probabilities assert class_probs.shape == (16, 3), "Classification shape broken" assert np.all(class_probs.data >= 0), "Negative probabilities" assert np.allclose(np.sum(class_probs.data, axis=1), 1.0), "Probabilities don't sum to 1" except ImportError: assert True, "Classification capability not ready yet" class TestCompleteStackValidation: """Validate the complete foundation stack works end-to-end.""" def test_end_to_end_neural_network(self): """Test complete neural network from scratch.""" try: from tinytorch.core.tensor import Tensor from tinytorch.core.layers import Dense from tinytorch.core.activations import ReLU, Sigmoid # End-to-end test: Build and run a complete neural network # 1. Data (from setup/tensor foundation) np.random.seed(42) # Reproducible X = Tensor(np.random.randn(10, 5)) # 2. Network architecture (from layers foundation) layer1 = Dense(5, 8) layer2 = Dense(8, 3) layer3 = Dense(3, 1) # 3. Activations (from activation foundation) relu = ReLU() sigmoid = Sigmoid() # 4. Forward pass (everything working together) h1 = relu(layer1(X)) # 10 x 8 h2 = relu(layer2(h1)) # 10 x 3 output = sigmoid(layer3(h2)) # 10 x 1 # 5. Validation assert output.shape == (10, 1), "End-to-end network broken" assert np.all(output.data >= 0), "Network output invalid" assert np.all(output.data <= 1), "Network output invalid" # 6. Network should be trainable (parameters exist) assert hasattr(layer1, 'weights'), "Layer 1 not trainable" assert hasattr(layer2, 'weights'), "Layer 2 not trainable" assert hasattr(layer3, 'weights'), "Layer 3 not trainable" except ImportError: assert True, "End-to-end neural network not ready yet" def test_foundation_stability_under_load(self): """Test foundation remains stable under computational load.""" try: from tinytorch.core.tensor import Tensor from tinytorch.core.layers import Dense from tinytorch.core.activations import ReLU # Stress test: Large network layer1 = Dense(100, 200) layer2 = Dense(200, 100) layer3 = Dense(100, 10) relu = ReLU() # Large batch X = Tensor(np.random.randn(256, 100)) # Multiple forward passes for i in range(5): h1 = relu(layer1(X)) h2 = relu(layer2(h1)) output = layer3(h2) assert output.shape == (256, 10), f"Foundation unstable at iteration {i}" except ImportError: assert True, "Foundation stress testing not ready yet"