# AGENTS.md - Agentic Coding Guidelines ## Project Overview C-based neural network implementation from scratch for image classification on CIFAR-10 and MNIST datasets. ## Build Commands ### Compilation ```bash # Main classifier (MNIST) - compiles the single-classifier training program gcc -o classificatore_singolo_mnist classificatore_singolo.c -lm # XOR test/demo - simple test to verify neural network works gcc -o codice_ricordo codice_ricordo.c -lm # Visualizer (requires Allegro library) gcc -o visualizzatore visualizzatore.c -lalleg -lm # Older multi-layer implementation gcc -o rete_neurale rete_neurale.c -lm ``` ### Running Tests ```bash # Run XOR validation test (quick sanity check for neural network) ./codice_ricordo # Run full training loop with existing compiled binary ./classificatore_singolo_mnist # Automated training with pauses (prevents overheating) ./addestratore.sh # Memory leak detection (valgrind) valgrind --leak-check=full ./codice_ricordo ``` ### Running a Single Test ```bash # Compile and run XOR test (single test case) gcc -o codice_ricordo codice_ricordo.c -lm && ./codice_ricordo # Compile and run classifier with specific category gcc -o classificatore_singolo_mnist classificatore_singolo.c -lm && ./classificatore_singolo_mnist ``` ## Code Style Guidelines ### Language - Use **Italian** for comments and variable names (maintain consistency) - Use **English** for struct/type definitions and technical terms ### Formatting - Indent with 4 spaces (no tabs) - Opening braces on same line: `if (cond) {` - Always use braces for control structures, even single lines - Line length: ~80-100 characters preferred - One space after keywords (if, for, while, return) - No space between function name and opening parenthesis - Blank line between functions ### Naming Conventions - Functions: `snake_case` (e.g., `inizializza_rete_neurale`) - Structs: `PascalCase` (e.g., `ReteNeurale`) - Constants: `UPPER_SNAKE_CASE` (e.g., `EPOCHE`) - Global variables: file scope preferred - Types: use `typedef` for structs ### Types - Use `byte` (typedef for `unsigned char`) for values 0-255 - Use `double` for all floating-point calculations - Prefer explicit types over implicit conversions - Use `size_t` for sizes and indices where appropriate ### Imports - Standard library headers first (``, ``, ``, ``) - Project headers after (use `"quotes"`) - No include guards needed for header-only library - Group related includes together ### Memory Management - Always check `malloc` return values - Free memory in reverse allocation order - Use `perror()` for error messages before exiting - Avoid memory leaks in loops ### Error Handling - Check file operations with `if (!file)` pattern - Return `NULL` on failure for functions returning pointers - Exit with `EXIT_FAILURE` on unrecoverable errors - Validate function inputs at entry points ### Key Constants (from percettroni.h) - `LRE = 0.1` (learning rate - was 1.414, now 0.1) - `soglia_sigmoide = 0.5` (sigmoid threshold for binary classification) - `file_pesi = "rete_pesi.bin"` (model weights file) ### Dataset Configuration In `percettroni.h`, uncomment the desired dataset section: - XOR: `#include "xor_manager.h"` (for testing - currently active) - MNIST: Uncomment mnist includes and set file paths - CIFAR-10: Uncomment cifar-10 includes and file paths ## Testing No formal test framework. Use these approaches: 1. `codice_ricordo.c` - XOR validation (4 inputs, quick convergence test) 2. Visual inspection of weight outputs via `stampa_pesi_rete()` 3. Monitor epoch error rates in training output 4. Check for memory leaks with valgrind ## Project Structure - `percettroni.h` - Core neural network (header-only library with implementations) - `classificatore_singolo.c` - Single-category classifier main program - `codice_ricordo.c` - XOR test/demo - `xor_manager.h` - XOR dataset for testing - `mnist/mnist_manager.h` - MNIST dataset loader - `cifar-10/cifar10_manager.h` - CIFAR-10 dataset loader - `rete_pesi.bin` - Saved model weights - `addestratore.sh` - Training automation script ## Neural Network Architecture - Activation: sigmoid function - Training: backpropagation with gradient descent - Configurable: layer count and perceptrons per layer - Learning rate: controlled via `LRE` constant (default 0.1) - Binary threshold: 0.5 for classification decisions ## Development Workflow ### Adding a New Dataset 1. Create manager header (e.g., `custom_manager.h`) 2. Define `N_INPUTS` constant for input size 3. Implement `get_dataset()` returning `Dataset*` 4. Update `percettroni.h` includes and file paths ### Debugging Tips - Call `stampa_pesi_rete(rete)` to inspect weights - Reference `codice_ricordo.c` for minimal working example - Verify dataset loading before training loop - Check epoch timing to monitor training progress ### File I/O - Weights saved as binary in `rete_pesi.bin` - Use `salvaReteNeurale()` and `caricaReteNeurale()` for persistence - Dataset files must match expected binary format ## Performance Notes - Training is CPU-intensive (minutes per epoch expected) - Use `addestratore.sh` with sleep intervals to prevent overheating - Memory allocated dynamically based on network architecture - No GPU acceleration - pure CPU implementation ## Language Reference Technical terms (English): activation function, gradient descent, sigmoid, neural network, backpropagation Italian terms: pesi (weights), bias, livello (layer), percettrone (perceptron), addestramento (training), epoca (epoch), errore (error), classificazione (label/classification), previsione (prediction), istanza (instance)