Metadata-Version: 2.1
Name: dno
Version: 0.2.3
Summary: Dynamic Neural Organism (DNO): A self-evolving, growing, and pruning neural network framework.
Home-page: https://github.com/yourusername/dno
Author: Uğurhan Çolak
Author-email: ugurhancolak5544@gmail.com
License: UNKNOWN
Platform: UNKNOWN
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: torch (>=1.9.0)
Requires-Dist: numpy

# DNO: Dynamic Neural Organism 🧬

[![PyPI version](https://badge.fury.io/py/dno.svg)](https://badge.fury.io/py/dno)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

**DNO** (Dynamic Neural Organism) is a PyTorch-based framework for creating biological neural networks that **grow**, **think**, and **evolve** at runtime.

Unlike static deep learning models (like Transformers or CNNs) which are "architectural statues", a DNO is a living organism. It starts small (as a single seed cortex), physically grows new neural pathways when confused, and prunes away useless connections when they are no longer needed.

> "Don't just train a model. Raise an organism."

---

## 🌟 Core Concepts: Biology Meets AI

DNO introduces several biological mechanisms into the deep learning workflow:

### 1. Neurogenesis (Mitosis) 📈
Traditional models have a fixed capacity. If the problem is too hard, they fail.
DNO monitors its own **Entropy** (state of confusion).
- If the organism is consistently "confused" (High Entropy) by incoming data, it triggers **Mitosis**.
- It interacts with the optimizer to clone its most active functional units (layers).
- It adds microscopic noise (mutation) to the clone to encourage specialization.
- The result: The model **physically grows larger** to accommodate the difficulty of the task.

### 2. Natural Selection (Apoptosis) ✂️
Growth without check is cancer. DNO implements **Apoptosis** (Programmed Cell Death).
- The `SurvivalEngine` tracks the **Utility Score** of every neuron group.
- Utility is calculated based on "Information Gain" (KL-Divergence between input and output).
- If a layer is just passing data through without adding value (Identity mapping), it starves.
- Eventually, efficient sub-structures emerge while useless ones die off.

### 3. Training Phases: Life Stages ⏳
DNO models go through distinct life stages, controlled by the `training_phase` config:

#### Phase 1: `scratch` (Infancy)
- **Goal**: Build a strong foundation.
- **Mechanism**: Growth is **LOCKED**. The model behaves like a standard static network.
- **Focus**: Train the "Seed Cortex" (the core brain) to understand basic patterns.
- **Logic**: A baby shouldn't try to grow complex specialized organs before it can digest basic food. All data is treated as "Familiar" (CPT).

#### Phase 2: `adaptive` (Adulthood)
- **Goal**: Specialization and Adaptation.
- **Mechanism**: Growth is **UNLOCKED**.
- **Focus**: The model detects "Novelty".
    - **Familiar Data (CPT)**: The core brain handles it. Specialized lobes are frozen to save energy.
    - **Novel Data (SFT)**: The core brain is frozen. A new "Expert Lobe" is grown or activated to handle this specific new type of difficulty.
- **Logic**: This enables **Continual Learning** without Catastrophic Forgetting.

---

## 📦 Installation

```bash
pip install dno
```

---

## 🚀 Usage Guide

### 1. The "Hello World" of Life
Create a brain, give it a DNA configuration, and process data.

```python
import torch
import torch.nn as nn
from dno.core.organism import OrganismManager, BaseEvolvableModule
from dno.core.network import DynamicNetwork
from dno.config import DnoConfig
from dno.utils.dashboard import print_organism_status

# 1. DNA Configuration
# training_phase='scratch': Start as a fixed seed (recommended for first epoch)
config = DnoConfig(
    training_phase='scratch', 
    entropy_threshold=0.6, 
    d_model=128
)

# 2. Birth (Initialize Manager & Body)
manager = OrganismManager()
network = DynamicNetwork(manager, config)

# 3. Seed Layer (The first neuron block - The Core)
seed_layer = nn.Sequential(
    nn.Linear(128, 128),
    nn.ReLU(),
    nn.Linear(128, 128)
)
# Wrap it in a biological shell
seed = BaseEvolvableModule(seed_layer)
seed.dynamic_id = "seed_cortex"
seed.set_specialty("general") # Mark as General Purpose Core

network.add_layer(seed)

# 4. Live (Forward Pass)
input_data = torch.randn(1, 128)
output = network(input_data)

print(f"Output shape: {output.shape}")
print_organism_status(manager)
```

### 2. Evolving (Adaptive Phase)
After pre-training (Phase 1), switch to Adaptive Mode to allow the model to grow specialized experts.

```python
from dno.core.growth import GrowthEngine
import torch.optim as optim

# Switch to Adulthood
network.config.training_phase = 'adaptive'

optimizer = optim.SGD(network.parameters(), lr=0.01)
growth_engine = GrowthEngine(network, config)

# ... inside your training loop ...
outputs = network(inputs)
loss = criterion(outputs, targets)

# 1. Update Biology (Entropy tracking)
# network._detect_novelty is called automatically in forward()

# 2. Check for Growth
# If model is confused (High Entropy) -> Mitosis
is_triggered, reason = growth_engine.check_growth_trigger(entropy_history, step)

if is_triggered:
    print(f"🌟 Epiphany! Growing new expert due to: {reason}")
    # Clone the seed cortex to create a new 'Expert Lobe'
    growth_engine.mitosis(
        parent_uuid="seed_cortex", 
        optimizer=optimizer, 
        specialty_tag="expert_coding" # Label the new organ
    )

loss.backward()
optimizer.step()
```

### 3. Saving & Loading (Fluid Serialization)
DNO models cannot be saved with just `torch.save()` because their architecture changes appropriately. Use `.dno` format.

```python
# Save the entire organism (Topology + Weights + Config + History)
network.save_dno("my_brain.dno")

# Resurrect it exactly as it was
new_network = DynamicNetwork.load_dno("my_brain.dno", module_factory=lambda t: nn.Linear(128, 128))
```

---

## 🔧 Advanced Configuration (`DnoConfig`)

| Parameter | Default | Description |
|---|---|---|
| `training_phase` | `'scratch'` | `'scratch'` (Fixed topology) or `'adaptive'` (Dynamic growth). |
| `entropy_threshold` | `0.6` | How confused the model needs to be to trigger growth (0.0-1.0). |
| `evolution_cooldown_steps` | `100` | Minimum steps between growth events to prevent explosion. |
| `pruning_decay_constant` | `0.001` | How fast unused neurons die off. |
| `max_param_count` | `1B` | Hard limit on organism size to prevent OOM. |

---

## 🤝 Contributing
DNO is an open-source experiment in Artificial Life.
- **Found a bug?** Open an issue.
- **Have an idea for a new organ?** Submit a PR.

## 📜 License
MIT License. **Go build something alive.**


