Metadata-Version: 2.4
Name: addernet
Version: 1.4.6
Summary: Neural networks with zero multiplications at inference. AdderNet + HDC for embedded systems.
Author: AdderNet Team
License: Apache-2.0
Project-URL: Homepage, https://github.com/addernet/addernet
Project-URL: Repository, https://github.com/addernet/addernet
Keywords: machine-learning,neural-network,addernet,hyperdimensional-computing,embedded,no-fpu
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy
Requires-Dist: scikit-learn
Requires-Dist: scipy
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Dynamic: license-file

# AdderNet

[![PyPI version](https://img.shields.io/pypi/v/addernet.svg)](https://pypi.org/project/addernet/)
[![Python](https://img.shields.io/pypi/pyversions/addernet.svg)](https://pypi.org/project/addernet/)
[![License](https://img.shields.io/github/license/PedroHenriqueBatistaSilva/AdderNet.svg)](LICENSE)

Biblioteca de machine learning que **não usa multiplicação de ponto flutuante** na inferência. Zero.

> Benchmarks medidos em CPU x86-64 com backend **AVX2** e GPUs NVIDIA via **CUDA 2026**, Python 3.x, v1.4.5.

---

## O que é?

AdderNet substitui multiplicações por **lookups em tabela** (LUT) e operações de soma inteiras,
tornando a inferência viável em microcontroladores sem FPU (ESP32, STM32, RPi).

A biblioteca expõe quatro componentes principais:

| Classe | Descrição |
|---|---|
| `AdderNetLayer` | Rede de uma variável — LUT + soma, zero multiplicação |
| `AdderNetHDC` | Classificador multivariável — Hyperdimensional Computing (HDC) |
| `AdderCluster` | Ensemble de `AdderNetLayer` com estratégias de combinação |
| `AdderBoost` | Gradient Boosting com `AdderNetLayer` — inferência sem multiplicação |
| `AdderAttention` | Attention mechanism baseado em distância de Hamming — zero multiplicação |

---

## Novidades v1.4.5 🔇

### Controle de Logs (Verbose Mode)
- **`set_verbose(False)`**: Silencia todos os logs de detecção CUDA e build
- **Variável de ambiente**: `ADDERNET_VERBOSE=0` para controle sem alterar código
- Ideal para scripts automatizados, produção e notebooks limpos

### Novidades v1.4.1 🔧

### Correções Críticas
- **Buffer overflow corrigido**: `counts[base + bit]` agora com bounds check — prevenia segfault com `hv_dim` não-múltiplo de 64
- **`safe_aligned_alloc`**: Wrapper seguro previne NULL returns em `aligned_alloc` com sizes não-alinhados
- **CUDA 12.8 compatível**: atomic casts (`int16_t*→int*`, `uint64_t*→unsigned long long*`), sm_75 gencode para T4

### Organização
- Testes Python movidos para `tests/`
- Wheels offline movidos para `wheels/`
- `python/` duplicata removida

### Novidades v1.4.0 🚀

### CUDA 2026 — Modernização Completa
- **Kernel 2026 Ampere+**: Treinamento cooperativo com shared memory 100KB, warp-level primitives, e unified kernel (encode → Hamming → update em um único launch)
- **Kernel Selection Automático**: Detecta a GPU e seleciona o kernel otimizado (Ampere sm_80+ → Turing sm_70-75 → Legacy sm_61)
- **Unified Memory**: Zero-copy GPU memory para datasets pequenos (ativa com `ADDERNET_UNIFIED_MEMORY=1`)
- **CUDA Graphs**: Capture once, replay many (ativa com `ADDERNET_CUDA_GRAPHS=1`)
- **Persistent Kernel**: Elimina overhead de kernel launch (ativa com `ADDERNET_PERSISTENT_KERNEL=1`)

### AdderAttention — Attention Mechanism sem Multiplicação
- Mecanismo de atenção baseado em distância de Hamming
- Ideal para transformers-like architectures em embedded systems
- Sem operações de ponto flutuante

### Recursos Mantidos
- **HV_DIM Dinâmico**: Dimensionalidade hiperdimensional configurável em runtime (`512`, `1024`, `2048`, `4096`, etc)
- **Aceleração CUDA no Treinamento**: AdaptHD/RefineHD paralelo em GPU com `atomicAdd`
- **Aceleração CUDA na Inferência**: `predict_batch` via kernels CUDA dedicados
- **Compatibilidade e Fallback**: Fallback automático para CPU (AVX2/NEON/SCALAR) quando GPU não disponível

---

## Instalação

```bash
pip install addernet
```

Ou do código-fonte (para compilar com otimizações nativas e CUDA opcional):

```bash
git clone https://github.com/PedroHenriqueBatistaSilva/AdderNet.git
cd AdderNet
make all         # Compila binários da CPU
make cuda_native # Opcional: Compila o backend de GPU (requer nvcc)
pip install -e .
```

---

## Controle de Logs (Verbose)

Para silenciar os logs de detecção de CUDA e build (ideal para scripts e produção):

**Método 1 — Variável de ambiente (recomendado):**
```bash
ADDERNET_VERBOSE=0 python main.py
```

**Método 2 — No código (antes dos imports):**
```python
import addernet
addernet.set_verbose(False)

from addernet import AdderNetLayer
# Nenhum log será exibido
```

⚠️ **Importante**: `set_verbose(False)` deve ser chamado **antes** de importar `AdderNetLayer` ou `AdderNetHDC`, pois a detecção de CUDA ocorre durante o carregamento desses módulos.

## Uso — AdderNetLayer (uma variável)

```python
from addernet import AdderNetLayer

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

celsius    = [0, 10, 20, 25, 30, 37, 50, 80, 100]
fahrenheit = [32, 50, 68, 77, 86, 98.6, 122, 176, 212]

rede.train(celsius, fahrenheit)

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

### Previsão em lote (numpy)

```python
import numpy as np

entradas = np.linspace(-50, 200, 1_000_000, dtype=np.float64)
saidas = rede.predict_batch(entradas)   # ~178M pred/s com AVX2
```

---

## Uso — AdderNetHDC (Aceleração GPU e HDC Dinâmico)

```python
from addernet import AdderNetHDC
import numpy as np
from sklearn.datasets import load_iris
from sklearn.preprocessing import MinMaxScaler

iris = load_iris()
X = MinMaxScaler(feature_range=(0, 150)).fit_transform(iris.data)
y = iris.target

# HV_DIM dinâmico configurável (ex: 2048, 4096)
model = AdderNetHDC(
    n_vars=4, 
    n_classes=3, 
    table_size=256, 
    hv_dim=4096,              # <- Dimensionalidade configurável no runtime!
    use_gpu=True,             # <- Ativa inferência batch em CUDA
    use_gpu_training=True     # <- Ativa treinamento iterativo em CUDA
)

# Arrays numpy precisam ser "C Contiguous" 
X_c = np.ascontiguousarray(X, dtype=np.float64)
y_c = np.ascontiguousarray(y, dtype=np.int32)

# Treino single-pass (OnlineHD)
model.train(X_c, y_c)

# Retreino iterativo (AdaptHD) — massivamente paralelo na GPU
model.train(X_c, y_c, n_iter=20, lr=1.0)

# Inferência massiva e ultrarrápida via GPU
preds = model.predict_batch(X_c)

print(f"Acurácia: {model.accuracy(X_c, y_c)*100:.1f}%")
```

---

## Uso — AdderCluster (ensemble multi-nó)

```python
from addernet import AdderCluster
import numpy as np

cluster = AdderCluster(
    n_nodes=4,
    strategy='feature',    # 'random' | 'range' | 'feature' | 'boosting'
    combination='vote',    # 'vote' | 'mean' | 'stack'
    input_min=0,
    input_max=150,
)

cluster.fit(X, y)
preds = cluster.predict_batch(X)

cluster.info()
```

---

## Uso — AdderAttention (Attention sem Multiplicação)

```python
from addernet import AdderAttention
import numpy as np

# Attention mechanism baseado em distância de Hamming
# Ideal para embedded systems sem FPU
attn = AdderAttention(
    n_vars=4,
    n_heads=8,  # Número de heads de atenção
    hv_dim=2048  # Dimensionalidade dos hipervetores
)

# Query, Key, Value (em formato hypervector)
# Treinamento
attn.fit(X_train, y_train)

# Attention scores usando Hamming distance
scores = attn.attention(X_query, X_keys)

# Classificação com attention
prediction = attn.predict(X_test)
```

### Configurações Avançadas do CUDA 2026

```python
import os
os.environ['ADDERNET_UNIFIED_MEMORY'] = '1'   # Zero-copy GPU memory
os.environ['ADDERNET_CUDA_GRAPHS'] = '1'       # Capture/replay
os.environ['ADDERNET_PERSISTENT_KERNEL'] = '1' # Elimina kernel launch overhead
```

---

## Otimizações disponíveis

```python
from addernet import hdc_detect_backend

print(hdc_detect_backend())   # 'AVX2', 'NEON', ou 'SCALAR'

model.set_threads(4)      # multithreading CPU (AdderNetHDC)
model.warm_cache()        # pré-computar hipervectors
model.set_cache(False)    # desligar cache (hardware com pouca RAM)
```

---

## Limitações

- **AdderNetLayer**: apenas uma variável de entrada por camada
- **AdderNetHDC**: acurácia inferior a MLPs profundas em datasets complexos (troca por zero multiplicação)
- `hv_dim` muito pequeno (< 1000) pode colapsar a acurácia, use a Dimensionalidade Dinâmica para testar!

---

## Licença

[Apache 2.0](LICENSE) — © Pedro Henrique Batista Silva
