Metadata-Version: 2.4
Name: addernet
Version: 0.1.0
Summary: Neural network with zero multiplications at inference. AdderNet + Hyperdimensional Computing.
License: MIT
Project-URL: Homepage, https://github.com/addernet/addernet
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy
Dynamic: license-file

# AdderNet

Rede neural que **não usa multiplicação** na inferência. Zero.

```
Rede normal:   resultado = entrada * peso + bias    (mulsd + addsd)
AdderNet:      resultado = tabela[entrada + offset]  (1 acesso à memória)
```

## O que faz?

AdderNet aprende funções usando **apenas adição e subtração** durante o treinamento, e na hora de prever o resultado basta **ler uma posição da tabela** — nenhuma conta de verdade.

Funciona bem para funções de **uma variável**: converter Celsius em Fahrenheit, aprender `y = 3x + 7`, etc.

## Instalação

**Requisitos**: GCC, Python 3.8+, numpy

```bash
cd addernet_lib
make
```

Isso gera `libaddernet.so`.

## Uso (Python)

```python
from addernet import AdderNetLayer

# Criar a rede
rede = AdderNetLayer(size=256, bias=50, input_min=-50, input_max=200, lr=0.1)

# Dados de treino: Celsius -> Fahrenheit
celsius    = [0, 10, 20, 25, 30, 37, 50, 80, 100]
fahrenheit = [32, 50, 68, 77, 86, 98.6, 122, 176, 212]

# Treinar
rede.train(celsius, fahrenheit)

# Prever
print(rede.predict(37))   # 98.60
print(rede.predict(100))  # 212.00
```

### Salvar e carregar

```python
# Salvar modelo treinado
rede.save("meu_modelo.bin")

# Carregar depois
rede = AdderNetLayer.load("meu_modelo.bin")
print(rede.predict(37))  # 98.60
```

### Previsão em lote (numpy)

```python
import numpy as np

entradas = np.array([0, 25, 37, 100], dtype=np.float64)
saidas = rede.predict_batch(entradas)
# array([32.0, 77.0, 98.6, 212.0])
```

### Usando em C

```c
#include "addernet.h"

an_layer *rede = an_layer_create(256, 50, -50, 200, 0.1);

double inputs[]  = {0, 10, 25, 37, 100};
double targets[] = {32, 50, 77, 98.6, 212};
an_train(rede, inputs, targets, 5, 1000, 4000);

double resultado = an_predict(rede, 37.0);  // 98.60

an_save(rede, "modelo.bin");
an_layer_free(rede);
```

Compile com:
```bash
gcc -O3 -o meu_programa meu_programa.c -L. -laddernet -lm
```

## Performance

| Método | Velocidade | vs Python puro |
|---|---|---|
| Python AdderNet (dict) | ~31K pred/s | 1x |
| C AdderNet (uma por uma via ctypes) | ~1.3M pred/s | ~42x |
| C AdderNet (lote numpy) | ~247M pred/s | ~8000x |

Para melhor performance em Python, use `predict_batch()` com arrays numpy.

## Exemplos prontos

```bash
cd addernet_lib

# Converter Celsius -> Fahrenheit
python3 examples/celsius_fahrenheit.py

# Aprender funções de adição
python3 examples/addition.py

# Benchmark de performance
python3 examples/benchmark.py
```

## Limitações

- Funciona para funções de **uma variável** (entrada inteira -> saída double)
- A entrada é truncada para int antes de indexar a tabela
- Para valores fora do range de treino, a precisão diminui (extrapolação linear)
- Não substitui redes neurais convencionais para problemas complexos (visão, linguagem, etc.)

## Como funciona?

1. **Treino**: Para cada amostra, testa se `peso + lr` ou `peso - lr` reduz o erro. Aplica a melhor direção.
2. **Expansão**: Interpola entre os pontos de treino para gerar dados densos, e extrapola além das bordas usando a inclinação dos dois pontos mais próximos.
3. **Inferência**: A tabela já tem o resultado final. É só acessar `tabela[(entrada + offset) & máscara]` — uma leitura de memória, zero aritmética.

## Arquivos

```
addernet_lib/
├── addernet.h          Cabeçalho da API
├── addernet.c          Implementação em C
├── addernet.py         Bindings Python (ctypes)
├── Makefile            Compilação
├── test_main.c         Teste em C
└── examples/
    ├── celsius_fahrenheit.py
    ├── addition.py
    └── benchmark.py
```
