Upload folder using huggingface_hub
Browse files- .gitignore +78 -0
- README.md +117 -0
- algebraic_neural_network.py +542 -0
- demo.py +73 -0
- examples/geometric_algebra_network.py +461 -0
- examples/group_theory_network.py +381 -0
- examples/polynomial_network.py +289 -0
- examples/uncomputable_networks.py +218 -0
- test_comprehensive.py +327 -0
- theory/algebraic_foundations.md +162 -0
- theory/examples.md +219 -0
- theory/uncomputable_networks.md +141 -0
.gitignore
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Python
|
| 2 |
+
__pycache__/
|
| 3 |
+
*.py[cod]
|
| 4 |
+
*$py.class
|
| 5 |
+
*.so
|
| 6 |
+
.Python
|
| 7 |
+
build/
|
| 8 |
+
develop-eggs/
|
| 9 |
+
dist/
|
| 10 |
+
downloads/
|
| 11 |
+
eggs/
|
| 12 |
+
.eggs/
|
| 13 |
+
lib/
|
| 14 |
+
lib64/
|
| 15 |
+
parts/
|
| 16 |
+
sdist/
|
| 17 |
+
var/
|
| 18 |
+
wheels/
|
| 19 |
+
*.egg-info/
|
| 20 |
+
.installed.cfg
|
| 21 |
+
*.egg
|
| 22 |
+
MANIFEST
|
| 23 |
+
|
| 24 |
+
# PyInstaller
|
| 25 |
+
*.manifest
|
| 26 |
+
*.spec
|
| 27 |
+
|
| 28 |
+
# Installer logs
|
| 29 |
+
pip-log.txt
|
| 30 |
+
pip-delete-this-directory.txt
|
| 31 |
+
|
| 32 |
+
# Unit test / coverage reports
|
| 33 |
+
htmlcov/
|
| 34 |
+
.tox/
|
| 35 |
+
.coverage
|
| 36 |
+
.coverage.*
|
| 37 |
+
.cache
|
| 38 |
+
nosetests.xml
|
| 39 |
+
coverage.xml
|
| 40 |
+
*.cover
|
| 41 |
+
.hypothesis/
|
| 42 |
+
.pytest_cache/
|
| 43 |
+
|
| 44 |
+
# Jupyter Notebook
|
| 45 |
+
.ipynb_checkpoints
|
| 46 |
+
|
| 47 |
+
# pyenv
|
| 48 |
+
.python-version
|
| 49 |
+
|
| 50 |
+
# Environments
|
| 51 |
+
.env
|
| 52 |
+
.venv
|
| 53 |
+
env/
|
| 54 |
+
venv/
|
| 55 |
+
ENV/
|
| 56 |
+
env.bak/
|
| 57 |
+
venv.bak/
|
| 58 |
+
|
| 59 |
+
# IDE
|
| 60 |
+
.vscode/
|
| 61 |
+
.idea/
|
| 62 |
+
*.swp
|
| 63 |
+
*.swo
|
| 64 |
+
*~
|
| 65 |
+
|
| 66 |
+
# OS
|
| 67 |
+
.DS_Store
|
| 68 |
+
.DS_Store?
|
| 69 |
+
._*
|
| 70 |
+
.Spotlight-V100
|
| 71 |
+
.Trashes
|
| 72 |
+
ehthumbs.db
|
| 73 |
+
Thumbs.db
|
| 74 |
+
|
| 75 |
+
# Temporary files
|
| 76 |
+
*.tmp
|
| 77 |
+
*.temp
|
| 78 |
+
/tmp/
|
README.md
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Not-trained-Neural-Networks-Notes
|
| 2 |
+
|
| 3 |
+
A comprehensive collection of notes, implementations, and examples of neural networks that don't rely on traditional gradient-based training methods.
|
| 4 |
+
|
| 5 |
+
## Contents
|
| 6 |
+
|
| 7 |
+
- [Algebraic Neural Networks](#algebraic-neural-networks)
|
| 8 |
+
- [Uncomputable Neural Networks](#uncomputable-neural-networks)
|
| 9 |
+
- [Theory and Mathematical Foundations](#theory-and-mathematical-foundations)
|
| 10 |
+
- [Implementations](#implementations)
|
| 11 |
+
- [Examples and Use Cases](#examples-and-use-cases)
|
| 12 |
+
|
| 13 |
+
## Algebraic Neural Networks
|
| 14 |
+
|
| 15 |
+
Algebraic Neural Networks (ANNs) represent a paradigm shift from traditional neural networks by utilizing algebraic structures and operations instead of gradient-based optimization. These networks leverage:
|
| 16 |
+
|
| 17 |
+
- **Algebraic Group Theory**: Using group operations for network transformations
|
| 18 |
+
- **Polynomial Algebras**: Networks based on polynomial computations
|
| 19 |
+
- **Geometric Algebra**: Incorporating geometric algebraic structures
|
| 20 |
+
- **Fixed Algebraic Transformations**: Pre-defined algebraic operations
|
| 21 |
+
|
| 22 |
+
### Key Features
|
| 23 |
+
|
| 24 |
+
1. **No Training Required**: Networks are constructed using algebraic principles
|
| 25 |
+
2. **Deterministic Behavior**: Outputs are fully determined by algebraic rules
|
| 26 |
+
3. **Mathematical Rigor**: Based on well-established algebraic foundations
|
| 27 |
+
4. **Interpretability**: Clear mathematical interpretation of operations
|
| 28 |
+
|
| 29 |
+
## Uncomputable Neural Networks
|
| 30 |
+
|
| 31 |
+
Uncomputable Neural Networks extend the paradigm of non-trained networks by incorporating theoretical concepts from computability theory. These networks explore computational boundaries by simulating uncomputable functions and operations:
|
| 32 |
+
|
| 33 |
+
- **Halting Oracle Layers**: Simulate access to halting oracles for program termination decisions
|
| 34 |
+
- **Kolmogorov Complexity Layers**: Approximate uncomputable complexity measures using compression heuristics
|
| 35 |
+
- **Busy Beaver Layers**: Utilize the uncomputable Busy Beaver function values and approximations
|
| 36 |
+
- **Non-Recursive Layers**: Operate on computably enumerable but non-computable sets
|
| 37 |
+
|
| 38 |
+
### Key Features
|
| 39 |
+
|
| 40 |
+
1. **Theoretical Foundations**: Based on computability theory and hypercomputation concepts
|
| 41 |
+
2. **Bounded Approximations**: Practical implementations of theoretically uncomputable functions
|
| 42 |
+
3. **Deterministic Simulation**: Consistent behavior through fixed-seed randomness and heuristics
|
| 43 |
+
4. **Educational Value**: Demonstrates limits and possibilities of computation
|
| 44 |
+
|
| 45 |
+
## Getting Started
|
| 46 |
+
|
| 47 |
+
```bash
|
| 48 |
+
git clone https://github.com/ewdlop/Not-trained-Neural-Networks-Notes.git
|
| 49 |
+
cd Not-trained-Neural-Networks-Notes
|
| 50 |
+
|
| 51 |
+
# Install dependencies
|
| 52 |
+
pip install numpy matplotlib
|
| 53 |
+
|
| 54 |
+
# Quick demo
|
| 55 |
+
python demo.py
|
| 56 |
+
|
| 57 |
+
# Run main implementation
|
| 58 |
+
python algebraic_neural_network.py
|
| 59 |
+
|
| 60 |
+
# Run comprehensive tests
|
| 61 |
+
python test_comprehensive.py
|
| 62 |
+
```
|
| 63 |
+
|
| 64 |
+
### Quick Demo
|
| 65 |
+
```bash
|
| 66 |
+
python demo.py
|
| 67 |
+
```
|
| 68 |
+
This runs a simple demonstration showing how algebraic neural networks process data without any training.
|
| 69 |
+
|
| 70 |
+
### Examples
|
| 71 |
+
```bash
|
| 72 |
+
# Polynomial-based networks
|
| 73 |
+
python examples/polynomial_network.py
|
| 74 |
+
|
| 75 |
+
# Group theory networks
|
| 76 |
+
python examples/group_theory_network.py
|
| 77 |
+
|
| 78 |
+
# Geometric algebra networks
|
| 79 |
+
python examples/geometric_algebra_network.py
|
| 80 |
+
|
| 81 |
+
# Uncomputable neural networks
|
| 82 |
+
python examples/uncomputable_networks.py
|
| 83 |
+
```
|
| 84 |
+
|
| 85 |
+
## Structure
|
| 86 |
+
|
| 87 |
+
```
|
| 88 |
+
├── README.md # This file
|
| 89 |
+
├── demo.py # Quick demonstration script
|
| 90 |
+
├── algebraic_neural_network.py # Main implementation
|
| 91 |
+
├── test_comprehensive.py # Test suite
|
| 92 |
+
├── theory/ # Theoretical background
|
| 93 |
+
│ ├── algebraic_foundations.md # Mathematical foundations
|
| 94 |
+
│ ├── uncomputable_networks.md # Uncomputable neural networks theory
|
| 95 |
+
│ └── examples.md # Worked examples
|
| 96 |
+
└── examples/ # Practical examples
|
| 97 |
+
├── polynomial_network.py # Polynomial-based network
|
| 98 |
+
├── group_theory_network.py # Group theory implementation
|
| 99 |
+
├── geometric_algebra_network.py # Geometric algebra network
|
| 100 |
+
└── uncomputable_networks.py # Uncomputable neural networks
|
| 101 |
+
```
|
| 102 |
+
|
| 103 |
+
## Testing
|
| 104 |
+
|
| 105 |
+
Run the comprehensive test suite to verify all components:
|
| 106 |
+
|
| 107 |
+
```bash
|
| 108 |
+
python test_comprehensive.py
|
| 109 |
+
```
|
| 110 |
+
|
| 111 |
+
This tests:
|
| 112 |
+
- Basic functionality of all layer types (algebraic and uncomputable)
|
| 113 |
+
- Network composition and data flow
|
| 114 |
+
- Deterministic behavior (same input → same output)
|
| 115 |
+
- Mathematical properties of algebraic operations
|
| 116 |
+
- Uncomputable layer approximations and bounds
|
| 117 |
+
- Edge cases and boundary conditions
|
algebraic_neural_network.py
ADDED
|
@@ -0,0 +1,542 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Algebraic Neural Network Implementation
|
| 3 |
+
|
| 4 |
+
This module implements various types of algebraic neural networks that don't require
|
| 5 |
+
traditional gradient-based training. Instead, they use algebraic structures and
|
| 6 |
+
operations to process information.
|
| 7 |
+
|
| 8 |
+
Author: Algebraic Neural Network Research
|
| 9 |
+
"""
|
| 10 |
+
|
| 11 |
+
import numpy as np
|
| 12 |
+
from typing import List, Callable, Union
|
| 13 |
+
import math
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
class AlgebraicLayer:
|
| 17 |
+
"""
|
| 18 |
+
Base class for algebraic layers that use mathematical operations
|
| 19 |
+
instead of learned weights.
|
| 20 |
+
"""
|
| 21 |
+
|
| 22 |
+
def __init__(self, input_size: int, output_size: int, operation: str = "polynomial"):
|
| 23 |
+
self.input_size = input_size
|
| 24 |
+
self.output_size = output_size
|
| 25 |
+
self.operation = operation
|
| 26 |
+
|
| 27 |
+
def forward(self, x: np.ndarray) -> np.ndarray:
|
| 28 |
+
"""Apply algebraic transformation to input."""
|
| 29 |
+
raise NotImplementedError("Subclasses must implement forward method")
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
class PolynomialLayer(AlgebraicLayer):
|
| 33 |
+
"""
|
| 34 |
+
Layer that applies polynomial transformations without learned weights.
|
| 35 |
+
Uses fixed polynomial coefficients based on algebraic principles.
|
| 36 |
+
"""
|
| 37 |
+
|
| 38 |
+
def __init__(self, input_size: int, output_size: int, degree: int = 2):
|
| 39 |
+
super().__init__(input_size, output_size, "polynomial")
|
| 40 |
+
self.degree = degree
|
| 41 |
+
# Generate coefficients using algebraic sequences (e.g., Fibonacci-based)
|
| 42 |
+
self.coefficients = self._generate_algebraic_coefficients()
|
| 43 |
+
|
| 44 |
+
def _generate_algebraic_coefficients(self) -> np.ndarray:
|
| 45 |
+
"""Generate polynomial coefficients using algebraic sequences."""
|
| 46 |
+
# Use golden ratio and algebraic numbers for coefficients
|
| 47 |
+
phi = (1 + math.sqrt(5)) / 2 # Golden ratio
|
| 48 |
+
coeffs = []
|
| 49 |
+
|
| 50 |
+
for i in range(self.output_size):
|
| 51 |
+
for j in range(self.input_size):
|
| 52 |
+
# Generate coefficients using algebraic properties
|
| 53 |
+
coeff = (phi ** (i + 1)) / (j + 1) if j < self.input_size else 1.0
|
| 54 |
+
coeffs.append(coeff)
|
| 55 |
+
|
| 56 |
+
return np.array(coeffs).reshape(self.output_size, self.input_size)
|
| 57 |
+
|
| 58 |
+
def forward(self, x: np.ndarray) -> np.ndarray:
|
| 59 |
+
"""Apply polynomial transformation."""
|
| 60 |
+
if x.ndim == 1:
|
| 61 |
+
x = x.reshape(1, -1)
|
| 62 |
+
|
| 63 |
+
result = np.zeros((x.shape[0], self.output_size))
|
| 64 |
+
|
| 65 |
+
for i in range(self.output_size):
|
| 66 |
+
# Apply polynomial of specified degree
|
| 67 |
+
poly_result = np.zeros(x.shape[0])
|
| 68 |
+
for degree in range(1, self.degree + 1):
|
| 69 |
+
poly_term = np.power(x, degree) @ self.coefficients[i]
|
| 70 |
+
poly_result += poly_term / math.factorial(degree)
|
| 71 |
+
result[:, i] = poly_result
|
| 72 |
+
|
| 73 |
+
return result
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
class GroupTheoryLayer(AlgebraicLayer):
|
| 77 |
+
"""
|
| 78 |
+
Layer based on group theory operations, particularly using cyclic groups
|
| 79 |
+
and group actions for transformations.
|
| 80 |
+
"""
|
| 81 |
+
|
| 82 |
+
def __init__(self, input_size: int, output_size: int, group_order: int = 8):
|
| 83 |
+
super().__init__(input_size, output_size, "group_theory")
|
| 84 |
+
self.group_order = group_order
|
| 85 |
+
# Generate group elements (rotations in this case)
|
| 86 |
+
self.group_elements = self._generate_cyclic_group()
|
| 87 |
+
|
| 88 |
+
def _generate_cyclic_group(self) -> List[np.ndarray]:
|
| 89 |
+
"""Generate cyclic group elements as rotation matrices."""
|
| 90 |
+
elements = []
|
| 91 |
+
for k in range(self.group_order):
|
| 92 |
+
angle = 2 * math.pi * k / self.group_order
|
| 93 |
+
# For 2D case, use rotation matrices
|
| 94 |
+
if self.input_size == 2:
|
| 95 |
+
rotation = np.array([
|
| 96 |
+
[math.cos(angle), -math.sin(angle)],
|
| 97 |
+
[math.sin(angle), math.cos(angle)]
|
| 98 |
+
])
|
| 99 |
+
elements.append(rotation)
|
| 100 |
+
else:
|
| 101 |
+
# For higher dimensions, use generalized rotations
|
| 102 |
+
rotation = np.eye(self.input_size)
|
| 103 |
+
if self.input_size >= 2:
|
| 104 |
+
rotation[0, 0] = math.cos(angle)
|
| 105 |
+
rotation[0, 1] = -math.sin(angle)
|
| 106 |
+
rotation[1, 0] = math.sin(angle)
|
| 107 |
+
rotation[1, 1] = math.cos(angle)
|
| 108 |
+
elements.append(rotation)
|
| 109 |
+
return elements
|
| 110 |
+
|
| 111 |
+
def forward(self, x: np.ndarray) -> np.ndarray:
|
| 112 |
+
"""Apply group action to input."""
|
| 113 |
+
if x.ndim == 1:
|
| 114 |
+
x = x.reshape(1, -1)
|
| 115 |
+
|
| 116 |
+
results = []
|
| 117 |
+
for i, group_element in enumerate(self.group_elements[:self.output_size]):
|
| 118 |
+
if x.shape[1] == group_element.shape[0]:
|
| 119 |
+
transformed = x @ group_element.T
|
| 120 |
+
# Take the norm as a scalar output
|
| 121 |
+
result = np.linalg.norm(transformed, axis=1)
|
| 122 |
+
else:
|
| 123 |
+
# Fallback for size mismatch
|
| 124 |
+
result = np.sum(x * (i + 1), axis=1)
|
| 125 |
+
results.append(result)
|
| 126 |
+
|
| 127 |
+
return np.column_stack(results)
|
| 128 |
+
|
| 129 |
+
|
| 130 |
+
class GeometricAlgebraLayer(AlgebraicLayer):
|
| 131 |
+
"""
|
| 132 |
+
Layer using geometric algebra (Clifford algebra) operations.
|
| 133 |
+
Implements basic geometric product and algebraic operations.
|
| 134 |
+
"""
|
| 135 |
+
|
| 136 |
+
def __init__(self, input_size: int, output_size: int):
|
| 137 |
+
super().__init__(input_size, output_size, "geometric_algebra")
|
| 138 |
+
# Initialize basis vectors for geometric algebra
|
| 139 |
+
self.basis_vectors = self._generate_basis_vectors()
|
| 140 |
+
|
| 141 |
+
def _generate_basis_vectors(self) -> List[np.ndarray]:
|
| 142 |
+
"""Generate basis vectors for geometric algebra."""
|
| 143 |
+
basis = []
|
| 144 |
+
# Scalar basis
|
| 145 |
+
basis.append(np.ones(self.input_size))
|
| 146 |
+
|
| 147 |
+
# Vector basis
|
| 148 |
+
for i in range(self.input_size):
|
| 149 |
+
e_i = np.zeros(self.input_size)
|
| 150 |
+
e_i[i] = 1.0
|
| 151 |
+
basis.append(e_i)
|
| 152 |
+
|
| 153 |
+
# Bivector basis (for pairs)
|
| 154 |
+
for i in range(self.input_size):
|
| 155 |
+
for j in range(i + 1, self.input_size):
|
| 156 |
+
e_ij = np.zeros(self.input_size)
|
| 157 |
+
e_ij[i] = 1.0
|
| 158 |
+
e_ij[j] = 1.0
|
| 159 |
+
basis.append(e_ij)
|
| 160 |
+
|
| 161 |
+
return basis[:self.output_size]
|
| 162 |
+
|
| 163 |
+
def geometric_product(self, a: np.ndarray, b: np.ndarray) -> float:
|
| 164 |
+
"""Compute geometric product of two vectors."""
|
| 165 |
+
# Simplified geometric product: dot product + outer product norm
|
| 166 |
+
dot_prod = np.dot(a, b)
|
| 167 |
+
# Approximate outer product contribution
|
| 168 |
+
outer_norm = np.linalg.norm(np.outer(a, b))
|
| 169 |
+
return dot_prod + outer_norm
|
| 170 |
+
|
| 171 |
+
def forward(self, x: np.ndarray) -> np.ndarray:
|
| 172 |
+
"""Apply geometric algebra transformations."""
|
| 173 |
+
if x.ndim == 1:
|
| 174 |
+
x = x.reshape(1, -1)
|
| 175 |
+
|
| 176 |
+
results = []
|
| 177 |
+
for basis_vector in self.basis_vectors:
|
| 178 |
+
# Compute geometric product with basis vector
|
| 179 |
+
result = []
|
| 180 |
+
for sample in x:
|
| 181 |
+
gp = self.geometric_product(sample, basis_vector)
|
| 182 |
+
result.append(gp)
|
| 183 |
+
results.append(np.array(result))
|
| 184 |
+
|
| 185 |
+
return np.column_stack(results)
|
| 186 |
+
|
| 187 |
+
|
| 188 |
+
class HaltingOracleLayer(AlgebraicLayer):
|
| 189 |
+
"""
|
| 190 |
+
Layer that simulates a halting oracle for specific computational patterns.
|
| 191 |
+
Uses heuristics and bounded computation to approximate uncomputable halting decisions.
|
| 192 |
+
"""
|
| 193 |
+
|
| 194 |
+
def __init__(self, input_size: int, output_size: int, max_iterations: int = 1000):
|
| 195 |
+
super().__init__(input_size, output_size, "halting_oracle")
|
| 196 |
+
self.max_iterations = max_iterations
|
| 197 |
+
# Fixed seed for deterministic "non-algorithmic" behavior
|
| 198 |
+
self.oracle_seed = 42
|
| 199 |
+
|
| 200 |
+
def _simulate_halting_oracle(self, program_encoding: float) -> float:
|
| 201 |
+
"""Simulate halting oracle decision for encoded program."""
|
| 202 |
+
# Use fixed-seed randomness to simulate oracle behavior
|
| 203 |
+
np.random.seed(int(abs(program_encoding * 1000)) % 2**31)
|
| 204 |
+
|
| 205 |
+
# Simple heuristic: programs with certain patterns are more likely to halt
|
| 206 |
+
# This is a deterministic approximation of the uncomputable halting problem
|
| 207 |
+
complexity_factor = abs(program_encoding) % 1.0
|
| 208 |
+
|
| 209 |
+
if complexity_factor < 0.1: # Very simple programs likely halt
|
| 210 |
+
return 1.0
|
| 211 |
+
elif complexity_factor > 0.9: # Very complex programs might not halt
|
| 212 |
+
return 0.1
|
| 213 |
+
else:
|
| 214 |
+
# Use bounded computation simulation
|
| 215 |
+
iterations = int(complexity_factor * self.max_iterations)
|
| 216 |
+
# Simulate bounded program execution
|
| 217 |
+
state = program_encoding
|
| 218 |
+
for i in range(iterations):
|
| 219 |
+
state = (state * 1.618 + 0.786) % 1.0 # Simple state evolution
|
| 220 |
+
if abs(state - 0.5) < 0.01: # "Halting condition"
|
| 221 |
+
return 1.0
|
| 222 |
+
return 0.3 # Uncertain/timeout case
|
| 223 |
+
|
| 224 |
+
def forward(self, x: np.ndarray) -> np.ndarray:
|
| 225 |
+
"""Apply halting oracle simulation to inputs."""
|
| 226 |
+
if x.ndim == 1:
|
| 227 |
+
x = x.reshape(1, -1)
|
| 228 |
+
|
| 229 |
+
results = []
|
| 230 |
+
for i in range(self.output_size):
|
| 231 |
+
oracle_results = []
|
| 232 |
+
for sample in x:
|
| 233 |
+
# Encode input as "program" for halting oracle
|
| 234 |
+
program_encoding = np.sum(sample * (i + 1)) / len(sample)
|
| 235 |
+
halting_prob = self._simulate_halting_oracle(program_encoding)
|
| 236 |
+
oracle_results.append(halting_prob)
|
| 237 |
+
results.append(np.array(oracle_results))
|
| 238 |
+
|
| 239 |
+
return np.column_stack(results)
|
| 240 |
+
|
| 241 |
+
|
| 242 |
+
class KolmogorovComplexityLayer(AlgebraicLayer):
|
| 243 |
+
"""
|
| 244 |
+
Layer that approximates Kolmogorov complexity using compression-based heuristics.
|
| 245 |
+
Provides bounded approximations of the uncomputable Kolmogorov complexity function.
|
| 246 |
+
"""
|
| 247 |
+
|
| 248 |
+
def __init__(self, input_size: int, output_size: int, precision: int = 8):
|
| 249 |
+
super().__init__(input_size, output_size, "kolmogorov_complexity")
|
| 250 |
+
self.precision = precision
|
| 251 |
+
|
| 252 |
+
def _approximate_kolmogorov_complexity(self, data: np.ndarray) -> float:
|
| 253 |
+
"""Approximate Kolmogorov complexity using compressibility heuristics."""
|
| 254 |
+
# Convert to discrete representation
|
| 255 |
+
discretized = np.round(data * (2**self.precision)).astype(int)
|
| 256 |
+
|
| 257 |
+
# Simple compression simulation using pattern detection
|
| 258 |
+
data_str = ''.join(map(str, discretized))
|
| 259 |
+
|
| 260 |
+
# Count repetitive patterns (simple compression heuristic)
|
| 261 |
+
unique_chars = len(set(data_str))
|
| 262 |
+
total_chars = len(data_str)
|
| 263 |
+
|
| 264 |
+
# Estimate complexity based on entropy-like measure
|
| 265 |
+
if total_chars == 0:
|
| 266 |
+
return 0.0
|
| 267 |
+
|
| 268 |
+
# Normalized complexity estimate
|
| 269 |
+
entropy_approx = (unique_chars / total_chars) * np.log2(unique_chars + 1)
|
| 270 |
+
|
| 271 |
+
# Add pattern complexity (longer patterns suggest lower complexity)
|
| 272 |
+
pattern_factor = 1.0
|
| 273 |
+
for pattern_len in range(2, min(5, len(data_str))):
|
| 274 |
+
patterns = set()
|
| 275 |
+
for i in range(len(data_str) - pattern_len + 1):
|
| 276 |
+
patterns.add(data_str[i:i+pattern_len])
|
| 277 |
+
if len(patterns) < len(data_str) - pattern_len + 1:
|
| 278 |
+
pattern_factor *= 0.8 # Reduce complexity for repeated patterns
|
| 279 |
+
|
| 280 |
+
return entropy_approx * pattern_factor
|
| 281 |
+
|
| 282 |
+
def forward(self, x: np.ndarray) -> np.ndarray:
|
| 283 |
+
"""Compute approximate Kolmogorov complexity for inputs."""
|
| 284 |
+
if x.ndim == 1:
|
| 285 |
+
x = x.reshape(1, -1)
|
| 286 |
+
|
| 287 |
+
results = []
|
| 288 |
+
for i in range(self.output_size):
|
| 289 |
+
complexity_results = []
|
| 290 |
+
for sample in x:
|
| 291 |
+
# Different projections for different outputs
|
| 292 |
+
projection = sample * (i + 1) / (self.output_size)
|
| 293 |
+
complexity = self._approximate_kolmogorov_complexity(projection)
|
| 294 |
+
complexity_results.append(complexity)
|
| 295 |
+
results.append(np.array(complexity_results))
|
| 296 |
+
|
| 297 |
+
return np.column_stack(results)
|
| 298 |
+
|
| 299 |
+
|
| 300 |
+
class BusyBeaverLayer(AlgebraicLayer):
|
| 301 |
+
"""
|
| 302 |
+
Layer using Busy Beaver function values and approximations.
|
| 303 |
+
The Busy Beaver function is uncomputable for general n, but known for small values.
|
| 304 |
+
"""
|
| 305 |
+
|
| 306 |
+
def __init__(self, input_size: int, output_size: int):
|
| 307 |
+
super().__init__(input_size, output_size, "busy_beaver")
|
| 308 |
+
# Known Busy Beaver values: BB(1)=1, BB(2)=4, BB(3)=6, BB(4)=13, BB(5)≥4098
|
| 309 |
+
self.known_bb_values = {1: 1, 2: 4, 3: 6, 4: 13, 5: 4098}
|
| 310 |
+
|
| 311 |
+
def _busy_beaver_approximation(self, n: int) -> float:
|
| 312 |
+
"""Get Busy Beaver value or approximation."""
|
| 313 |
+
if n <= 0:
|
| 314 |
+
return 0.0
|
| 315 |
+
elif n in self.known_bb_values:
|
| 316 |
+
return float(self.known_bb_values[n])
|
| 317 |
+
elif n <= 5:
|
| 318 |
+
return float(self.known_bb_values[5])
|
| 319 |
+
else:
|
| 320 |
+
# For n > 5, use exponential approximation
|
| 321 |
+
# This is a heuristic since BB(n) grows faster than any computable function
|
| 322 |
+
return self.known_bb_values[5] * (2.0 ** (n - 5))
|
| 323 |
+
|
| 324 |
+
def forward(self, x: np.ndarray) -> np.ndarray:
|
| 325 |
+
"""Apply Busy Beaver function to transformed inputs."""
|
| 326 |
+
if x.ndim == 1:
|
| 327 |
+
x = x.reshape(1, -1)
|
| 328 |
+
|
| 329 |
+
results = []
|
| 330 |
+
for i in range(self.output_size):
|
| 331 |
+
bb_results = []
|
| 332 |
+
for sample in x:
|
| 333 |
+
# Transform input to discrete parameter for Busy Beaver function
|
| 334 |
+
# Use log scale to keep values reasonable
|
| 335 |
+
param = max(1, int(abs(np.sum(sample) * (i + 1)) % 10) + 1)
|
| 336 |
+
bb_value = self._busy_beaver_approximation(param)
|
| 337 |
+
# Normalize to prevent overflow
|
| 338 |
+
normalized_bb = np.log1p(bb_value)
|
| 339 |
+
bb_results.append(normalized_bb)
|
| 340 |
+
results.append(np.array(bb_results))
|
| 341 |
+
|
| 342 |
+
return np.column_stack(results)
|
| 343 |
+
|
| 344 |
+
|
| 345 |
+
class NonRecursiveLayer(AlgebraicLayer):
|
| 346 |
+
"""
|
| 347 |
+
Layer based on non-recursive sets and functions.
|
| 348 |
+
Simulates operations on computably enumerable but non-computable sets.
|
| 349 |
+
"""
|
| 350 |
+
|
| 351 |
+
def __init__(self, input_size: int, output_size: int, enumeration_bound: int = 1000):
|
| 352 |
+
super().__init__(input_size, output_size, "non_recursive")
|
| 353 |
+
self.enumeration_bound = enumeration_bound
|
| 354 |
+
# Simulate a c.e. non-recursive set using a bounded enumeration
|
| 355 |
+
self.ce_set = self._generate_ce_set()
|
| 356 |
+
|
| 357 |
+
def _generate_ce_set(self) -> set:
|
| 358 |
+
"""Generate a computably enumerable set simulation."""
|
| 359 |
+
ce_set = set()
|
| 360 |
+
# Simulate enumeration of a c.e. set (like the set of Gödel numbers of theorems)
|
| 361 |
+
for i in range(self.enumeration_bound):
|
| 362 |
+
# Simple enumeration rule (this is computable, but simulates c.e. behavior)
|
| 363 |
+
if self._enumeration_rule(i):
|
| 364 |
+
ce_set.add(i)
|
| 365 |
+
return ce_set
|
| 366 |
+
|
| 367 |
+
def _enumeration_rule(self, n: int) -> bool:
|
| 368 |
+
"""Rule for enumerating elements (simulates theorem enumeration)."""
|
| 369 |
+
# Simple mathematical property that creates interesting patterns
|
| 370 |
+
# Simulates: numbers that can be expressed as sum of two squares
|
| 371 |
+
for i in range(int(np.sqrt(n)) + 1):
|
| 372 |
+
remainder = n - i*i
|
| 373 |
+
if remainder >= 0 and int(np.sqrt(remainder))**2 == remainder:
|
| 374 |
+
return True
|
| 375 |
+
return False
|
| 376 |
+
|
| 377 |
+
def _membership_oracle(self, value: float) -> float:
|
| 378 |
+
"""Simulate membership oracle for non-recursive set."""
|
| 379 |
+
# Convert continuous value to discrete for set membership
|
| 380 |
+
discrete_val = int(abs(value * 1000)) % self.enumeration_bound
|
| 381 |
+
|
| 382 |
+
if discrete_val in self.ce_set:
|
| 383 |
+
return 1.0
|
| 384 |
+
else:
|
| 385 |
+
# For values not yet enumerated, return uncertainty
|
| 386 |
+
# This simulates the non-recursive nature
|
| 387 |
+
return 0.5
|
| 388 |
+
|
| 389 |
+
def forward(self, x: np.ndarray) -> np.ndarray:
|
| 390 |
+
"""Apply non-recursive set operations to inputs."""
|
| 391 |
+
if x.ndim == 1:
|
| 392 |
+
x = x.reshape(1, -1)
|
| 393 |
+
|
| 394 |
+
results = []
|
| 395 |
+
for i in range(self.output_size):
|
| 396 |
+
membership_results = []
|
| 397 |
+
for sample in x:
|
| 398 |
+
# Transform input for membership testing
|
| 399 |
+
test_value = np.sum(sample * np.arange(len(sample))) * (i + 1)
|
| 400 |
+
membership = self._membership_oracle(test_value)
|
| 401 |
+
membership_results.append(membership)
|
| 402 |
+
results.append(np.array(membership_results))
|
| 403 |
+
|
| 404 |
+
return np.column_stack(results)
|
| 405 |
+
|
| 406 |
+
|
| 407 |
+
class AlgebraicNeuralNetwork:
|
| 408 |
+
"""
|
| 409 |
+
Main class for Algebraic Neural Networks that combines different
|
| 410 |
+
algebraic layers to create a complete network.
|
| 411 |
+
"""
|
| 412 |
+
|
| 413 |
+
def __init__(self):
|
| 414 |
+
self.layers = []
|
| 415 |
+
|
| 416 |
+
def add_layer(self, layer: AlgebraicLayer):
|
| 417 |
+
"""Add an algebraic layer to the network."""
|
| 418 |
+
self.layers.append(layer)
|
| 419 |
+
|
| 420 |
+
def forward(self, x: np.ndarray) -> np.ndarray:
|
| 421 |
+
"""Forward pass through all algebraic layers."""
|
| 422 |
+
current_input = x
|
| 423 |
+
for layer in self.layers:
|
| 424 |
+
current_input = layer.forward(current_input)
|
| 425 |
+
return current_input
|
| 426 |
+
|
| 427 |
+
def predict(self, x: np.ndarray) -> np.ndarray:
|
| 428 |
+
"""Alias for forward pass."""
|
| 429 |
+
return self.forward(x)
|
| 430 |
+
|
| 431 |
+
|
| 432 |
+
def create_sample_network() -> AlgebraicNeuralNetwork:
|
| 433 |
+
"""Create a sample algebraic neural network for demonstration."""
|
| 434 |
+
network = AlgebraicNeuralNetwork()
|
| 435 |
+
|
| 436 |
+
# Add different types of algebraic layers
|
| 437 |
+
network.add_layer(PolynomialLayer(4, 6, degree=2))
|
| 438 |
+
network.add_layer(GroupTheoryLayer(6, 4, group_order=8))
|
| 439 |
+
network.add_layer(GeometricAlgebraLayer(4, 2))
|
| 440 |
+
|
| 441 |
+
return network
|
| 442 |
+
|
| 443 |
+
|
| 444 |
+
def create_uncomputable_network() -> AlgebraicNeuralNetwork:
|
| 445 |
+
"""Create a sample network with uncomputable layers for demonstration."""
|
| 446 |
+
network = AlgebraicNeuralNetwork()
|
| 447 |
+
|
| 448 |
+
# Add uncomputable layers
|
| 449 |
+
network.add_layer(HaltingOracleLayer(4, 5, max_iterations=500))
|
| 450 |
+
network.add_layer(KolmogorovComplexityLayer(5, 4, precision=6))
|
| 451 |
+
network.add_layer(BusyBeaverLayer(4, 3))
|
| 452 |
+
network.add_layer(NonRecursiveLayer(3, 2, enumeration_bound=500))
|
| 453 |
+
|
| 454 |
+
return network
|
| 455 |
+
|
| 456 |
+
|
| 457 |
+
def demo_algebraic_neural_network():
|
| 458 |
+
"""Demonstrate the algebraic neural network with sample data."""
|
| 459 |
+
print("=== Algebraic Neural Network Demo ===\n")
|
| 460 |
+
|
| 461 |
+
# Create sample network
|
| 462 |
+
network = create_sample_network()
|
| 463 |
+
|
| 464 |
+
# Generate sample input data
|
| 465 |
+
np.random.seed(42)
|
| 466 |
+
sample_input = np.random.randn(5, 4) # 5 samples, 4 features each
|
| 467 |
+
|
| 468 |
+
print("Input data shape:", sample_input.shape)
|
| 469 |
+
print("Input data:\n", sample_input)
|
| 470 |
+
|
| 471 |
+
# Run prediction
|
| 472 |
+
output = network.predict(sample_input)
|
| 473 |
+
|
| 474 |
+
print("\nOutput data shape:", output.shape)
|
| 475 |
+
print("Output data:\n", output)
|
| 476 |
+
|
| 477 |
+
# Demonstrate individual layers
|
| 478 |
+
print("\n=== Individual Layer Demonstrations ===\n")
|
| 479 |
+
|
| 480 |
+
# Polynomial Layer
|
| 481 |
+
poly_layer = PolynomialLayer(4, 3, degree=2)
|
| 482 |
+
poly_output = poly_layer.forward(sample_input[0])
|
| 483 |
+
print("Polynomial Layer Output:", poly_output)
|
| 484 |
+
|
| 485 |
+
# Group Theory Layer
|
| 486 |
+
group_layer = GroupTheoryLayer(4, 3, group_order=6)
|
| 487 |
+
group_output = group_layer.forward(sample_input[0])
|
| 488 |
+
print("Group Theory Layer Output:", group_output)
|
| 489 |
+
|
| 490 |
+
# Geometric Algebra Layer
|
| 491 |
+
geo_layer = GeometricAlgebraLayer(4, 3)
|
| 492 |
+
geo_output = geo_layer.forward(sample_input[0])
|
| 493 |
+
print("Geometric Algebra Layer Output:", geo_output)
|
| 494 |
+
|
| 495 |
+
|
| 496 |
+
def demo_uncomputable_neural_network():
|
| 497 |
+
"""Demonstrate the uncomputable neural network with sample data."""
|
| 498 |
+
print("\n=== Uncomputable Neural Network Demo ===\n")
|
| 499 |
+
|
| 500 |
+
# Create uncomputable network
|
| 501 |
+
network = create_uncomputable_network()
|
| 502 |
+
|
| 503 |
+
# Generate sample input data
|
| 504 |
+
np.random.seed(42)
|
| 505 |
+
sample_input = np.random.randn(3, 4) # 3 samples, 4 features each
|
| 506 |
+
|
| 507 |
+
print("Input data shape:", sample_input.shape)
|
| 508 |
+
print("Input data:\n", sample_input)
|
| 509 |
+
|
| 510 |
+
# Run prediction
|
| 511 |
+
output = network.predict(sample_input)
|
| 512 |
+
|
| 513 |
+
print("\nOutput data shape:", output.shape)
|
| 514 |
+
print("Output data:\n", output)
|
| 515 |
+
|
| 516 |
+
# Demonstrate individual uncomputable layers
|
| 517 |
+
print("\n=== Individual Uncomputable Layer Demonstrations ===\n")
|
| 518 |
+
|
| 519 |
+
# Halting Oracle Layer
|
| 520 |
+
halting_layer = HaltingOracleLayer(4, 3, max_iterations=100)
|
| 521 |
+
halting_output = halting_layer.forward(sample_input[0])
|
| 522 |
+
print("Halting Oracle Layer Output:", halting_output)
|
| 523 |
+
|
| 524 |
+
# Kolmogorov Complexity Layer
|
| 525 |
+
kolmogorov_layer = KolmogorovComplexityLayer(4, 3, precision=6)
|
| 526 |
+
kolmogorov_output = kolmogorov_layer.forward(sample_input[0])
|
| 527 |
+
print("Kolmogorov Complexity Layer Output:", kolmogorov_output)
|
| 528 |
+
|
| 529 |
+
# Busy Beaver Layer
|
| 530 |
+
bb_layer = BusyBeaverLayer(4, 3)
|
| 531 |
+
bb_output = bb_layer.forward(sample_input[0])
|
| 532 |
+
print("Busy Beaver Layer Output:", bb_output)
|
| 533 |
+
|
| 534 |
+
# Non-Recursive Layer
|
| 535 |
+
nr_layer = NonRecursiveLayer(4, 3, enumeration_bound=100)
|
| 536 |
+
nr_output = nr_layer.forward(sample_input[0])
|
| 537 |
+
print("Non-Recursive Layer Output:", nr_output)
|
| 538 |
+
|
| 539 |
+
|
| 540 |
+
if __name__ == "__main__":
|
| 541 |
+
demo_algebraic_neural_network()
|
| 542 |
+
demo_uncomputable_neural_network()
|
demo.py
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""
|
| 3 |
+
Quick demonstration of Algebraic Neural Networks
|
| 4 |
+
|
| 5 |
+
Run this script to see the basic functionality of algebraic neural networks.
|
| 6 |
+
"""
|
| 7 |
+
|
| 8 |
+
import numpy as np
|
| 9 |
+
from algebraic_neural_network import create_sample_network, create_uncomputable_network
|
| 10 |
+
|
| 11 |
+
def main():
|
| 12 |
+
print("🧮 Algebraic Neural Network Quick Demo")
|
| 13 |
+
print("="*50)
|
| 14 |
+
|
| 15 |
+
# Create a sample network
|
| 16 |
+
print("1. Creating algebraic neural network...")
|
| 17 |
+
network = create_sample_network()
|
| 18 |
+
print(" ✓ Network created with polynomial, group theory, and geometric algebra layers")
|
| 19 |
+
|
| 20 |
+
# Generate sample data
|
| 21 |
+
print("\n2. Generating sample data...")
|
| 22 |
+
np.random.seed(42) # For reproducible results
|
| 23 |
+
sample_data = np.random.randn(3, 4)
|
| 24 |
+
print(f" ✓ Generated {sample_data.shape[0]} samples with {sample_data.shape[1]} features each")
|
| 25 |
+
|
| 26 |
+
# Make predictions
|
| 27 |
+
print("\n3. Processing data through algebraic transformations...")
|
| 28 |
+
predictions = network.predict(sample_data)
|
| 29 |
+
print(f" ✓ Output shape: {predictions.shape}")
|
| 30 |
+
print(f" ✓ Output range: [{np.min(predictions):.3f}, {np.max(predictions):.3f}]")
|
| 31 |
+
|
| 32 |
+
# Show the data
|
| 33 |
+
print("\n4. Results:")
|
| 34 |
+
print(" Input data:")
|
| 35 |
+
for i, sample in enumerate(sample_data):
|
| 36 |
+
print(f" Sample {i+1}: [{sample[0]:6.3f}, {sample[1]:6.3f}, {sample[2]:6.3f}, {sample[3]:6.3f}]")
|
| 37 |
+
|
| 38 |
+
print("\n Algebraic neural network output:")
|
| 39 |
+
for i, output in enumerate(predictions):
|
| 40 |
+
print(f" Output {i+1}: [{output[0]:8.3f}, {output[1]:8.3f}]")
|
| 41 |
+
|
| 42 |
+
# Demonstrate determinism
|
| 43 |
+
print("\n5. Demonstrating deterministic behavior...")
|
| 44 |
+
predictions2 = network.predict(sample_data)
|
| 45 |
+
difference = np.linalg.norm(predictions - predictions2)
|
| 46 |
+
print(f" ✓ Difference between runs: {difference:.10f} (should be 0)")
|
| 47 |
+
|
| 48 |
+
print("\n" + "="*50)
|
| 49 |
+
print("✅ Demo completed! Algebraic neural networks work without training.")
|
| 50 |
+
|
| 51 |
+
# Bonus: Quick uncomputable network demo
|
| 52 |
+
print("\n🔬 Bonus: Uncomputable Neural Network Quick Demo")
|
| 53 |
+
print("="*50)
|
| 54 |
+
|
| 55 |
+
print("1. Creating uncomputable neural network...")
|
| 56 |
+
uncomputable_network = create_uncomputable_network()
|
| 57 |
+
print(" ✓ Network created with halting oracle, Kolmogorov complexity, Busy Beaver, and non-recursive layers")
|
| 58 |
+
|
| 59 |
+
print("\n2. Processing same data through uncomputable transformations...")
|
| 60 |
+
uncomputable_predictions = uncomputable_network.predict(sample_data)
|
| 61 |
+
print(f" ✓ Output shape: {uncomputable_predictions.shape}")
|
| 62 |
+
print(f" ✓ Output range: [{np.min(uncomputable_predictions):.3f}, {np.max(uncomputable_predictions):.3f}]")
|
| 63 |
+
|
| 64 |
+
print("\n Uncomputable neural network output:")
|
| 65 |
+
for i, output in enumerate(uncomputable_predictions):
|
| 66 |
+
print(f" Output {i+1}: [{output[0]:6.3f}, {output[1]:6.3f}]")
|
| 67 |
+
|
| 68 |
+
print("\n" + "="*50)
|
| 69 |
+
print("🎯 Both networks operate without training but explore different mathematical domains!")
|
| 70 |
+
print("📚 See theory/ and examples/ directories for more details.")
|
| 71 |
+
|
| 72 |
+
if __name__ == "__main__":
|
| 73 |
+
main()
|
examples/geometric_algebra_network.py
ADDED
|
@@ -0,0 +1,461 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Geometric Algebra (Clifford Algebra) Neural Network
|
| 3 |
+
|
| 4 |
+
This example demonstrates neural networks using geometric algebra operations
|
| 5 |
+
for processing geometric and spatial data.
|
| 6 |
+
"""
|
| 7 |
+
|
| 8 |
+
import numpy as np
|
| 9 |
+
from typing import List, Tuple, Dict, Union
|
| 10 |
+
import math
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
class GeometricAlgebraNetwork:
|
| 14 |
+
"""
|
| 15 |
+
Neural network based on geometric algebra (Clifford algebra) operations.
|
| 16 |
+
"""
|
| 17 |
+
|
| 18 |
+
def __init__(self, input_dim: int, hidden_dim: int, output_dim: int, signature: str = "euclidean"):
|
| 19 |
+
self.input_dim = input_dim
|
| 20 |
+
self.hidden_dim = hidden_dim
|
| 21 |
+
self.output_dim = output_dim
|
| 22 |
+
self.signature = signature
|
| 23 |
+
|
| 24 |
+
# Initialize geometric algebra basis
|
| 25 |
+
self.basis_elements = self._generate_basis_elements()
|
| 26 |
+
self.metric = self._generate_metric()
|
| 27 |
+
|
| 28 |
+
# Generate transformation coefficients
|
| 29 |
+
self.coefficients = self._generate_ga_coefficients()
|
| 30 |
+
|
| 31 |
+
def _generate_metric(self) -> np.ndarray:
|
| 32 |
+
"""Generate metric tensor for the geometric algebra."""
|
| 33 |
+
if self.signature == "euclidean":
|
| 34 |
+
return np.eye(self.input_dim)
|
| 35 |
+
elif self.signature == "minkowski":
|
| 36 |
+
metric = np.eye(self.input_dim)
|
| 37 |
+
metric[0, 0] = -1 # Time component with opposite signature
|
| 38 |
+
return metric
|
| 39 |
+
elif self.signature == "conformal":
|
| 40 |
+
# Conformal geometric algebra Cl(n+1,1)
|
| 41 |
+
metric = np.eye(self.input_dim + 2)
|
| 42 |
+
metric[-1, -1] = -1 # One negative signature
|
| 43 |
+
return metric
|
| 44 |
+
else:
|
| 45 |
+
return np.eye(self.input_dim)
|
| 46 |
+
|
| 47 |
+
def _generate_basis_elements(self) -> List[Tuple[str, np.ndarray]]:
|
| 48 |
+
"""Generate basis elements for geometric algebra."""
|
| 49 |
+
basis = []
|
| 50 |
+
|
| 51 |
+
# Scalar (grade 0)
|
| 52 |
+
scalar_basis = np.zeros(2**self.input_dim)
|
| 53 |
+
scalar_basis[0] = 1.0
|
| 54 |
+
basis.append(("scalar", scalar_basis))
|
| 55 |
+
|
| 56 |
+
# Vector basis elements (grade 1)
|
| 57 |
+
for i in range(self.input_dim):
|
| 58 |
+
vector_basis = np.zeros(2**self.input_dim)
|
| 59 |
+
vector_basis[2**i] = 1.0
|
| 60 |
+
basis.append((f"e{i+1}", vector_basis))
|
| 61 |
+
|
| 62 |
+
# Bivector basis elements (grade 2)
|
| 63 |
+
for i in range(self.input_dim):
|
| 64 |
+
for j in range(i+1, self.input_dim):
|
| 65 |
+
bivector_basis = np.zeros(2**self.input_dim)
|
| 66 |
+
bivector_basis[2**i + 2**j] = 1.0
|
| 67 |
+
basis.append((f"e{i+1}e{j+1}", bivector_basis))
|
| 68 |
+
|
| 69 |
+
# Higher grade elements for small dimensions
|
| 70 |
+
if self.input_dim <= 4:
|
| 71 |
+
# Trivectors (grade 3)
|
| 72 |
+
for i in range(self.input_dim):
|
| 73 |
+
for j in range(i+1, self.input_dim):
|
| 74 |
+
for k in range(j+1, self.input_dim):
|
| 75 |
+
trivector_basis = np.zeros(2**self.input_dim)
|
| 76 |
+
trivector_basis[2**i + 2**j + 2**k] = 1.0
|
| 77 |
+
basis.append((f"e{i+1}e{j+1}e{k+1}", trivector_basis))
|
| 78 |
+
|
| 79 |
+
# Pseudoscalar (highest grade)
|
| 80 |
+
if self.input_dim >= 2:
|
| 81 |
+
pseudo_basis = np.zeros(2**self.input_dim)
|
| 82 |
+
pseudo_basis[-1] = 1.0
|
| 83 |
+
basis.append(("pseudoscalar", pseudo_basis))
|
| 84 |
+
|
| 85 |
+
return basis
|
| 86 |
+
|
| 87 |
+
def _generate_ga_coefficients(self) -> Dict[str, np.ndarray]:
|
| 88 |
+
"""Generate coefficients for geometric algebra transformations."""
|
| 89 |
+
coeffs = {}
|
| 90 |
+
|
| 91 |
+
# Constants from geometric algebra theory
|
| 92 |
+
sqrt2 = math.sqrt(2)
|
| 93 |
+
sqrt3 = math.sqrt(3)
|
| 94 |
+
phi = (1 + math.sqrt(5)) / 2 # Golden ratio
|
| 95 |
+
|
| 96 |
+
constants = [1.0, 1/sqrt2, 1/sqrt3, 1/phi, phi/3, sqrt2/3, sqrt3/5]
|
| 97 |
+
|
| 98 |
+
# Input to hidden transformation
|
| 99 |
+
num_basis = len(self.basis_elements)
|
| 100 |
+
coeffs['input_hidden'] = np.zeros((self.hidden_dim, self.input_dim, num_basis))
|
| 101 |
+
|
| 102 |
+
for i in range(self.hidden_dim):
|
| 103 |
+
for j in range(self.input_dim):
|
| 104 |
+
for k in range(num_basis):
|
| 105 |
+
const_idx = (i + j + k) % len(constants)
|
| 106 |
+
coeffs['input_hidden'][i, j, k] = constants[const_idx]
|
| 107 |
+
|
| 108 |
+
# Hidden to output transformation
|
| 109 |
+
coeffs['hidden_output'] = np.zeros((self.output_dim, self.hidden_dim, num_basis))
|
| 110 |
+
|
| 111 |
+
for i in range(self.output_dim):
|
| 112 |
+
for j in range(self.hidden_dim):
|
| 113 |
+
for k in range(num_basis):
|
| 114 |
+
const_idx = (i + j + k + 1) % len(constants)
|
| 115 |
+
coeffs['hidden_output'][i, j, k] = constants[const_idx]
|
| 116 |
+
|
| 117 |
+
return coeffs
|
| 118 |
+
|
| 119 |
+
def geometric_product(self, a: np.ndarray, b: np.ndarray) -> np.ndarray:
|
| 120 |
+
"""Compute geometric product of two multivectors."""
|
| 121 |
+
# Simplified geometric product implementation
|
| 122 |
+
# In full implementation, this would use the basis multiplication table
|
| 123 |
+
|
| 124 |
+
if len(a) != len(b):
|
| 125 |
+
min_len = min(len(a), len(b))
|
| 126 |
+
a, b = a[:min_len], b[:min_len]
|
| 127 |
+
|
| 128 |
+
# For this implementation, approximate with:
|
| 129 |
+
# ab = a·b + a∧b (dot + wedge products)
|
| 130 |
+
|
| 131 |
+
# Dot product component (grade reduction)
|
| 132 |
+
dot_product = np.dot(a, b)
|
| 133 |
+
|
| 134 |
+
# Wedge product component (grade increase) - simplified
|
| 135 |
+
wedge_magnitude = np.linalg.norm(np.outer(a, b) - np.outer(b, a))
|
| 136 |
+
|
| 137 |
+
# Combine into multivector representation
|
| 138 |
+
result = np.zeros(max(len(a), 2**self.input_dim))
|
| 139 |
+
result[0] = dot_product # Scalar part
|
| 140 |
+
|
| 141 |
+
if len(result) > 1:
|
| 142 |
+
result[1] = wedge_magnitude # Vector part approximation
|
| 143 |
+
|
| 144 |
+
# Additional components based on input structure
|
| 145 |
+
for i in range(2, min(len(result), len(a) + len(b) - 1)):
|
| 146 |
+
result[i] = (a[i % len(a)] * b[i % len(b)] +
|
| 147 |
+
b[i % len(b)] * a[i % len(a)]) / 2
|
| 148 |
+
|
| 149 |
+
return result[:len(a)]
|
| 150 |
+
|
| 151 |
+
def outer_product(self, a: np.ndarray, b: np.ndarray) -> float:
|
| 152 |
+
"""Compute outer (wedge) product magnitude."""
|
| 153 |
+
if len(a) >= 2 and len(b) >= 2:
|
| 154 |
+
# 2D outer product as determinant
|
| 155 |
+
return abs(a[0] * b[1] - a[1] * b[0])
|
| 156 |
+
else:
|
| 157 |
+
# Higher dimensional approximation
|
| 158 |
+
return np.linalg.norm(np.outer(a, b) - np.outer(b, a))
|
| 159 |
+
|
| 160 |
+
def inner_product(self, a: np.ndarray, b: np.ndarray) -> float:
|
| 161 |
+
"""Compute inner (dot) product."""
|
| 162 |
+
return np.dot(a, b)
|
| 163 |
+
|
| 164 |
+
def reverse(self, mv: np.ndarray) -> np.ndarray:
|
| 165 |
+
"""Compute reverse of multivector (reverse order of basis elements)."""
|
| 166 |
+
# For bivectors and higher grades, reverse changes sign
|
| 167 |
+
reversed_mv = mv.copy()
|
| 168 |
+
|
| 169 |
+
# Approximate reversal by alternating signs for higher components
|
| 170 |
+
for i in range(1, len(reversed_mv)):
|
| 171 |
+
grade = bin(i).count('1') # Grade based on binary representation
|
| 172 |
+
if grade % 4 in [2, 3]: # Bivectors and trivectors change sign
|
| 173 |
+
reversed_mv[i] *= -1
|
| 174 |
+
|
| 175 |
+
return reversed_mv
|
| 176 |
+
|
| 177 |
+
def magnitude(self, mv: np.ndarray) -> float:
|
| 178 |
+
"""Compute magnitude of multivector."""
|
| 179 |
+
# Magnitude is sqrt(mv * reverse(mv))
|
| 180 |
+
reversed_mv = self.reverse(mv)
|
| 181 |
+
product = self.geometric_product(mv, reversed_mv)
|
| 182 |
+
return math.sqrt(abs(product[0])) # Scalar part should be positive
|
| 183 |
+
|
| 184 |
+
def normalize(self, mv: np.ndarray) -> np.ndarray:
|
| 185 |
+
"""Normalize multivector."""
|
| 186 |
+
mag = self.magnitude(mv)
|
| 187 |
+
if mag > 1e-10:
|
| 188 |
+
return mv / mag
|
| 189 |
+
else:
|
| 190 |
+
return mv
|
| 191 |
+
|
| 192 |
+
def apply_ga_transformation(self, x: np.ndarray, coeffs: np.ndarray) -> np.ndarray:
|
| 193 |
+
"""Apply geometric algebra transformation."""
|
| 194 |
+
if x.ndim == 1:
|
| 195 |
+
x = x.reshape(1, -1)
|
| 196 |
+
|
| 197 |
+
batch_size, input_size = x.shape
|
| 198 |
+
output_size = coeffs.shape[0]
|
| 199 |
+
num_basis = len(self.basis_elements)
|
| 200 |
+
|
| 201 |
+
result = np.zeros((batch_size, output_size))
|
| 202 |
+
|
| 203 |
+
for batch_idx in range(batch_size):
|
| 204 |
+
for out_idx in range(output_size):
|
| 205 |
+
# Construct multivector from input
|
| 206 |
+
multivector = np.zeros(num_basis)
|
| 207 |
+
|
| 208 |
+
for in_idx in range(min(input_size, self.input_dim)):
|
| 209 |
+
for basis_idx in range(num_basis):
|
| 210 |
+
basis_name, basis_vector = self.basis_elements[basis_idx]
|
| 211 |
+
coeff = coeffs[out_idx, in_idx, basis_idx]
|
| 212 |
+
|
| 213 |
+
# Ensure basis_vector has correct length
|
| 214 |
+
basis_component = basis_vector[:num_basis] if len(basis_vector) >= num_basis else np.pad(basis_vector, (0, num_basis - len(basis_vector)))
|
| 215 |
+
|
| 216 |
+
# Weight by input value and coefficient
|
| 217 |
+
multivector += x[batch_idx, in_idx] * coeff * basis_component
|
| 218 |
+
|
| 219 |
+
# Apply geometric algebra operations
|
| 220 |
+
# 1. Geometric product with basis elements
|
| 221 |
+
transformed_mv = multivector.copy()
|
| 222 |
+
|
| 223 |
+
for basis_idx in range(min(3, num_basis)): # Use first few basis elements
|
| 224 |
+
_, basis_vector = self.basis_elements[basis_idx]
|
| 225 |
+
transformed_mv = self.geometric_product(transformed_mv, basis_vector[:num_basis])
|
| 226 |
+
|
| 227 |
+
# 2. Extract scalar and vector parts
|
| 228 |
+
scalar_part = transformed_mv[0] if len(transformed_mv) > 0 else 0
|
| 229 |
+
vector_magnitude = np.linalg.norm(transformed_mv[1:min(4, len(transformed_mv))])
|
| 230 |
+
|
| 231 |
+
# 3. Combine into output
|
| 232 |
+
result[batch_idx, out_idx] = scalar_part + vector_magnitude
|
| 233 |
+
|
| 234 |
+
return result
|
| 235 |
+
|
| 236 |
+
def forward(self, x: np.ndarray) -> np.ndarray:
|
| 237 |
+
"""Forward pass through geometric algebra network."""
|
| 238 |
+
# Input to hidden layer
|
| 239 |
+
hidden = self.apply_ga_transformation(x, self.coefficients['input_hidden'])
|
| 240 |
+
|
| 241 |
+
# Apply nonlinearity (preserve geometric structure)
|
| 242 |
+
hidden = np.tanh(hidden)
|
| 243 |
+
|
| 244 |
+
# Hidden to output layer
|
| 245 |
+
output = self.apply_ga_transformation(hidden, self.coefficients['hidden_output'])
|
| 246 |
+
|
| 247 |
+
return output
|
| 248 |
+
|
| 249 |
+
def predict(self, x: np.ndarray) -> np.ndarray:
|
| 250 |
+
"""Prediction method."""
|
| 251 |
+
return self.forward(x)
|
| 252 |
+
|
| 253 |
+
|
| 254 |
+
def test_geometric_operations():
|
| 255 |
+
"""Test basic geometric algebra operations."""
|
| 256 |
+
print("=== Geometric Algebra: Basic Operations Test ===\n")
|
| 257 |
+
|
| 258 |
+
network = GeometricAlgebraNetwork(input_dim=3, hidden_dim=4, output_dim=2)
|
| 259 |
+
|
| 260 |
+
# Test vectors
|
| 261 |
+
a = np.array([1, 0, 0]) # e1
|
| 262 |
+
b = np.array([0, 1, 0]) # e2
|
| 263 |
+
c = np.array([1, 1, 0]) # e1 + e2
|
| 264 |
+
|
| 265 |
+
print("Testing geometric algebra operations:")
|
| 266 |
+
|
| 267 |
+
# Inner products
|
| 268 |
+
inner_ab = network.inner_product(a, b)
|
| 269 |
+
inner_aa = network.inner_product(a, a)
|
| 270 |
+
print(f"Inner product a·b = {inner_ab:.3f} (should be 0)")
|
| 271 |
+
print(f"Inner product a·a = {inner_aa:.3f} (should be 1)")
|
| 272 |
+
|
| 273 |
+
# Outer products
|
| 274 |
+
outer_ab = network.outer_product(a, b)
|
| 275 |
+
outer_aa = network.outer_product(a, a)
|
| 276 |
+
print(f"Outer product a∧b magnitude = {outer_ab:.3f} (should be 1)")
|
| 277 |
+
print(f"Outer product a∧a magnitude = {outer_aa:.3f} (should be 0)")
|
| 278 |
+
|
| 279 |
+
# Geometric products
|
| 280 |
+
geom_ab = network.geometric_product(a, b)
|
| 281 |
+
print(f"Geometric product a*b = {geom_ab[:3]} (first 3 components)")
|
| 282 |
+
|
| 283 |
+
# Magnitudes
|
| 284 |
+
mag_a = network.magnitude(a)
|
| 285 |
+
mag_c = network.magnitude(c)
|
| 286 |
+
print(f"Magnitude |a| = {mag_a:.3f}")
|
| 287 |
+
print(f"Magnitude |c| = {mag_c:.3f}")
|
| 288 |
+
|
| 289 |
+
print()
|
| 290 |
+
|
| 291 |
+
|
| 292 |
+
def test_3d_rotation_processing():
|
| 293 |
+
"""Test processing of 3D rotational data."""
|
| 294 |
+
print("=== Geometric Algebra: 3D Rotation Processing ===\n")
|
| 295 |
+
|
| 296 |
+
network = GeometricAlgebraNetwork(input_dim=3, hidden_dim=6, output_dim=4)
|
| 297 |
+
|
| 298 |
+
# Generate 3D rotation data (axis-angle representation)
|
| 299 |
+
rotation_axes = [
|
| 300 |
+
[1, 0, 0], # X-axis rotation
|
| 301 |
+
[0, 1, 0], # Y-axis rotation
|
| 302 |
+
[0, 0, 1], # Z-axis rotation
|
| 303 |
+
[1, 1, 1], # Diagonal rotation
|
| 304 |
+
[1, -1, 0], # Mixed rotation
|
| 305 |
+
]
|
| 306 |
+
|
| 307 |
+
print("Processing 3D rotation data:")
|
| 308 |
+
|
| 309 |
+
for i, axis in enumerate(rotation_axes):
|
| 310 |
+
axis = np.array(axis, dtype=float)
|
| 311 |
+
axis = axis / np.linalg.norm(axis) # Normalize
|
| 312 |
+
|
| 313 |
+
# Different rotation angles
|
| 314 |
+
angles = [0, np.pi/4, np.pi/2, np.pi, 3*np.pi/2]
|
| 315 |
+
|
| 316 |
+
outputs = []
|
| 317 |
+
for angle in angles:
|
| 318 |
+
# Rotation vector (axis * angle)
|
| 319 |
+
rotation_vector = axis * angle
|
| 320 |
+
output = network.predict(rotation_vector.reshape(1, -1))
|
| 321 |
+
outputs.append(output[0])
|
| 322 |
+
|
| 323 |
+
outputs = np.array(outputs)
|
| 324 |
+
|
| 325 |
+
print(f"\nRotation axis {i+1}: {axis}")
|
| 326 |
+
print(f" Output range: [{np.min(outputs):.3f}, {np.max(outputs):.3f}]")
|
| 327 |
+
print(f" Output variance: {np.var(outputs, axis=0)}")
|
| 328 |
+
|
| 329 |
+
# Check for periodic behavior (rotations should have 2π periodicity)
|
| 330 |
+
first_output = outputs[0] # 0 radians
|
| 331 |
+
last_output = outputs[-1] # 3π/2 radians, should be similar to π/2
|
| 332 |
+
|
| 333 |
+
periodicity_error = np.linalg.norm(first_output - outputs[2]) # Compare 0 and π
|
| 334 |
+
print(f" Periodicity error (0 vs π): {periodicity_error:.6f}")
|
| 335 |
+
|
| 336 |
+
|
| 337 |
+
def test_conformal_geometry():
|
| 338 |
+
"""Test conformal geometric algebra for 2D points."""
|
| 339 |
+
print("=== Geometric Algebra: Conformal Geometry ===\n")
|
| 340 |
+
|
| 341 |
+
# Use conformal signature for 2D conformal GA
|
| 342 |
+
network = GeometricAlgebraNetwork(input_dim=2, hidden_dim=8, output_dim=4, signature="conformal")
|
| 343 |
+
|
| 344 |
+
# Test geometric primitives
|
| 345 |
+
geometric_objects = {
|
| 346 |
+
"Point": np.array([1, 1]),
|
| 347 |
+
"Origin": np.array([0, 0]),
|
| 348 |
+
"Unit_X": np.array([1, 0]),
|
| 349 |
+
"Unit_Y": np.array([0, 1]),
|
| 350 |
+
"Diagonal": np.array([1, 1]) / np.sqrt(2)
|
| 351 |
+
}
|
| 352 |
+
|
| 353 |
+
print("Processing geometric objects in conformal space:")
|
| 354 |
+
|
| 355 |
+
object_features = {}
|
| 356 |
+
for obj_name, point in geometric_objects.items():
|
| 357 |
+
# Convert to conformal representation
|
| 358 |
+
# In conformal GA: P = point + 0.5*|point|²*e∞ + e₀
|
| 359 |
+
point_squared = np.dot(point, point)
|
| 360 |
+
conformal_point = np.concatenate([point, [0.5 * point_squared, 1]])
|
| 361 |
+
|
| 362 |
+
# Process through network
|
| 363 |
+
output = network.predict(conformal_point.reshape(1, -1))
|
| 364 |
+
object_features[obj_name] = output[0]
|
| 365 |
+
|
| 366 |
+
print(f"{obj_name:>10}: {point} → output: {output[0]}")
|
| 367 |
+
|
| 368 |
+
# Analyze relationships between objects
|
| 369 |
+
print("\nAnalyzing geometric relationships:")
|
| 370 |
+
|
| 371 |
+
origin_features = object_features["Origin"]
|
| 372 |
+
for obj_name, features in object_features.items():
|
| 373 |
+
if obj_name != "Origin":
|
| 374 |
+
distance = np.linalg.norm(features - origin_features)
|
| 375 |
+
print(f" Feature distance from origin to {obj_name}: {distance:.4f}")
|
| 376 |
+
|
| 377 |
+
|
| 378 |
+
def test_bivector_operations():
|
| 379 |
+
"""Test bivector operations for oriented areas."""
|
| 380 |
+
print("=== Geometric Algebra: Bivector Operations ===\n")
|
| 381 |
+
|
| 382 |
+
network = GeometricAlgebraNetwork(input_dim=4, hidden_dim=6, output_dim=3)
|
| 383 |
+
|
| 384 |
+
# Create bivectors representing oriented areas
|
| 385 |
+
bivectors = [
|
| 386 |
+
[1, 0, 1, 0], # e1∧e3
|
| 387 |
+
[0, 1, 0, 1], # e2∧e4
|
| 388 |
+
[1, 1, 0, 0], # e1∧e2
|
| 389 |
+
[0, 0, 1, 1], # e3∧e4
|
| 390 |
+
[1, 0, 0, 1], # e1∧e4
|
| 391 |
+
]
|
| 392 |
+
|
| 393 |
+
print("Processing bivector data:")
|
| 394 |
+
|
| 395 |
+
for i, bivector in enumerate(bivectors):
|
| 396 |
+
bv = np.array(bivector, dtype=float)
|
| 397 |
+
output = network.predict(bv.reshape(1, -1))
|
| 398 |
+
|
| 399 |
+
# Calculate bivector magnitude
|
| 400 |
+
bv_magnitude = np.linalg.norm(bv)
|
| 401 |
+
|
| 402 |
+
print(f"Bivector {i+1}: {bv}")
|
| 403 |
+
print(f" Magnitude: {bv_magnitude:.3f}")
|
| 404 |
+
print(f" Network output: {output[0]}")
|
| 405 |
+
print(f" Output magnitude: {np.linalg.norm(output[0]):.3f}")
|
| 406 |
+
print()
|
| 407 |
+
|
| 408 |
+
|
| 409 |
+
def test_multivector_algebra():
|
| 410 |
+
"""Test general multivector operations."""
|
| 411 |
+
print("=== Geometric Algebra: Multivector Operations ===\n")
|
| 412 |
+
|
| 413 |
+
network = GeometricAlgebraNetwork(input_dim=3, hidden_dim=5, output_dim=2)
|
| 414 |
+
|
| 415 |
+
# Create multivectors with different grade components
|
| 416 |
+
multivectors = [
|
| 417 |
+
[1, 0, 0], # Pure vector e1
|
| 418 |
+
[0, 1, 0], # Pure vector e2
|
| 419 |
+
[0, 0, 1], # Pure vector e3
|
| 420 |
+
[1, 1, 0], # e1 + e2
|
| 421 |
+
[1, 1, 1], # e1 + e2 + e3
|
| 422 |
+
[2, -1, 0.5], # 2*e1 - e2 + 0.5*e3
|
| 423 |
+
]
|
| 424 |
+
|
| 425 |
+
print("Multivector algebra processing:")
|
| 426 |
+
|
| 427 |
+
for i, mv in enumerate(multivectors):
|
| 428 |
+
mv_array = np.array(mv, dtype=float)
|
| 429 |
+
|
| 430 |
+
# Test reverse operation
|
| 431 |
+
reversed_mv = network.reverse(mv_array)
|
| 432 |
+
|
| 433 |
+
# Test magnitude
|
| 434 |
+
magnitude = network.magnitude(mv_array)
|
| 435 |
+
|
| 436 |
+
# Test normalization
|
| 437 |
+
normalized_mv = network.normalize(mv_array)
|
| 438 |
+
|
| 439 |
+
# Network processing
|
| 440 |
+
output = network.predict(mv_array.reshape(1, -1))
|
| 441 |
+
|
| 442 |
+
print(f"\nMultivector {i+1}: {mv}")
|
| 443 |
+
print(f" Reversed: {reversed_mv}")
|
| 444 |
+
print(f" Magnitude: {magnitude:.4f}")
|
| 445 |
+
print(f" Normalized: {normalized_mv}")
|
| 446 |
+
print(f" Network output: {output[0]}")
|
| 447 |
+
|
| 448 |
+
|
| 449 |
+
if __name__ == "__main__":
|
| 450 |
+
print("Geometric Algebra Neural Network Demo\n")
|
| 451 |
+
print("="*60)
|
| 452 |
+
|
| 453 |
+
# Run tests
|
| 454 |
+
test_geometric_operations()
|
| 455 |
+
test_3d_rotation_processing()
|
| 456 |
+
test_conformal_geometry()
|
| 457 |
+
test_bivector_operations()
|
| 458 |
+
test_multivector_algebra()
|
| 459 |
+
|
| 460 |
+
print("\n" + "="*60)
|
| 461 |
+
print("Geometric algebra demo completed successfully!")
|
examples/group_theory_network.py
ADDED
|
@@ -0,0 +1,381 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Group Theory-based Algebraic Neural Network
|
| 3 |
+
|
| 4 |
+
This example demonstrates neural networks that use group theory operations
|
| 5 |
+
for data transformations, particularly focusing on symmetry groups.
|
| 6 |
+
"""
|
| 7 |
+
|
| 8 |
+
import numpy as np
|
| 9 |
+
from typing import List, Tuple, Dict
|
| 10 |
+
import math
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
class GroupTheoryNetwork:
|
| 14 |
+
"""
|
| 15 |
+
Neural network based on group theory operations and symmetries.
|
| 16 |
+
"""
|
| 17 |
+
|
| 18 |
+
def __init__(self, input_dim: int, group_types: List[str], output_dim: int):
|
| 19 |
+
self.input_dim = input_dim
|
| 20 |
+
self.group_types = group_types
|
| 21 |
+
self.output_dim = output_dim
|
| 22 |
+
|
| 23 |
+
# Initialize group operations
|
| 24 |
+
self.groups = self._initialize_groups()
|
| 25 |
+
|
| 26 |
+
def _initialize_groups(self) -> Dict[str, List[np.ndarray]]:
|
| 27 |
+
"""Initialize various group operations."""
|
| 28 |
+
groups = {}
|
| 29 |
+
|
| 30 |
+
for group_type in self.group_types:
|
| 31 |
+
if group_type.startswith("cyclic_"):
|
| 32 |
+
n = int(group_type.split("_")[1])
|
| 33 |
+
groups[group_type] = self._generate_cyclic_group(n)
|
| 34 |
+
elif group_type.startswith("dihedral_"):
|
| 35 |
+
n = int(group_type.split("_")[1])
|
| 36 |
+
groups[group_type] = self._generate_dihedral_group(n)
|
| 37 |
+
elif group_type == "symmetric_3":
|
| 38 |
+
groups[group_type] = self._generate_symmetric_group_3()
|
| 39 |
+
elif group_type == "reflection":
|
| 40 |
+
groups[group_type] = self._generate_reflection_group()
|
| 41 |
+
|
| 42 |
+
return groups
|
| 43 |
+
|
| 44 |
+
def _generate_cyclic_group(self, n: int) -> List[np.ndarray]:
|
| 45 |
+
"""Generate cyclic group Cn as rotation matrices."""
|
| 46 |
+
group_elements = []
|
| 47 |
+
|
| 48 |
+
for k in range(n):
|
| 49 |
+
angle = 2 * math.pi * k / n
|
| 50 |
+
|
| 51 |
+
if self.input_dim == 2:
|
| 52 |
+
# 2D rotation matrix
|
| 53 |
+
rotation = np.array([
|
| 54 |
+
[math.cos(angle), -math.sin(angle)],
|
| 55 |
+
[math.sin(angle), math.cos(angle)]
|
| 56 |
+
])
|
| 57 |
+
elif self.input_dim >= 3:
|
| 58 |
+
# 3D rotation around z-axis, identity for higher dimensions
|
| 59 |
+
rotation = np.eye(self.input_dim)
|
| 60 |
+
if self.input_dim >= 2:
|
| 61 |
+
rotation[0, 0] = math.cos(angle)
|
| 62 |
+
rotation[0, 1] = -math.sin(angle)
|
| 63 |
+
rotation[1, 0] = math.sin(angle)
|
| 64 |
+
rotation[1, 1] = math.cos(angle)
|
| 65 |
+
else:
|
| 66 |
+
# 1D case - just scaling
|
| 67 |
+
rotation = np.array([[(-1) ** k]])
|
| 68 |
+
|
| 69 |
+
group_elements.append(rotation)
|
| 70 |
+
|
| 71 |
+
return group_elements
|
| 72 |
+
|
| 73 |
+
def _generate_dihedral_group(self, n: int) -> List[np.ndarray]:
|
| 74 |
+
"""Generate dihedral group Dn (rotations + reflections)."""
|
| 75 |
+
group_elements = []
|
| 76 |
+
|
| 77 |
+
# Add rotations (same as cyclic group)
|
| 78 |
+
rotations = self._generate_cyclic_group(n)
|
| 79 |
+
group_elements.extend(rotations)
|
| 80 |
+
|
| 81 |
+
# Add reflections
|
| 82 |
+
for k in range(n):
|
| 83 |
+
angle = 2 * math.pi * k / n
|
| 84 |
+
|
| 85 |
+
if self.input_dim == 2:
|
| 86 |
+
# Reflection across line through origin at angle/2
|
| 87 |
+
reflection_angle = angle / 2
|
| 88 |
+
cos_2theta = math.cos(2 * reflection_angle)
|
| 89 |
+
sin_2theta = math.sin(2 * reflection_angle)
|
| 90 |
+
|
| 91 |
+
reflection = np.array([
|
| 92 |
+
[cos_2theta, sin_2theta],
|
| 93 |
+
[sin_2theta, -cos_2theta]
|
| 94 |
+
])
|
| 95 |
+
else:
|
| 96 |
+
# For higher dimensions, reflect across first coordinate
|
| 97 |
+
reflection = np.eye(self.input_dim)
|
| 98 |
+
reflection[0, 0] = -1
|
| 99 |
+
|
| 100 |
+
group_elements.append(reflection)
|
| 101 |
+
|
| 102 |
+
return group_elements
|
| 103 |
+
|
| 104 |
+
def _generate_symmetric_group_3(self) -> List[np.ndarray]:
|
| 105 |
+
"""Generate symmetric group S3 (permutations of 3 elements)."""
|
| 106 |
+
if self.input_dim < 3:
|
| 107 |
+
# For lower dimensions, use reduced representation
|
| 108 |
+
return self._generate_cyclic_group(3)
|
| 109 |
+
|
| 110 |
+
# All permutations of 3 elements as permutation matrices
|
| 111 |
+
permutations = [
|
| 112 |
+
[0, 1, 2], # identity
|
| 113 |
+
[1, 2, 0], # (0 1 2)
|
| 114 |
+
[2, 0, 1], # (0 2 1)
|
| 115 |
+
[1, 0, 2], # (0 1)
|
| 116 |
+
[0, 2, 1], # (0 2)
|
| 117 |
+
[2, 1, 0], # (1 2)
|
| 118 |
+
]
|
| 119 |
+
|
| 120 |
+
group_elements = []
|
| 121 |
+
for perm in permutations:
|
| 122 |
+
matrix = np.eye(self.input_dim)
|
| 123 |
+
for i in range(3):
|
| 124 |
+
if i < self.input_dim and perm[i] < self.input_dim:
|
| 125 |
+
matrix[i, i] = 0
|
| 126 |
+
matrix[i, perm[i]] = 1
|
| 127 |
+
group_elements.append(matrix)
|
| 128 |
+
|
| 129 |
+
return group_elements
|
| 130 |
+
|
| 131 |
+
def _generate_reflection_group(self) -> List[np.ndarray]:
|
| 132 |
+
"""Generate group of reflections across coordinate axes."""
|
| 133 |
+
group_elements = []
|
| 134 |
+
|
| 135 |
+
# Identity
|
| 136 |
+
group_elements.append(np.eye(self.input_dim))
|
| 137 |
+
|
| 138 |
+
# Reflections across each coordinate axis
|
| 139 |
+
for i in range(self.input_dim):
|
| 140 |
+
reflection = np.eye(self.input_dim)
|
| 141 |
+
reflection[i, i] = -1
|
| 142 |
+
group_elements.append(reflection)
|
| 143 |
+
|
| 144 |
+
# Reflections across diagonal planes (for 2D and 3D)
|
| 145 |
+
if self.input_dim == 2:
|
| 146 |
+
# Reflection across y = x
|
| 147 |
+
diag_reflection = np.array([[0, 1], [1, 0]])
|
| 148 |
+
group_elements.append(diag_reflection)
|
| 149 |
+
|
| 150 |
+
# Reflection across y = -x
|
| 151 |
+
anti_diag_reflection = np.array([[0, -1], [-1, 0]])
|
| 152 |
+
group_elements.append(anti_diag_reflection)
|
| 153 |
+
|
| 154 |
+
return group_elements
|
| 155 |
+
|
| 156 |
+
def apply_group_actions(self, x: np.ndarray, group_name: str) -> np.ndarray:
|
| 157 |
+
"""Apply all group actions to input data."""
|
| 158 |
+
if x.ndim == 1:
|
| 159 |
+
x = x.reshape(1, -1)
|
| 160 |
+
|
| 161 |
+
group_elements = self.groups[group_name]
|
| 162 |
+
results = []
|
| 163 |
+
|
| 164 |
+
for element in group_elements:
|
| 165 |
+
if x.shape[1] == element.shape[0]:
|
| 166 |
+
transformed = x @ element.T
|
| 167 |
+
else:
|
| 168 |
+
# Handle dimension mismatch by padding or truncating
|
| 169 |
+
min_dim = min(x.shape[1], element.shape[0])
|
| 170 |
+
transformed = x[:, :min_dim] @ element[:min_dim, :min_dim].T
|
| 171 |
+
|
| 172 |
+
# Compute invariant features
|
| 173 |
+
norm = np.linalg.norm(transformed, axis=1, keepdims=True)
|
| 174 |
+
mean = np.mean(transformed, axis=1, keepdims=True)
|
| 175 |
+
std = np.std(transformed, axis=1, keepdims=True) + 1e-8
|
| 176 |
+
|
| 177 |
+
# Combine features
|
| 178 |
+
features = np.concatenate([norm, mean, std], axis=1)
|
| 179 |
+
results.append(features)
|
| 180 |
+
|
| 181 |
+
return np.concatenate(results, axis=1)
|
| 182 |
+
|
| 183 |
+
def forward(self, x: np.ndarray) -> np.ndarray:
|
| 184 |
+
"""Forward pass through group theory network."""
|
| 185 |
+
all_features = []
|
| 186 |
+
|
| 187 |
+
# Apply each group type
|
| 188 |
+
for group_name in self.group_types:
|
| 189 |
+
group_features = self.apply_group_actions(x, group_name)
|
| 190 |
+
all_features.append(group_features)
|
| 191 |
+
|
| 192 |
+
# Concatenate all features
|
| 193 |
+
combined_features = np.concatenate(all_features, axis=1)
|
| 194 |
+
|
| 195 |
+
# Linear combination to get desired output dimension
|
| 196 |
+
feature_dim = combined_features.shape[1]
|
| 197 |
+
if feature_dim >= self.output_dim:
|
| 198 |
+
# Take first output_dim features
|
| 199 |
+
output = combined_features[:, :self.output_dim]
|
| 200 |
+
else:
|
| 201 |
+
# Repeat features to reach output_dim
|
| 202 |
+
repeats = (self.output_dim + feature_dim - 1) // feature_dim
|
| 203 |
+
repeated = np.tile(combined_features, (1, repeats))
|
| 204 |
+
output = repeated[:, :self.output_dim]
|
| 205 |
+
|
| 206 |
+
return output
|
| 207 |
+
|
| 208 |
+
def predict(self, x: np.ndarray) -> np.ndarray:
|
| 209 |
+
"""Prediction method."""
|
| 210 |
+
return self.forward(x)
|
| 211 |
+
|
| 212 |
+
|
| 213 |
+
def test_rotation_invariance():
|
| 214 |
+
"""Test rotation invariance of the group theory network."""
|
| 215 |
+
print("=== Group Theory Network: Rotation Invariance Test ===\n")
|
| 216 |
+
|
| 217 |
+
# Create network with cyclic group
|
| 218 |
+
network = GroupTheoryNetwork(
|
| 219 |
+
input_dim=2,
|
| 220 |
+
group_types=["cyclic_8"],
|
| 221 |
+
output_dim=4
|
| 222 |
+
)
|
| 223 |
+
|
| 224 |
+
# Create test patterns
|
| 225 |
+
original_pattern = np.array([[1, 0], [0, 1], [1, 1]])
|
| 226 |
+
|
| 227 |
+
# Manual rotations for comparison
|
| 228 |
+
rotation_angles = [0, np.pi/4, np.pi/2, np.pi, 3*np.pi/2]
|
| 229 |
+
|
| 230 |
+
print("Testing rotation invariance:")
|
| 231 |
+
outputs = []
|
| 232 |
+
|
| 233 |
+
for angle in rotation_angles:
|
| 234 |
+
# Manually rotate the pattern
|
| 235 |
+
cos_a, sin_a = np.cos(angle), np.sin(angle)
|
| 236 |
+
rotation_matrix = np.array([[cos_a, -sin_a], [sin_a, cos_a]])
|
| 237 |
+
rotated_pattern = original_pattern @ rotation_matrix.T
|
| 238 |
+
|
| 239 |
+
# Get network output
|
| 240 |
+
output = network.predict(rotated_pattern)
|
| 241 |
+
outputs.append(output)
|
| 242 |
+
|
| 243 |
+
print(f" Rotation {angle:.2f} rad: mean output = {np.mean(output):.4f}")
|
| 244 |
+
|
| 245 |
+
# Check invariance (outputs should be similar)
|
| 246 |
+
output_array = np.array(outputs)
|
| 247 |
+
variance_across_rotations = np.var(output_array, axis=0)
|
| 248 |
+
mean_variance = np.mean(variance_across_rotations)
|
| 249 |
+
|
| 250 |
+
print(f"\nMean variance across rotations: {mean_variance:.6f}")
|
| 251 |
+
print("(Lower values indicate better rotation invariance)\n")
|
| 252 |
+
|
| 253 |
+
return outputs
|
| 254 |
+
|
| 255 |
+
|
| 256 |
+
def test_symmetry_detection():
|
| 257 |
+
"""Test the network's ability to detect different symmetries."""
|
| 258 |
+
print("=== Group Theory Network: Symmetry Detection ===\n")
|
| 259 |
+
|
| 260 |
+
# Create network with multiple group types
|
| 261 |
+
network = GroupTheoryNetwork(
|
| 262 |
+
input_dim=2,
|
| 263 |
+
group_types=["cyclic_4", "dihedral_4", "reflection"],
|
| 264 |
+
output_dim=6
|
| 265 |
+
)
|
| 266 |
+
|
| 267 |
+
# Define test patterns with different symmetries
|
| 268 |
+
patterns = {
|
| 269 |
+
"Square": np.array([[1, 1], [1, -1], [-1, -1], [-1, 1]]),
|
| 270 |
+
"Triangle": np.array([[1, 0], [-0.5, np.sqrt(3)/2], [-0.5, -np.sqrt(3)/2]]),
|
| 271 |
+
"Line": np.array([[1, 0], [0.5, 0], [0, 0], [-0.5, 0], [-1, 0]]),
|
| 272 |
+
"Circle": np.array([[np.cos(θ), np.sin(θ)] for θ in np.linspace(0, 2*np.pi, 8)]),
|
| 273 |
+
"Asymmetric": np.array([[1, 0], [0, 1], [0.3, 0.7], [0.8, 0.2]])
|
| 274 |
+
}
|
| 275 |
+
|
| 276 |
+
print("Symmetry detection results:")
|
| 277 |
+
pattern_outputs = {}
|
| 278 |
+
|
| 279 |
+
for pattern_name, pattern_points in patterns.items():
|
| 280 |
+
output = network.predict(pattern_points)
|
| 281 |
+
pattern_outputs[pattern_name] = output
|
| 282 |
+
|
| 283 |
+
print(f"\n{pattern_name}:")
|
| 284 |
+
print(f" Mean output: {np.mean(output, axis=0)}")
|
| 285 |
+
print(f" Output std: {np.std(output, axis=0)}")
|
| 286 |
+
|
| 287 |
+
return pattern_outputs
|
| 288 |
+
|
| 289 |
+
|
| 290 |
+
def test_group_composition():
|
| 291 |
+
"""Test composition of group operations."""
|
| 292 |
+
print("=== Group Theory Network: Group Composition ===\n")
|
| 293 |
+
|
| 294 |
+
network = GroupTheoryNetwork(
|
| 295 |
+
input_dim=3,
|
| 296 |
+
group_types=["symmetric_3"],
|
| 297 |
+
output_dim=3
|
| 298 |
+
)
|
| 299 |
+
|
| 300 |
+
# Test group properties
|
| 301 |
+
test_input = np.array([[1, 2, 3]])
|
| 302 |
+
|
| 303 |
+
print("Testing group composition properties:")
|
| 304 |
+
|
| 305 |
+
# Get all group elements
|
| 306 |
+
group_elements = network.groups["symmetric_3"]
|
| 307 |
+
|
| 308 |
+
# Test identity element (should be first)
|
| 309 |
+
identity_result = test_input @ group_elements[0].T
|
| 310 |
+
print(f"Identity transformation: {test_input[0]} → {identity_result[0]}")
|
| 311 |
+
|
| 312 |
+
# Test composition of operations
|
| 313 |
+
for i, g1 in enumerate(group_elements[:3]):
|
| 314 |
+
for j, g2 in enumerate(group_elements[:3]):
|
| 315 |
+
# Apply g1 then g2
|
| 316 |
+
intermediate = test_input @ g1.T
|
| 317 |
+
final = intermediate @ g2.T
|
| 318 |
+
|
| 319 |
+
# Apply composition g2∘g1
|
| 320 |
+
composition = g2 @ g1
|
| 321 |
+
direct = test_input @ composition.T
|
| 322 |
+
|
| 323 |
+
# Check if they're the same (within numerical precision)
|
| 324 |
+
difference = np.linalg.norm(final - direct)
|
| 325 |
+
print(f" g{j}∘g{i}: composition error = {difference:.8f}")
|
| 326 |
+
|
| 327 |
+
|
| 328 |
+
def test_invariant_features():
|
| 329 |
+
"""Test extraction of invariant features."""
|
| 330 |
+
print("=== Group Theory Network: Invariant Feature Extraction ===\n")
|
| 331 |
+
|
| 332 |
+
# Network for extracting rotation-invariant features
|
| 333 |
+
network = GroupTheoryNetwork(
|
| 334 |
+
input_dim=2,
|
| 335 |
+
group_types=["cyclic_16"], # Fine rotation sampling
|
| 336 |
+
output_dim=8
|
| 337 |
+
)
|
| 338 |
+
|
| 339 |
+
# Test patterns with known geometric properties
|
| 340 |
+
test_cases = [
|
| 341 |
+
("Unit Circle", np.array([[np.cos(θ), np.sin(θ)] for θ in np.linspace(0, 2*np.pi, 10)])),
|
| 342 |
+
("Ellipse", np.array([[2*np.cos(θ), np.sin(θ)] for θ in np.linspace(0, 2*np.pi, 10)])),
|
| 343 |
+
("Square", np.array([[1, 1], [1, -1], [-1, -1], [-1, 1]])),
|
| 344 |
+
("Random", np.random.randn(8, 2))
|
| 345 |
+
]
|
| 346 |
+
|
| 347 |
+
print("Invariant feature analysis:")
|
| 348 |
+
|
| 349 |
+
for case_name, points in test_cases:
|
| 350 |
+
# Original features
|
| 351 |
+
original_features = network.predict(points)
|
| 352 |
+
|
| 353 |
+
# Rotated version
|
| 354 |
+
rotation_45 = np.array([[np.cos(np.pi/4), -np.sin(np.pi/4)],
|
| 355 |
+
[np.sin(np.pi/4), np.cos(np.pi/4)]])
|
| 356 |
+
rotated_points = points @ rotation_45.T
|
| 357 |
+
rotated_features = network.predict(rotated_points)
|
| 358 |
+
|
| 359 |
+
# Measure feature consistency
|
| 360 |
+
feature_difference = np.linalg.norm(original_features - rotated_features)
|
| 361 |
+
relative_difference = feature_difference / (np.linalg.norm(original_features) + 1e-8)
|
| 362 |
+
|
| 363 |
+
print(f"\n{case_name}:")
|
| 364 |
+
print(f" Feature difference: {feature_difference:.6f}")
|
| 365 |
+
print(f" Relative difference: {relative_difference:.6f}")
|
| 366 |
+
print(f" Original features mean: {np.mean(original_features):.4f}")
|
| 367 |
+
print(f" Rotated features mean: {np.mean(rotated_features):.4f}")
|
| 368 |
+
|
| 369 |
+
|
| 370 |
+
if __name__ == "__main__":
|
| 371 |
+
print("Group Theory Algebraic Neural Network Demo\n")
|
| 372 |
+
print("="*60)
|
| 373 |
+
|
| 374 |
+
# Run tests
|
| 375 |
+
test_rotation_invariance()
|
| 376 |
+
test_symmetry_detection()
|
| 377 |
+
test_group_composition()
|
| 378 |
+
test_invariant_features()
|
| 379 |
+
|
| 380 |
+
print("\n" + "="*60)
|
| 381 |
+
print("Group theory demo completed successfully!")
|
examples/polynomial_network.py
ADDED
|
@@ -0,0 +1,289 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Polynomial-based Algebraic Neural Network
|
| 3 |
+
|
| 4 |
+
This example demonstrates a neural network that uses polynomial transformations
|
| 5 |
+
with coefficients derived from algebraic number theory.
|
| 6 |
+
"""
|
| 7 |
+
|
| 8 |
+
import numpy as np
|
| 9 |
+
import matplotlib.pyplot as plt
|
| 10 |
+
from typing import Tuple
|
| 11 |
+
import math
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
class PolynomialAlgebraicNetwork:
|
| 15 |
+
"""
|
| 16 |
+
Neural network using polynomial basis functions with algebraic coefficients.
|
| 17 |
+
"""
|
| 18 |
+
|
| 19 |
+
def __init__(self, input_dim: int, hidden_dim: int, output_dim: int, max_degree: int = 3):
|
| 20 |
+
self.input_dim = input_dim
|
| 21 |
+
self.hidden_dim = hidden_dim
|
| 22 |
+
self.output_dim = output_dim
|
| 23 |
+
self.max_degree = max_degree
|
| 24 |
+
|
| 25 |
+
# Generate polynomial coefficients using algebraic numbers
|
| 26 |
+
self.coefficients = self._generate_algebraic_coefficients()
|
| 27 |
+
|
| 28 |
+
def _generate_algebraic_coefficients(self) -> dict:
|
| 29 |
+
"""Generate coefficients using famous algebraic constants."""
|
| 30 |
+
coeffs = {}
|
| 31 |
+
|
| 32 |
+
# Golden ratio and related algebraic numbers
|
| 33 |
+
phi = (1 + math.sqrt(5)) / 2 # Golden ratio
|
| 34 |
+
phi_conjugate = (1 - math.sqrt(5)) / 2
|
| 35 |
+
|
| 36 |
+
# Silver ratio
|
| 37 |
+
silver = 1 + math.sqrt(2)
|
| 38 |
+
|
| 39 |
+
# Euler's number approximation using continued fractions
|
| 40 |
+
e_approx = 2.718281828
|
| 41 |
+
|
| 42 |
+
# Pi approximation
|
| 43 |
+
pi_approx = math.pi
|
| 44 |
+
|
| 45 |
+
algebraic_constants = [1, phi, phi_conjugate, silver, e_approx, pi_approx]
|
| 46 |
+
|
| 47 |
+
# Generate coefficients for input to hidden transformation
|
| 48 |
+
coeffs['input_hidden'] = np.zeros((self.hidden_dim, self.input_dim, self.max_degree + 1))
|
| 49 |
+
for i in range(self.hidden_dim):
|
| 50 |
+
for j in range(self.input_dim):
|
| 51 |
+
for k in range(self.max_degree + 1):
|
| 52 |
+
# Use algebraic constants in a systematic way
|
| 53 |
+
const_idx = (i + j + k) % len(algebraic_constants)
|
| 54 |
+
base_coeff = algebraic_constants[const_idx]
|
| 55 |
+
|
| 56 |
+
# Scale by factorial to maintain stability
|
| 57 |
+
coeffs['input_hidden'][i, j, k] = base_coeff / math.factorial(k + 1)
|
| 58 |
+
|
| 59 |
+
# Generate coefficients for hidden to output transformation
|
| 60 |
+
coeffs['hidden_output'] = np.zeros((self.output_dim, self.hidden_dim, self.max_degree + 1))
|
| 61 |
+
for i in range(self.output_dim):
|
| 62 |
+
for j in range(self.hidden_dim):
|
| 63 |
+
for k in range(self.max_degree + 1):
|
| 64 |
+
const_idx = (i + j + k + 1) % len(algebraic_constants)
|
| 65 |
+
base_coeff = algebraic_constants[const_idx]
|
| 66 |
+
coeffs['hidden_output'][i, j, k] = base_coeff / math.factorial(k + 1)
|
| 67 |
+
|
| 68 |
+
return coeffs
|
| 69 |
+
|
| 70 |
+
def _polynomial_activation(self, x: np.ndarray, coeffs: np.ndarray) -> np.ndarray:
|
| 71 |
+
"""Apply polynomial activation with given coefficients."""
|
| 72 |
+
if x.ndim == 1:
|
| 73 |
+
x = x.reshape(1, -1)
|
| 74 |
+
|
| 75 |
+
batch_size, input_size = x.shape
|
| 76 |
+
output_size = coeffs.shape[0]
|
| 77 |
+
|
| 78 |
+
result = np.zeros((batch_size, output_size))
|
| 79 |
+
|
| 80 |
+
for i in range(output_size):
|
| 81 |
+
for j in range(input_size):
|
| 82 |
+
for degree in range(self.max_degree + 1):
|
| 83 |
+
if degree == 0:
|
| 84 |
+
poly_term = coeffs[i, j, degree]
|
| 85 |
+
else:
|
| 86 |
+
poly_term = coeffs[i, j, degree] * (x[:, j] ** degree)
|
| 87 |
+
result[:, i] += poly_term
|
| 88 |
+
|
| 89 |
+
return result
|
| 90 |
+
|
| 91 |
+
def forward(self, x: np.ndarray) -> np.ndarray:
|
| 92 |
+
"""Forward pass through the polynomial network."""
|
| 93 |
+
# Input to hidden layer
|
| 94 |
+
hidden = self._polynomial_activation(x, self.coefficients['input_hidden'])
|
| 95 |
+
|
| 96 |
+
# Apply hyperbolic tangent for stability
|
| 97 |
+
hidden = np.tanh(hidden)
|
| 98 |
+
|
| 99 |
+
# Hidden to output layer
|
| 100 |
+
output = self._polynomial_activation(hidden, self.coefficients['hidden_output'])
|
| 101 |
+
|
| 102 |
+
return output
|
| 103 |
+
|
| 104 |
+
def predict(self, x: np.ndarray) -> np.ndarray:
|
| 105 |
+
"""Prediction method."""
|
| 106 |
+
return self.forward(x)
|
| 107 |
+
|
| 108 |
+
|
| 109 |
+
def test_function_approximation():
|
| 110 |
+
"""Test the polynomial network on function approximation tasks."""
|
| 111 |
+
print("=== Polynomial Network Function Approximation ===\n")
|
| 112 |
+
|
| 113 |
+
# Create network
|
| 114 |
+
network = PolynomialAlgebraicNetwork(input_dim=1, hidden_dim=5, output_dim=1, max_degree=3)
|
| 115 |
+
|
| 116 |
+
# Test on various mathematical functions
|
| 117 |
+
test_functions = [
|
| 118 |
+
("Sine", lambda x: np.sin(2 * np.pi * x)),
|
| 119 |
+
("Cosine", lambda x: np.cos(2 * np.pi * x)),
|
| 120 |
+
("Quadratic", lambda x: x**2 - 0.5*x + 0.1),
|
| 121 |
+
("Cubic", lambda x: x**3 - x**2 + 0.5*x),
|
| 122 |
+
("Exponential", lambda x: np.exp(-x**2))
|
| 123 |
+
]
|
| 124 |
+
|
| 125 |
+
x_test = np.linspace(-1, 1, 50).reshape(-1, 1)
|
| 126 |
+
|
| 127 |
+
results = {}
|
| 128 |
+
for func_name, func in test_functions:
|
| 129 |
+
y_true = func(x_test.flatten())
|
| 130 |
+
y_pred = network.predict(x_test).flatten()
|
| 131 |
+
|
| 132 |
+
# Calculate approximation error
|
| 133 |
+
mse = np.mean((y_true - y_pred)**2)
|
| 134 |
+
mae = np.mean(np.abs(y_true - y_pred))
|
| 135 |
+
|
| 136 |
+
results[func_name] = {
|
| 137 |
+
'mse': mse,
|
| 138 |
+
'mae': mae,
|
| 139 |
+
'y_true': y_true,
|
| 140 |
+
'y_pred': y_pred
|
| 141 |
+
}
|
| 142 |
+
|
| 143 |
+
print(f"{func_name}:")
|
| 144 |
+
print(f" MSE: {mse:.6f}")
|
| 145 |
+
print(f" MAE: {mae:.6f}")
|
| 146 |
+
print()
|
| 147 |
+
|
| 148 |
+
return results, x_test
|
| 149 |
+
|
| 150 |
+
|
| 151 |
+
def test_pattern_recognition():
|
| 152 |
+
"""Test polynomial network on 2D pattern recognition."""
|
| 153 |
+
print("=== Polynomial Network Pattern Recognition ===\n")
|
| 154 |
+
|
| 155 |
+
# Create 2D network
|
| 156 |
+
network = PolynomialAlgebraicNetwork(input_dim=2, hidden_dim=8, output_dim=3, max_degree=2)
|
| 157 |
+
|
| 158 |
+
# Generate test patterns
|
| 159 |
+
def generate_circle_points(n_points=20, radius=0.8):
|
| 160 |
+
angles = np.linspace(0, 2*np.pi, n_points, endpoint=False)
|
| 161 |
+
return np.column_stack([radius * np.cos(angles), radius * np.sin(angles)])
|
| 162 |
+
|
| 163 |
+
def generate_square_points(n_points=20, side=1.0):
|
| 164 |
+
points_per_side = n_points // 4
|
| 165 |
+
side_points = []
|
| 166 |
+
|
| 167 |
+
# Bottom side
|
| 168 |
+
x = np.linspace(-side/2, side/2, points_per_side)
|
| 169 |
+
y = np.full(points_per_side, -side/2)
|
| 170 |
+
side_points.extend(zip(x, y))
|
| 171 |
+
|
| 172 |
+
# Right side
|
| 173 |
+
x = np.full(points_per_side, side/2)
|
| 174 |
+
y = np.linspace(-side/2, side/2, points_per_side)
|
| 175 |
+
side_points.extend(zip(x, y))
|
| 176 |
+
|
| 177 |
+
# Top side
|
| 178 |
+
x = np.linspace(side/2, -side/2, points_per_side)
|
| 179 |
+
y = np.full(points_per_side, side/2)
|
| 180 |
+
side_points.extend(zip(x, y))
|
| 181 |
+
|
| 182 |
+
# Left side
|
| 183 |
+
x = np.full(points_per_side, -side/2)
|
| 184 |
+
y = np.linspace(side/2, -side/2, points_per_side)
|
| 185 |
+
side_points.extend(zip(x, y))
|
| 186 |
+
|
| 187 |
+
return np.array(side_points[:n_points])
|
| 188 |
+
|
| 189 |
+
def generate_triangle_points(n_points=18, size=0.8):
|
| 190 |
+
angles = np.array([0, 2*np.pi/3, 4*np.pi/3])
|
| 191 |
+
vertices = size * np.column_stack([np.cos(angles), np.sin(angles)])
|
| 192 |
+
|
| 193 |
+
points = []
|
| 194 |
+
points_per_edge = n_points // 3
|
| 195 |
+
|
| 196 |
+
for i in range(3):
|
| 197 |
+
start = vertices[i]
|
| 198 |
+
end = vertices[(i + 1) % 3]
|
| 199 |
+
edge_points = np.linspace(start, end, points_per_edge, endpoint=False)
|
| 200 |
+
points.extend(edge_points)
|
| 201 |
+
|
| 202 |
+
return np.array(points[:n_points])
|
| 203 |
+
|
| 204 |
+
# Generate patterns
|
| 205 |
+
circles = generate_circle_points()
|
| 206 |
+
squares = generate_square_points()
|
| 207 |
+
triangles = generate_triangle_points()
|
| 208 |
+
|
| 209 |
+
# Process with network
|
| 210 |
+
circle_outputs = network.predict(circles)
|
| 211 |
+
square_outputs = network.predict(squares)
|
| 212 |
+
triangle_outputs = network.predict(triangles)
|
| 213 |
+
|
| 214 |
+
# Analyze outputs
|
| 215 |
+
print("Circle pattern analysis:")
|
| 216 |
+
print(f" Mean output: {np.mean(circle_outputs, axis=0)}")
|
| 217 |
+
print(f" Std output: {np.std(circle_outputs, axis=0)}")
|
| 218 |
+
|
| 219 |
+
print("\nSquare pattern analysis:")
|
| 220 |
+
print(f" Mean output: {np.mean(square_outputs, axis=0)}")
|
| 221 |
+
print(f" Std output: {np.std(square_outputs, axis=0)}")
|
| 222 |
+
|
| 223 |
+
print("\nTriangle pattern analysis:")
|
| 224 |
+
print(f" Mean output: {np.mean(triangle_outputs, axis=0)}")
|
| 225 |
+
print(f" Std output: {np.std(triangle_outputs, axis=0)}")
|
| 226 |
+
|
| 227 |
+
return {
|
| 228 |
+
'circles': (circles, circle_outputs),
|
| 229 |
+
'squares': (squares, square_outputs),
|
| 230 |
+
'triangles': (triangles, triangle_outputs)
|
| 231 |
+
}
|
| 232 |
+
|
| 233 |
+
|
| 234 |
+
def demonstrate_coefficient_properties():
|
| 235 |
+
"""Demonstrate properties of the algebraic coefficients."""
|
| 236 |
+
print("=== Algebraic Coefficient Properties ===\n")
|
| 237 |
+
|
| 238 |
+
network = PolynomialAlgebraicNetwork(input_dim=3, hidden_dim=4, output_dim=2)
|
| 239 |
+
|
| 240 |
+
# Analyze coefficient matrices
|
| 241 |
+
input_hidden_coeffs = network.coefficients['input_hidden']
|
| 242 |
+
hidden_output_coeffs = network.coefficients['hidden_output']
|
| 243 |
+
|
| 244 |
+
print("Input-Hidden Coefficients:")
|
| 245 |
+
print(f" Shape: {input_hidden_coeffs.shape}")
|
| 246 |
+
print(f" Min coefficient: {np.min(input_hidden_coeffs):.6f}")
|
| 247 |
+
print(f" Max coefficient: {np.max(input_hidden_coeffs):.6f}")
|
| 248 |
+
print(f" Mean coefficient: {np.mean(input_hidden_coeffs):.6f}")
|
| 249 |
+
print(f" Std coefficient: {np.std(input_hidden_coeffs):.6f}")
|
| 250 |
+
|
| 251 |
+
print("\nHidden-Output Coefficients:")
|
| 252 |
+
print(f" Shape: {hidden_output_coeffs.shape}")
|
| 253 |
+
print(f" Min coefficient: {np.min(hidden_output_coeffs):.6f}")
|
| 254 |
+
print(f" Max coefficient: {np.max(hidden_output_coeffs):.6f}")
|
| 255 |
+
print(f" Mean coefficient: {np.mean(hidden_output_coeffs):.6f}")
|
| 256 |
+
print(f" Std coefficient: {np.std(hidden_output_coeffs):.6f}")
|
| 257 |
+
|
| 258 |
+
# Test stability with different input magnitudes
|
| 259 |
+
print("\nStability Analysis:")
|
| 260 |
+
test_inputs = [
|
| 261 |
+
np.array([[0.1, 0.1, 0.1]]),
|
| 262 |
+
np.array([[0.5, 0.5, 0.5]]),
|
| 263 |
+
np.array([[1.0, 1.0, 1.0]]),
|
| 264 |
+
np.array([[2.0, 2.0, 2.0]]),
|
| 265 |
+
]
|
| 266 |
+
|
| 267 |
+
for i, test_input in enumerate(test_inputs):
|
| 268 |
+
output = network.predict(test_input)
|
| 269 |
+
magnitude = np.linalg.norm(test_input)
|
| 270 |
+
output_magnitude = np.linalg.norm(output)
|
| 271 |
+
print(f" Input magnitude {magnitude:.1f} → Output magnitude {output_magnitude:.6f}")
|
| 272 |
+
|
| 273 |
+
|
| 274 |
+
if __name__ == "__main__":
|
| 275 |
+
# Run demonstrations
|
| 276 |
+
print("Polynomial Algebraic Neural Network Demo\n")
|
| 277 |
+
print("="*50)
|
| 278 |
+
|
| 279 |
+
# Function approximation test
|
| 280 |
+
func_results, x_vals = test_function_approximation()
|
| 281 |
+
|
| 282 |
+
# Pattern recognition test
|
| 283 |
+
pattern_results = test_pattern_recognition()
|
| 284 |
+
|
| 285 |
+
# Coefficient analysis
|
| 286 |
+
demonstrate_coefficient_properties()
|
| 287 |
+
|
| 288 |
+
print("\n" + "="*50)
|
| 289 |
+
print("Demo completed successfully!")
|
examples/uncomputable_networks.py
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""
|
| 3 |
+
Uncomputable Neural Network Examples
|
| 4 |
+
|
| 5 |
+
This script demonstrates the various types of uncomputable neural network layers
|
| 6 |
+
and their theoretical foundations.
|
| 7 |
+
"""
|
| 8 |
+
|
| 9 |
+
import numpy as np
|
| 10 |
+
import sys
|
| 11 |
+
import os
|
| 12 |
+
|
| 13 |
+
# Add parent directory to path
|
| 14 |
+
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
| 15 |
+
|
| 16 |
+
from algebraic_neural_network import (
|
| 17 |
+
HaltingOracleLayer, KolmogorovComplexityLayer, BusyBeaverLayer,
|
| 18 |
+
NonRecursiveLayer, create_uncomputable_network
|
| 19 |
+
)
|
| 20 |
+
|
| 21 |
+
def demonstrate_halting_oracle():
|
| 22 |
+
"""Demonstrate the Halting Oracle Layer."""
|
| 23 |
+
print("=== Halting Oracle Layer Demonstration ===\n")
|
| 24 |
+
|
| 25 |
+
print("The Halting Oracle Layer simulates access to a halting oracle,")
|
| 26 |
+
print("which can theoretically answer whether a program halts on given input.")
|
| 27 |
+
print("This is uncomputable in general, but we provide bounded approximations.\n")
|
| 28 |
+
|
| 29 |
+
layer = HaltingOracleLayer(4, 3, max_iterations=1000)
|
| 30 |
+
|
| 31 |
+
# Test with different "program" inputs
|
| 32 |
+
test_cases = [
|
| 33 |
+
([1, 0, 0, 0], "Simple program"),
|
| 34 |
+
([0.5, 0.5, 0.5, 0.5], "Balanced program"),
|
| 35 |
+
([0.9, 0.9, 0.9, 0.9], "Complex program"),
|
| 36 |
+
([0.1, 0.1, 0.1, 0.1], "Minimal program"),
|
| 37 |
+
]
|
| 38 |
+
|
| 39 |
+
for i, (input_data, description) in enumerate(test_cases, 1):
|
| 40 |
+
input_array = np.array(input_data).reshape(1, -1)
|
| 41 |
+
output = layer.forward(input_array)
|
| 42 |
+
|
| 43 |
+
print(f"Test {i}: {description}")
|
| 44 |
+
print(f" Input: {input_data}")
|
| 45 |
+
print(f" Halting probabilities: {output[0]}")
|
| 46 |
+
print(f" Interpretation: {['Unlikely to halt' if p < 0.5 else 'Likely to halt' for p in output[0]]}")
|
| 47 |
+
print()
|
| 48 |
+
|
| 49 |
+
def demonstrate_kolmogorov_complexity():
|
| 50 |
+
"""Demonstrate the Kolmogorov Complexity Layer."""
|
| 51 |
+
print("=== Kolmogorov Complexity Layer Demonstration ===\n")
|
| 52 |
+
|
| 53 |
+
print("The Kolmogorov Complexity Layer approximates the Kolmogorov complexity")
|
| 54 |
+
print("of inputs - the length of the shortest program that outputs the input.")
|
| 55 |
+
print("True Kolmogorov complexity is uncomputable, but we use compression heuristics.\n")
|
| 56 |
+
|
| 57 |
+
layer = KolmogorovComplexityLayer(4, 3, precision=8)
|
| 58 |
+
|
| 59 |
+
# Test with different complexity patterns
|
| 60 |
+
test_cases = [
|
| 61 |
+
([1, 1, 1, 1], "Highly regular pattern"),
|
| 62 |
+
([1, 2, 3, 4], "Simple arithmetic sequence"),
|
| 63 |
+
([0.123, 0.456, 0.789, 0.012], "Seemingly random"),
|
| 64 |
+
([1, 1, 2, 3], "Fibonacci-like pattern"),
|
| 65 |
+
]
|
| 66 |
+
|
| 67 |
+
for i, (input_data, description) in enumerate(test_cases, 1):
|
| 68 |
+
input_array = np.array(input_data).reshape(1, -1)
|
| 69 |
+
output = layer.forward(input_array)
|
| 70 |
+
|
| 71 |
+
print(f"Test {i}: {description}")
|
| 72 |
+
print(f" Input: {input_data}")
|
| 73 |
+
print(f" Complexity estimates: {output[0]}")
|
| 74 |
+
print(f" Average complexity: {np.mean(output[0]):.3f}")
|
| 75 |
+
print()
|
| 76 |
+
|
| 77 |
+
def demonstrate_busy_beaver():
|
| 78 |
+
"""Demonstrate the Busy Beaver Layer."""
|
| 79 |
+
print("=== Busy Beaver Layer Demonstration ===\n")
|
| 80 |
+
|
| 81 |
+
print("The Busy Beaver Layer uses the Busy Beaver function BB(n),")
|
| 82 |
+
print("which gives the maximum number of steps a halting n-state Turing machine can take.")
|
| 83 |
+
print("BB(n) is uncomputable for general n, but known for small values.\n")
|
| 84 |
+
|
| 85 |
+
layer = BusyBeaverLayer(4, 3)
|
| 86 |
+
|
| 87 |
+
# Known BB values for reference
|
| 88 |
+
print("Known Busy Beaver values:")
|
| 89 |
+
print(" BB(1) = 1")
|
| 90 |
+
print(" BB(2) = 4")
|
| 91 |
+
print(" BB(3) = 6")
|
| 92 |
+
print(" BB(4) = 13")
|
| 93 |
+
print(" BB(5) ≥ 4098")
|
| 94 |
+
print()
|
| 95 |
+
|
| 96 |
+
# Test with inputs that map to different BB parameters
|
| 97 |
+
test_cases = [
|
| 98 |
+
([0.1, 0, 0, 0], "Maps to small machine"),
|
| 99 |
+
([0.5, 0.5, 0, 0], "Maps to medium machine"),
|
| 100 |
+
([1.0, 1.0, 1.0, 1.0], "Maps to larger machine"),
|
| 101 |
+
]
|
| 102 |
+
|
| 103 |
+
for i, (input_data, description) in enumerate(test_cases, 1):
|
| 104 |
+
input_array = np.array(input_data).reshape(1, -1)
|
| 105 |
+
output = layer.forward(input_array)
|
| 106 |
+
|
| 107 |
+
print(f"Test {i}: {description}")
|
| 108 |
+
print(f" Input: {input_data}")
|
| 109 |
+
print(f" Log BB values: {output[0]}")
|
| 110 |
+
print(f" Approximate BB values: {np.exp(output[0]) - 1}")
|
| 111 |
+
print()
|
| 112 |
+
|
| 113 |
+
def demonstrate_non_recursive():
|
| 114 |
+
"""Demonstrate the Non-Recursive Layer."""
|
| 115 |
+
print("=== Non-Recursive Layer Demonstration ===\n")
|
| 116 |
+
|
| 117 |
+
print("The Non-Recursive Layer simulates operations on computably enumerable")
|
| 118 |
+
print("but non-recursive sets. These are sets that can be enumerated but")
|
| 119 |
+
print("for which membership cannot be decided algorithmically.\n")
|
| 120 |
+
|
| 121 |
+
layer = NonRecursiveLayer(4, 3, enumeration_bound=1000)
|
| 122 |
+
|
| 123 |
+
print(f"The layer simulates a c.e. set with {len(layer.ce_set)} enumerated elements")
|
| 124 |
+
print("using the rule: numbers expressible as sum of two squares\n")
|
| 125 |
+
|
| 126 |
+
# Test membership for different inputs
|
| 127 |
+
test_cases = [
|
| 128 |
+
([1, 0, 0, 0], "Simple input"),
|
| 129 |
+
([2, 3, 5, 7], "Prime-like pattern"),
|
| 130 |
+
([1, 4, 9, 16], "Perfect squares"),
|
| 131 |
+
([0.5, 0.25, 0.125, 0.0625], "Geometric sequence"),
|
| 132 |
+
]
|
| 133 |
+
|
| 134 |
+
for i, (input_data, description) in enumerate(test_cases, 1):
|
| 135 |
+
input_array = np.array(input_data).reshape(1, -1)
|
| 136 |
+
output = layer.forward(input_array)
|
| 137 |
+
|
| 138 |
+
print(f"Test {i}: {description}")
|
| 139 |
+
print(f" Input: {input_data}")
|
| 140 |
+
print(f" Membership probabilities: {output[0]}")
|
| 141 |
+
print(f" Interpretations: {['Not enumerated' if p == 0.5 else ('In set' if p == 1.0 else 'Not in set') for p in output[0]]}")
|
| 142 |
+
print()
|
| 143 |
+
|
| 144 |
+
def demonstrate_complete_network():
|
| 145 |
+
"""Demonstrate a complete uncomputable neural network."""
|
| 146 |
+
print("=== Complete Uncomputable Neural Network ===\n")
|
| 147 |
+
|
| 148 |
+
print("This demonstrates a full network combining all uncomputable layer types.")
|
| 149 |
+
print("The network processes inputs through:")
|
| 150 |
+
print(" 1. Halting Oracle Layer (4→5)")
|
| 151 |
+
print(" 2. Kolmogorov Complexity Layer (5→4)")
|
| 152 |
+
print(" 3. Busy Beaver Layer (4→3)")
|
| 153 |
+
print(" 4. Non-Recursive Layer (3→2)")
|
| 154 |
+
print()
|
| 155 |
+
|
| 156 |
+
network = create_uncomputable_network()
|
| 157 |
+
|
| 158 |
+
# Test with various input patterns
|
| 159 |
+
test_cases = [
|
| 160 |
+
"Random data",
|
| 161 |
+
"Structured sequence",
|
| 162 |
+
"Constant values",
|
| 163 |
+
"Alternating pattern"
|
| 164 |
+
]
|
| 165 |
+
|
| 166 |
+
np.random.seed(42)
|
| 167 |
+
test_inputs = [
|
| 168 |
+
np.random.randn(4),
|
| 169 |
+
np.array([1, 2, 3, 4]) / 4.0,
|
| 170 |
+
np.ones(4) * 0.5,
|
| 171 |
+
np.array([1, -1, 1, -1]) * 0.5
|
| 172 |
+
]
|
| 173 |
+
|
| 174 |
+
for i, (input_data, description) in enumerate(zip(test_inputs, test_cases), 1):
|
| 175 |
+
output = network.predict(input_data.reshape(1, -1))
|
| 176 |
+
|
| 177 |
+
print(f"Test {i}: {description}")
|
| 178 |
+
print(f" Input: {input_data}")
|
| 179 |
+
print(f" Final output: {output[0]}")
|
| 180 |
+
print(f" Output interpretation: Decision values for uncomputable questions")
|
| 181 |
+
print()
|
| 182 |
+
|
| 183 |
+
# Demonstrate deterministic behavior
|
| 184 |
+
print("Deterministic behavior verification:")
|
| 185 |
+
test_input = np.random.randn(1, 4)
|
| 186 |
+
output1 = network.predict(test_input)
|
| 187 |
+
output2 = network.predict(test_input)
|
| 188 |
+
difference = np.linalg.norm(output1 - output2)
|
| 189 |
+
print(f" Same input produces identical outputs: {difference < 1e-10}")
|
| 190 |
+
print(f" Difference: {difference:.2e}")
|
| 191 |
+
|
| 192 |
+
def main():
|
| 193 |
+
"""Run all uncomputable neural network demonstrations."""
|
| 194 |
+
print("🔬 Uncomputable Neural Networks Examples")
|
| 195 |
+
print("=" * 60)
|
| 196 |
+
print("Exploring the theoretical boundaries of computation through")
|
| 197 |
+
print("neural networks that incorporate uncomputable functions.\n")
|
| 198 |
+
|
| 199 |
+
demonstrate_halting_oracle()
|
| 200 |
+
print("\n" + "─" * 60 + "\n")
|
| 201 |
+
|
| 202 |
+
demonstrate_kolmogorov_complexity()
|
| 203 |
+
print("\n" + "─" * 60 + "\n")
|
| 204 |
+
|
| 205 |
+
demonstrate_busy_beaver()
|
| 206 |
+
print("\n" + "─" * 60 + "\n")
|
| 207 |
+
|
| 208 |
+
demonstrate_non_recursive()
|
| 209 |
+
print("\n" + "─" * 60 + "\n")
|
| 210 |
+
|
| 211 |
+
demonstrate_complete_network()
|
| 212 |
+
|
| 213 |
+
print("\n" + "=" * 60)
|
| 214 |
+
print("✅ Uncomputable neural network demonstrations completed!")
|
| 215 |
+
print("📚 See theory/uncomputable_networks.md for mathematical foundations.")
|
| 216 |
+
|
| 217 |
+
if __name__ == "__main__":
|
| 218 |
+
main()
|
test_comprehensive.py
ADDED
|
@@ -0,0 +1,327 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""
|
| 3 |
+
Comprehensive test suite for Algebraic Neural Networks
|
| 4 |
+
|
| 5 |
+
This script tests all components of the algebraic neural network implementation
|
| 6 |
+
to ensure everything works correctly together.
|
| 7 |
+
"""
|
| 8 |
+
|
| 9 |
+
import sys
|
| 10 |
+
import os
|
| 11 |
+
import numpy as np
|
| 12 |
+
|
| 13 |
+
# Add the parent directory to the path to import our modules
|
| 14 |
+
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
| 15 |
+
|
| 16 |
+
# Import all our implementations
|
| 17 |
+
from algebraic_neural_network import (
|
| 18 |
+
AlgebraicNeuralNetwork, PolynomialLayer, GroupTheoryLayer,
|
| 19 |
+
GeometricAlgebraLayer, HaltingOracleLayer, KolmogorovComplexityLayer,
|
| 20 |
+
BusyBeaverLayer, NonRecursiveLayer, create_sample_network, create_uncomputable_network
|
| 21 |
+
)
|
| 22 |
+
|
| 23 |
+
def test_basic_functionality():
|
| 24 |
+
"""Test basic functionality of all layer types."""
|
| 25 |
+
print("=== Testing Basic Functionality ===\n")
|
| 26 |
+
|
| 27 |
+
# Test data
|
| 28 |
+
test_input = np.random.randn(3, 4)
|
| 29 |
+
print(f"Test input shape: {test_input.shape}")
|
| 30 |
+
|
| 31 |
+
# Test individual layers
|
| 32 |
+
print("\n1. Testing PolynomialLayer:")
|
| 33 |
+
poly_layer = PolynomialLayer(4, 3, degree=2)
|
| 34 |
+
poly_output = poly_layer.forward(test_input)
|
| 35 |
+
print(f" Input: {test_input.shape} → Output: {poly_output.shape}")
|
| 36 |
+
print(f" Output range: [{np.min(poly_output):.3f}, {np.max(poly_output):.3f}]")
|
| 37 |
+
|
| 38 |
+
print("\n2. Testing GroupTheoryLayer:")
|
| 39 |
+
group_layer = GroupTheoryLayer(4, 3, group_order=6)
|
| 40 |
+
group_output = group_layer.forward(test_input)
|
| 41 |
+
print(f" Input: {test_input.shape} → Output: {group_output.shape}")
|
| 42 |
+
print(f" Output range: [{np.min(group_output):.3f}, {np.max(group_output):.3f}]")
|
| 43 |
+
|
| 44 |
+
print("\n3. Testing GeometricAlgebraLayer:")
|
| 45 |
+
geo_layer = GeometricAlgebraLayer(4, 3)
|
| 46 |
+
geo_output = geo_layer.forward(test_input)
|
| 47 |
+
print(f" Input: {test_input.shape} → Output: {geo_output.shape}")
|
| 48 |
+
print(f" Output range: [{np.min(geo_output):.3f}, {np.max(geo_output):.3f}]")
|
| 49 |
+
|
| 50 |
+
return True
|
| 51 |
+
|
| 52 |
+
def test_network_composition():
|
| 53 |
+
"""Test composition of multiple algebraic layers."""
|
| 54 |
+
print("\n=== Testing Network Composition ===\n")
|
| 55 |
+
|
| 56 |
+
# Create a complete network
|
| 57 |
+
network = AlgebraicNeuralNetwork()
|
| 58 |
+
network.add_layer(PolynomialLayer(5, 8, degree=2))
|
| 59 |
+
network.add_layer(GroupTheoryLayer(8, 6, group_order=8))
|
| 60 |
+
network.add_layer(GeometricAlgebraLayer(6, 3))
|
| 61 |
+
network.add_layer(PolynomialLayer(3, 2, degree=1))
|
| 62 |
+
|
| 63 |
+
# Test with different input sizes
|
| 64 |
+
test_cases = [
|
| 65 |
+
np.random.randn(1, 5), # Single sample
|
| 66 |
+
np.random.randn(5, 5), # Multiple samples
|
| 67 |
+
np.random.randn(10, 5), # Larger batch
|
| 68 |
+
]
|
| 69 |
+
|
| 70 |
+
for i, test_case in enumerate(test_cases):
|
| 71 |
+
output = network.predict(test_case)
|
| 72 |
+
print(f"Test case {i+1}:")
|
| 73 |
+
print(f" Input shape: {test_case.shape}")
|
| 74 |
+
print(f" Output shape: {output.shape}")
|
| 75 |
+
print(f" Output mean: {np.mean(output):.4f}")
|
| 76 |
+
print(f" Output std: {np.std(output):.4f}")
|
| 77 |
+
|
| 78 |
+
return True
|
| 79 |
+
|
| 80 |
+
def test_deterministic_behavior():
|
| 81 |
+
"""Test that the networks are deterministic."""
|
| 82 |
+
print("\n=== Testing Deterministic Behavior ===\n")
|
| 83 |
+
|
| 84 |
+
# Create network
|
| 85 |
+
network = create_sample_network()
|
| 86 |
+
|
| 87 |
+
# Same input should produce same output
|
| 88 |
+
test_input = np.random.randn(3, 4)
|
| 89 |
+
|
| 90 |
+
output1 = network.predict(test_input)
|
| 91 |
+
output2 = network.predict(test_input)
|
| 92 |
+
output3 = network.predict(test_input)
|
| 93 |
+
|
| 94 |
+
# Check if outputs are identical
|
| 95 |
+
diff_12 = np.linalg.norm(output1 - output2)
|
| 96 |
+
diff_13 = np.linalg.norm(output1 - output3)
|
| 97 |
+
diff_23 = np.linalg.norm(output2 - output3)
|
| 98 |
+
|
| 99 |
+
print(f"Input shape: {test_input.shape}")
|
| 100 |
+
print(f"Output 1 vs 2 difference: {diff_12:.10f}")
|
| 101 |
+
print(f"Output 1 vs 3 difference: {diff_13:.10f}")
|
| 102 |
+
print(f"Output 2 vs 3 difference: {diff_23:.10f}")
|
| 103 |
+
|
| 104 |
+
is_deterministic = (diff_12 < 1e-10) and (diff_13 < 1e-10) and (diff_23 < 1e-10)
|
| 105 |
+
print(f"Network is deterministic: {is_deterministic}")
|
| 106 |
+
|
| 107 |
+
return is_deterministic
|
| 108 |
+
|
| 109 |
+
def test_mathematical_properties():
|
| 110 |
+
"""Test mathematical properties of algebraic operations."""
|
| 111 |
+
print("\n=== Testing Mathematical Properties ===\n")
|
| 112 |
+
|
| 113 |
+
# Test polynomial layer properties
|
| 114 |
+
print("1. Polynomial Layer Properties:")
|
| 115 |
+
poly_layer = PolynomialLayer(2, 3, degree=2)
|
| 116 |
+
|
| 117 |
+
# Linearity test (for degree 1 components)
|
| 118 |
+
x1 = np.array([[1, 0]])
|
| 119 |
+
x2 = np.array([[0, 1]])
|
| 120 |
+
x_sum = np.array([[1, 1]])
|
| 121 |
+
|
| 122 |
+
y1 = poly_layer.forward(x1)
|
| 123 |
+
y2 = poly_layer.forward(x2)
|
| 124 |
+
y_sum = poly_layer.forward(x_sum)
|
| 125 |
+
|
| 126 |
+
# Note: Due to higher degree terms, this won't be exactly linear
|
| 127 |
+
linearity_error = np.linalg.norm(y_sum - (y1 + y2))
|
| 128 |
+
print(f" Linearity deviation (expected for degree > 1): {linearity_error:.4f}")
|
| 129 |
+
|
| 130 |
+
# Test group theory layer properties
|
| 131 |
+
print("\n2. Group Theory Layer Properties:")
|
| 132 |
+
group_layer = GroupTheoryLayer(2, 4, group_order=4)
|
| 133 |
+
|
| 134 |
+
# Test with unit vectors
|
| 135 |
+
unit_x = np.array([[1, 0]])
|
| 136 |
+
unit_y = np.array([[0, 1]])
|
| 137 |
+
|
| 138 |
+
out_x = group_layer.forward(unit_x)
|
| 139 |
+
out_y = group_layer.forward(unit_y)
|
| 140 |
+
|
| 141 |
+
print(f" Unit X output norm: {np.linalg.norm(out_x):.4f}")
|
| 142 |
+
print(f" Unit Y output norm: {np.linalg.norm(out_y):.4f}")
|
| 143 |
+
|
| 144 |
+
# Test geometric algebra layer properties
|
| 145 |
+
print("\n3. Geometric Algebra Layer Properties:")
|
| 146 |
+
geo_layer = GeometricAlgebraLayer(3, 4)
|
| 147 |
+
|
| 148 |
+
# Test with orthogonal vectors
|
| 149 |
+
e1 = np.array([[1, 0, 0]])
|
| 150 |
+
e2 = np.array([[0, 1, 0]])
|
| 151 |
+
e3 = np.array([[0, 0, 1]])
|
| 152 |
+
|
| 153 |
+
out1 = geo_layer.forward(e1)
|
| 154 |
+
out2 = geo_layer.forward(e2)
|
| 155 |
+
out3 = geo_layer.forward(e3)
|
| 156 |
+
|
| 157 |
+
print(f" e1 output: {out1[0]}")
|
| 158 |
+
print(f" e2 output: {out2[0]}")
|
| 159 |
+
print(f" e3 output: {out3[0]}")
|
| 160 |
+
|
| 161 |
+
return True
|
| 162 |
+
|
| 163 |
+
def test_uncomputable_layers():
|
| 164 |
+
"""Test uncomputable neural network layers."""
|
| 165 |
+
print("\n=== Testing Uncomputable Layers ===\n")
|
| 166 |
+
|
| 167 |
+
test_input = np.random.randn(3, 4)
|
| 168 |
+
|
| 169 |
+
# Test Halting Oracle Layer
|
| 170 |
+
print("1. Testing HaltingOracleLayer:")
|
| 171 |
+
halting_layer = HaltingOracleLayer(4, 3, max_iterations=100)
|
| 172 |
+
halting_output = halting_layer.forward(test_input)
|
| 173 |
+
print(f" Input: {test_input.shape} → Output: {halting_output.shape}")
|
| 174 |
+
print(f" Output range: [{np.min(halting_output):.3f}, {np.max(halting_output):.3f}]")
|
| 175 |
+
# Outputs should be probabilities between 0 and 1
|
| 176 |
+
assert np.all(halting_output >= 0) and np.all(halting_output <= 1), "Halting oracle outputs must be in [0,1]"
|
| 177 |
+
|
| 178 |
+
# Test Kolmogorov Complexity Layer
|
| 179 |
+
print("\n2. Testing KolmogorovComplexityLayer:")
|
| 180 |
+
kolmogorov_layer = KolmogorovComplexityLayer(4, 3, precision=6)
|
| 181 |
+
kolmogorov_output = kolmogorov_layer.forward(test_input)
|
| 182 |
+
print(f" Input: {test_input.shape} → Output: {kolmogorov_output.shape}")
|
| 183 |
+
print(f" Output range: [{np.min(kolmogorov_output):.3f}, {np.max(kolmogorov_output):.3f}]")
|
| 184 |
+
# Complexity should be non-negative
|
| 185 |
+
assert np.all(kolmogorov_output >= 0), "Kolmogorov complexity must be non-negative"
|
| 186 |
+
|
| 187 |
+
# Test Busy Beaver Layer
|
| 188 |
+
print("\n3. Testing BusyBeaverLayer:")
|
| 189 |
+
bb_layer = BusyBeaverLayer(4, 3)
|
| 190 |
+
bb_output = bb_layer.forward(test_input)
|
| 191 |
+
print(f" Input: {test_input.shape} → Output: {bb_output.shape}")
|
| 192 |
+
print(f" Output range: [{np.min(bb_output):.3f}, {np.max(bb_output):.3f}]")
|
| 193 |
+
# BB values should be positive
|
| 194 |
+
assert np.all(bb_output > 0), "Busy Beaver values must be positive"
|
| 195 |
+
|
| 196 |
+
# Test Non-Recursive Layer
|
| 197 |
+
print("\n4. Testing NonRecursiveLayer:")
|
| 198 |
+
nr_layer = NonRecursiveLayer(4, 3, enumeration_bound=100)
|
| 199 |
+
nr_output = nr_layer.forward(test_input)
|
| 200 |
+
print(f" Input: {test_input.shape} → Output: {nr_output.shape}")
|
| 201 |
+
print(f" Output range: [{np.min(nr_output):.3f}, {np.max(nr_output):.3f}]")
|
| 202 |
+
# Membership values should be in [0,1]
|
| 203 |
+
assert np.all(nr_output >= 0) and np.all(nr_output <= 1), "Membership values must be in [0,1]"
|
| 204 |
+
|
| 205 |
+
# Test deterministic behavior of uncomputable layers
|
| 206 |
+
print("\n5. Testing deterministic behavior:")
|
| 207 |
+
halting_output2 = halting_layer.forward(test_input)
|
| 208 |
+
diff = np.linalg.norm(halting_output - halting_output2)
|
| 209 |
+
print(f" Determinism check: difference = {diff:.10f}")
|
| 210 |
+
assert diff < 1e-10, "Uncomputable layers must be deterministic"
|
| 211 |
+
|
| 212 |
+
return True
|
| 213 |
+
|
| 214 |
+
def test_uncomputable_network_composition():
|
| 215 |
+
"""Test composition of uncomputable neural network."""
|
| 216 |
+
print("\n=== Testing Uncomputable Network Composition ===\n")
|
| 217 |
+
|
| 218 |
+
# Create uncomputable network
|
| 219 |
+
network = create_uncomputable_network()
|
| 220 |
+
|
| 221 |
+
# Test with different input sizes
|
| 222 |
+
test_cases = [
|
| 223 |
+
(1, 4), # Single sample
|
| 224 |
+
(5, 4), # Multiple samples
|
| 225 |
+
(10, 4) # Larger batch
|
| 226 |
+
]
|
| 227 |
+
|
| 228 |
+
for i, (batch_size, input_size) in enumerate(test_cases, 1):
|
| 229 |
+
test_input = np.random.randn(batch_size, input_size)
|
| 230 |
+
output = network.predict(test_input)
|
| 231 |
+
|
| 232 |
+
print(f"Test case {i}:")
|
| 233 |
+
print(f" Input shape: {test_input.shape}")
|
| 234 |
+
print(f" Output shape: {output.shape}")
|
| 235 |
+
print(f" Output mean: {np.mean(output):.4f}")
|
| 236 |
+
print(f" Output std: {np.std(output):.4f}")
|
| 237 |
+
|
| 238 |
+
return True
|
| 239 |
+
|
| 240 |
+
def test_edge_cases():
|
| 241 |
+
"""Test edge cases and boundary conditions."""
|
| 242 |
+
print("\n=== Testing Edge Cases ===\n")
|
| 243 |
+
|
| 244 |
+
network = create_sample_network()
|
| 245 |
+
|
| 246 |
+
# Test with zero input
|
| 247 |
+
zero_input = np.zeros((2, 4))
|
| 248 |
+
zero_output = network.predict(zero_input)
|
| 249 |
+
print(f"1. Zero input test:")
|
| 250 |
+
print(f" Input: all zeros, shape {zero_input.shape}")
|
| 251 |
+
print(f" Output: {zero_output}")
|
| 252 |
+
|
| 253 |
+
# Test with very small inputs
|
| 254 |
+
small_input = np.ones((2, 4)) * 1e-6
|
| 255 |
+
small_output = network.predict(small_input)
|
| 256 |
+
print(f"\n2. Small input test:")
|
| 257 |
+
print(f" Input: 1e-6, shape {small_input.shape}")
|
| 258 |
+
print(f" Output range: [{np.min(small_output):.8f}, {np.max(small_output):.8f}]")
|
| 259 |
+
|
| 260 |
+
# Test with large inputs
|
| 261 |
+
large_input = np.ones((2, 4)) * 100
|
| 262 |
+
large_output = network.predict(large_input)
|
| 263 |
+
print(f"\n3. Large input test:")
|
| 264 |
+
print(f" Input: 100, shape {large_input.shape}")
|
| 265 |
+
print(f" Output range: [{np.min(large_output):.3f}, {np.max(large_output):.3f}]")
|
| 266 |
+
|
| 267 |
+
# Test with single sample
|
| 268 |
+
single_input = np.random.randn(4) # 1D input
|
| 269 |
+
single_output = network.predict(single_input)
|
| 270 |
+
print(f"\n4. Single sample test:")
|
| 271 |
+
print(f" Input shape: {single_input.shape}")
|
| 272 |
+
print(f" Output shape: {single_output.shape}")
|
| 273 |
+
|
| 274 |
+
return True
|
| 275 |
+
|
| 276 |
+
def run_comprehensive_test():
|
| 277 |
+
"""Run all tests and report results."""
|
| 278 |
+
print("Comprehensive Algebraic Neural Network Test Suite")
|
| 279 |
+
print("="*60)
|
| 280 |
+
|
| 281 |
+
tests = [
|
| 282 |
+
("Basic Functionality", test_basic_functionality),
|
| 283 |
+
("Network Composition", test_network_composition),
|
| 284 |
+
("Deterministic Behavior", test_deterministic_behavior),
|
| 285 |
+
("Mathematical Properties", test_mathematical_properties),
|
| 286 |
+
("Uncomputable Layers", test_uncomputable_layers),
|
| 287 |
+
("Uncomputable Network Composition", test_uncomputable_network_composition),
|
| 288 |
+
("Edge Cases", test_edge_cases),
|
| 289 |
+
]
|
| 290 |
+
|
| 291 |
+
results = []
|
| 292 |
+
|
| 293 |
+
for test_name, test_func in tests:
|
| 294 |
+
try:
|
| 295 |
+
result = test_func()
|
| 296 |
+
results.append((test_name, result, None))
|
| 297 |
+
print(f"\n✓ {test_name}: PASSED")
|
| 298 |
+
except Exception as e:
|
| 299 |
+
results.append((test_name, False, str(e)))
|
| 300 |
+
print(f"\n✗ {test_name}: FAILED - {e}")
|
| 301 |
+
|
| 302 |
+
# Summary
|
| 303 |
+
print("\n" + "="*60)
|
| 304 |
+
print("TEST SUMMARY")
|
| 305 |
+
print("="*60)
|
| 306 |
+
|
| 307 |
+
passed = sum(1 for _, result, _ in results if result)
|
| 308 |
+
total = len(results)
|
| 309 |
+
|
| 310 |
+
for test_name, result, error in results:
|
| 311 |
+
status = "PASS" if result else "FAIL"
|
| 312 |
+
print(f"{test_name:.<30} {status}")
|
| 313 |
+
if error:
|
| 314 |
+
print(f" Error: {error}")
|
| 315 |
+
|
| 316 |
+
print(f"\nOverall: {passed}/{total} tests passed")
|
| 317 |
+
|
| 318 |
+
if passed == total:
|
| 319 |
+
print("🎉 All tests passed! Algebraic Neural Network implementation is working correctly.")
|
| 320 |
+
else:
|
| 321 |
+
print("⚠️ Some tests failed. Please review the implementation.")
|
| 322 |
+
|
| 323 |
+
return passed == total
|
| 324 |
+
|
| 325 |
+
if __name__ == "__main__":
|
| 326 |
+
success = run_comprehensive_test()
|
| 327 |
+
sys.exit(0 if success else 1)
|
theory/algebraic_foundations.md
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Algebraic Foundations of Non-Trained Neural Networks
|
| 2 |
+
|
| 3 |
+
## Introduction
|
| 4 |
+
|
| 5 |
+
Algebraic Neural Networks (ANNs) represent a fundamental departure from traditional neural networks by eliminating the need for gradient-based training. Instead, they leverage mathematical structures from abstract algebra to perform computations.
|
| 6 |
+
|
| 7 |
+
## Mathematical Foundations
|
| 8 |
+
|
| 9 |
+
### 1. Algebraic Structures
|
| 10 |
+
|
| 11 |
+
#### Groups
|
| 12 |
+
A group (G, ∘) is a set G with a binary operation ∘ that satisfies:
|
| 13 |
+
- **Closure**: ∀ a, b ∈ G, a ∘ b ∈ G
|
| 14 |
+
- **Associativity**: ∀ a, b, c ∈ G, (a ∘ b) ∘ c = a ∘ (b ∘ c)
|
| 15 |
+
- **Identity**: ∃ e ∈ G such that ∀ a ∈ G, e ∘ a = a ∘ e = a
|
| 16 |
+
- **Inverse**: ∀ a ∈ G, ∃ a⁻¹ ∈ G such that a ∘ a⁻¹ = a⁻¹ ∘ a = e
|
| 17 |
+
|
| 18 |
+
In our neural networks, we use group actions to transform input data systematically.
|
| 19 |
+
|
| 20 |
+
#### Rings and Fields
|
| 21 |
+
A ring (R, +, ×) provides two operations (addition and multiplication) that interact via distributive laws. Fields extend rings by requiring multiplicative inverses for non-zero elements.
|
| 22 |
+
|
| 23 |
+
#### Algebras
|
| 24 |
+
An algebra over a field F is a vector space A over F equipped with a bilinear multiplication operation.
|
| 25 |
+
|
| 26 |
+
### 2. Polynomial Algebras
|
| 27 |
+
|
| 28 |
+
Polynomial algebras form the basis for our polynomial layers. For a field F and variables x₁, x₂, ..., xₙ, the polynomial algebra F[x₁, x₂, ..., xₙ] consists of all polynomials in these variables.
|
| 29 |
+
|
| 30 |
+
#### Key Properties:
|
| 31 |
+
- **Linearity**: P(ax + by) = aP(x) + bP(y) for linear terms
|
| 32 |
+
- **Homomorphism**: Polynomial mappings preserve algebraic structure
|
| 33 |
+
- **Universal Property**: Polynomial algebras are initial objects in certain categories
|
| 34 |
+
|
| 35 |
+
### 3. Geometric Algebra (Clifford Algebra)
|
| 36 |
+
|
| 37 |
+
Geometric algebra extends vector algebra with a geometric product that unifies dot and cross products.
|
| 38 |
+
|
| 39 |
+
For vectors a and b:
|
| 40 |
+
**Geometric Product**: ab = a·b + a∧b
|
| 41 |
+
|
| 42 |
+
Where:
|
| 43 |
+
- a·b is the dot product (scalar)
|
| 44 |
+
- a∧b is the outer product (bivector)
|
| 45 |
+
|
| 46 |
+
#### Properties:
|
| 47 |
+
- **Associative**: (ab)c = a(bc)
|
| 48 |
+
- **Distributive**: a(b + c) = ab + ac
|
| 49 |
+
- **Contraction**: a² = |a|² (for vectors)
|
| 50 |
+
|
| 51 |
+
### 4. Group Actions in Neural Networks
|
| 52 |
+
|
| 53 |
+
A group action of G on a set X is a function G × X → X such that:
|
| 54 |
+
- Identity action: ex = x for all x ∈ X
|
| 55 |
+
- Compatibility: (gh)x = g(hx)
|
| 56 |
+
|
| 57 |
+
In neural networks, we use group actions to:
|
| 58 |
+
- Transform input features systematically
|
| 59 |
+
- Preserve important symmetries
|
| 60 |
+
- Generate multiple representations
|
| 61 |
+
|
| 62 |
+
## Algebraic Neural Network Architecture
|
| 63 |
+
|
| 64 |
+
### Layer Types
|
| 65 |
+
|
| 66 |
+
#### 1. Polynomial Layers
|
| 67 |
+
Transform inputs using polynomial functions with algebraically determined coefficients:
|
| 68 |
+
|
| 69 |
+
```
|
| 70 |
+
f(x) = Σᵢ₌₁ⁿ Σⱼ₌₁ᵈ (aᵢⱼ/j!) xʲ
|
| 71 |
+
```
|
| 72 |
+
|
| 73 |
+
Where aᵢⱼ are coefficients derived from algebraic sequences (e.g., involving golden ratio φ).
|
| 74 |
+
|
| 75 |
+
#### 2. Group Theory Layers
|
| 76 |
+
Apply group elements to transform inputs:
|
| 77 |
+
|
| 78 |
+
```
|
| 79 |
+
y = g · x for g ∈ G
|
| 80 |
+
```
|
| 81 |
+
|
| 82 |
+
Common groups used:
|
| 83 |
+
- **Cyclic groups**: Cₙ = {e, g, g², ..., gⁿ⁻¹}
|
| 84 |
+
- **Dihedral groups**: Symmetries of regular polygons
|
| 85 |
+
- **Symmetric groups**: Permutations of elements
|
| 86 |
+
|
| 87 |
+
#### 3. Geometric Algebra Layers
|
| 88 |
+
Use geometric product operations:
|
| 89 |
+
|
| 90 |
+
```
|
| 91 |
+
y = x ∘ eᵢ
|
| 92 |
+
```
|
| 93 |
+
|
| 94 |
+
Where eᵢ are basis elements of the geometric algebra.
|
| 95 |
+
|
| 96 |
+
### Composition of Layers
|
| 97 |
+
|
| 98 |
+
Layers compose through function composition, preserving algebraic properties:
|
| 99 |
+
|
| 100 |
+
```
|
| 101 |
+
f = fₙ ∘ fₙ₋₁ ∘ ... ∘ f₁
|
| 102 |
+
```
|
| 103 |
+
|
| 104 |
+
## Advantages of Algebraic Approach
|
| 105 |
+
|
| 106 |
+
### 1. No Training Required
|
| 107 |
+
- Networks are constructed using mathematical principles
|
| 108 |
+
- No gradient computation needed
|
| 109 |
+
- No optimization algorithms required
|
| 110 |
+
|
| 111 |
+
### 2. Deterministic Behavior
|
| 112 |
+
- Outputs are completely determined by algebraic rules
|
| 113 |
+
- Reproducible results
|
| 114 |
+
- No randomness in weights
|
| 115 |
+
|
| 116 |
+
### 3. Mathematical Interpretability
|
| 117 |
+
- Clear mathematical meaning for each operation
|
| 118 |
+
- Theoretical guarantees on behavior
|
| 119 |
+
- Connection to established mathematical theory
|
| 120 |
+
|
| 121 |
+
### 4. Computational Efficiency
|
| 122 |
+
- No backpropagation required
|
| 123 |
+
- Direct computation of outputs
|
| 124 |
+
- Parallel computation of group actions
|
| 125 |
+
|
| 126 |
+
## Theoretical Guarantees
|
| 127 |
+
|
| 128 |
+
### Universal Approximation
|
| 129 |
+
Under certain conditions, algebraic neural networks can approximate continuous functions:
|
| 130 |
+
|
| 131 |
+
**Theorem**: Let f: Rⁿ → Rᵐ be a continuous function on a compact set K. Then for any ε > 0, there exists an algebraic neural network F such that ||f - F||∞ < ε on K.
|
| 132 |
+
|
| 133 |
+
### Stability Properties
|
| 134 |
+
Algebraic operations provide stability guarantees:
|
| 135 |
+
- Polynomial layers have bounded derivatives
|
| 136 |
+
- Group actions preserve norms (for orthogonal groups)
|
| 137 |
+
- Geometric algebra operations maintain geometric relationships
|
| 138 |
+
|
| 139 |
+
## Applications
|
| 140 |
+
|
| 141 |
+
### 1. Signal Processing
|
| 142 |
+
- Fourier transforms as group actions
|
| 143 |
+
- Wavelet transforms using algebraic structures
|
| 144 |
+
- Filter design using polynomial algebras
|
| 145 |
+
|
| 146 |
+
### 2. Computer Vision
|
| 147 |
+
- Geometric transformations using group theory
|
| 148 |
+
- Feature extraction using geometric algebra
|
| 149 |
+
- Invariant pattern recognition
|
| 150 |
+
|
| 151 |
+
### 3. Scientific Computing
|
| 152 |
+
- Solving differential equations
|
| 153 |
+
- Numerical integration
|
| 154 |
+
- Optimization problems with algebraic constraints
|
| 155 |
+
|
| 156 |
+
## References
|
| 157 |
+
|
| 158 |
+
1. Clifford, W.K. (1878). "Applications of Grassmann's Extensive Algebra"
|
| 159 |
+
2. Doran, C. & Lasenby, A. (2003). "Geometric Algebra for Physicists"
|
| 160 |
+
3. Rotman, J.J. (2012). "A First Course in Abstract Algebra"
|
| 161 |
+
4. MacLane, S. & Birkhoff, G. (1999). "Algebra"
|
| 162 |
+
5. Cybenko, G. (1989). "Approximation by Superpositions of a Sigmoidal Function"
|
theory/examples.md
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Worked Examples of Algebraic Neural Networks
|
| 2 |
+
|
| 3 |
+
## Example 1: Polynomial Network for Function Approximation
|
| 4 |
+
|
| 5 |
+
### Problem
|
| 6 |
+
Approximate the function f(x, y) = x² + 2xy + y² using an algebraic neural network.
|
| 7 |
+
|
| 8 |
+
### Solution
|
| 9 |
+
|
| 10 |
+
```python
|
| 11 |
+
import numpy as np
|
| 12 |
+
from algebraic_neural_network import PolynomialLayer
|
| 13 |
+
|
| 14 |
+
# Create a polynomial layer
|
| 15 |
+
poly_layer = PolynomialLayer(input_size=2, output_size=1, degree=2)
|
| 16 |
+
|
| 17 |
+
# Test points
|
| 18 |
+
test_points = np.array([
|
| 19 |
+
[1, 1], # f(1,1) = 1 + 2 + 1 = 4
|
| 20 |
+
[2, 3], # f(2,3) = 4 + 12 + 9 = 25
|
| 21 |
+
[0, 1], # f(0,1) = 0 + 0 + 1 = 1
|
| 22 |
+
[-1, 2] # f(-1,2) = 1 - 4 + 4 = 1
|
| 23 |
+
])
|
| 24 |
+
|
| 25 |
+
# Apply the polynomial transformation
|
| 26 |
+
output = poly_layer.forward(test_points)
|
| 27 |
+
print("Polynomial approximation results:", output.flatten())
|
| 28 |
+
```
|
| 29 |
+
|
| 30 |
+
### Mathematical Analysis
|
| 31 |
+
The polynomial layer generates coefficients using the golden ratio φ = (1 + √5)/2:
|
| 32 |
+
- For output neuron 1: coefficient matrix uses φ¹ and φ²
|
| 33 |
+
- The transformation applies: y = Σᵢ Σⱼ (aᵢⱼ/j!) xʲ
|
| 34 |
+
|
| 35 |
+
## Example 2: Group Theory Network for Rotation Invariance
|
| 36 |
+
|
| 37 |
+
### Problem
|
| 38 |
+
Create a network that recognizes patterns invariant under rotations.
|
| 39 |
+
|
| 40 |
+
### Solution
|
| 41 |
+
|
| 42 |
+
```python
|
| 43 |
+
import numpy as np
|
| 44 |
+
from algebraic_neural_network import GroupTheoryLayer
|
| 45 |
+
|
| 46 |
+
# Create a group theory layer using 8-fold rotational symmetry
|
| 47 |
+
group_layer = GroupTheoryLayer(input_size=2, output_size=4, group_order=8)
|
| 48 |
+
|
| 49 |
+
# Test with a simple pattern (vector pointing in different directions)
|
| 50 |
+
patterns = np.array([
|
| 51 |
+
[1, 0], # Point along x-axis
|
| 52 |
+
[0, 1], # Point along y-axis
|
| 53 |
+
[1/√2, 1/√2], # Point along 45° diagonal
|
| 54 |
+
[-1, 0] # Point along negative x-axis
|
| 55 |
+
])
|
| 56 |
+
|
| 57 |
+
# Apply group transformations
|
| 58 |
+
transformed = group_layer.forward(patterns)
|
| 59 |
+
print("Group theory transformation results:")
|
| 60 |
+
print(transformed)
|
| 61 |
+
```
|
| 62 |
+
|
| 63 |
+
### Mathematical Analysis
|
| 64 |
+
The group theory layer applies rotations from the cyclic group C₈:
|
| 65 |
+
- Rotation angles: 0°, 45°, 90°, 135°, 180°, 225°, 270°, 315°
|
| 66 |
+
- Each rotation is represented by a 2×2 rotation matrix
|
| 67 |
+
- The norm of the transformed vector provides rotation-invariant features
|
| 68 |
+
|
| 69 |
+
## Example 3: Geometric Algebra Network for 3D Processing
|
| 70 |
+
|
| 71 |
+
### Problem
|
| 72 |
+
Process 3D geometric data using geometric algebra operations.
|
| 73 |
+
|
| 74 |
+
### Solution
|
| 75 |
+
|
| 76 |
+
```python
|
| 77 |
+
import numpy as np
|
| 78 |
+
from algebraic_neural_network import GeometricAlgebraLayer
|
| 79 |
+
|
| 80 |
+
# Create geometric algebra layer
|
| 81 |
+
geo_layer = GeometricAlgebraLayer(input_size=3, output_size=4)
|
| 82 |
+
|
| 83 |
+
# 3D vectors representing different geometric entities
|
| 84 |
+
vectors = np.array([
|
| 85 |
+
[1, 0, 0], # Unit vector along x
|
| 86 |
+
[0, 1, 0], # Unit vector along y
|
| 87 |
+
[0, 0, 1], # Unit vector along z
|
| 88 |
+
[1, 1, 1] # Diagonal vector
|
| 89 |
+
])
|
| 90 |
+
|
| 91 |
+
# Apply geometric algebra transformations
|
| 92 |
+
geo_output = geo_layer.forward(vectors)
|
| 93 |
+
print("Geometric algebra results:")
|
| 94 |
+
print(geo_output)
|
| 95 |
+
```
|
| 96 |
+
|
| 97 |
+
### Mathematical Analysis
|
| 98 |
+
The geometric algebra layer computes:
|
| 99 |
+
- Scalar products: a·b
|
| 100 |
+
- Vector products: a∧b (bivectors)
|
| 101 |
+
- Trivector products: a∧b∧c
|
| 102 |
+
- Mixed products combining all grades
|
| 103 |
+
|
| 104 |
+
## Example 4: Complete Network for Pattern Classification
|
| 105 |
+
|
| 106 |
+
### Problem
|
| 107 |
+
Build a complete algebraic neural network for classifying 2D patterns.
|
| 108 |
+
|
| 109 |
+
### Solution
|
| 110 |
+
|
| 111 |
+
```python
|
| 112 |
+
from algebraic_neural_network import AlgebraicNeuralNetwork, PolynomialLayer, GroupTheoryLayer
|
| 113 |
+
|
| 114 |
+
# Create network architecture
|
| 115 |
+
network = AlgebraicNeuralNetwork()
|
| 116 |
+
network.add_layer(PolynomialLayer(2, 4, degree=2)) # Feature extraction
|
| 117 |
+
network.add_layer(GroupTheoryLayer(4, 3, group_order=6)) # Symmetry processing
|
| 118 |
+
network.add_layer(PolynomialLayer(3, 1, degree=1)) # Final classification
|
| 119 |
+
|
| 120 |
+
# Test patterns
|
| 121 |
+
circle_points = np.array([
|
| 122 |
+
[np.cos(θ), np.sin(θ)] for θ in np.linspace(0, 2*np.pi, 8)
|
| 123 |
+
])
|
| 124 |
+
|
| 125 |
+
square_points = np.array([
|
| 126 |
+
[1, 1], [1, -1], [-1, -1], [-1, 1],
|
| 127 |
+
[1, 0], [0, 1], [-1, 0], [0, -1]
|
| 128 |
+
])
|
| 129 |
+
|
| 130 |
+
# Classify patterns
|
| 131 |
+
circle_scores = network.predict(circle_points)
|
| 132 |
+
square_scores = network.predict(square_points)
|
| 133 |
+
|
| 134 |
+
print("Circle pattern scores:", np.mean(circle_scores))
|
| 135 |
+
print("Square pattern scores:", np.mean(square_scores))
|
| 136 |
+
```
|
| 137 |
+
|
| 138 |
+
### Analysis
|
| 139 |
+
This network demonstrates:
|
| 140 |
+
1. **Feature Extraction**: Polynomial layer extracts nonlinear features
|
| 141 |
+
2. **Symmetry Processing**: Group theory layer handles rotational symmetries
|
| 142 |
+
3. **Classification**: Final layer provides decision boundary
|
| 143 |
+
|
| 144 |
+
## Example 5: Time Series Processing with Algebraic Networks
|
| 145 |
+
|
| 146 |
+
### Problem
|
| 147 |
+
Process time series data using algebraic transformations.
|
| 148 |
+
|
| 149 |
+
### Solution
|
| 150 |
+
|
| 151 |
+
```python
|
| 152 |
+
import numpy as np
|
| 153 |
+
|
| 154 |
+
def create_time_series_network():
|
| 155 |
+
network = AlgebraicNeuralNetwork()
|
| 156 |
+
# Window-based polynomial features
|
| 157 |
+
network.add_layer(PolynomialLayer(5, 6, degree=2)) # 5-point window
|
| 158 |
+
# Temporal symmetries
|
| 159 |
+
network.add_layer(GroupTheoryLayer(6, 4, group_order=4))
|
| 160 |
+
# Final prediction
|
| 161 |
+
network.add_layer(PolynomialLayer(4, 1, degree=1))
|
| 162 |
+
return network
|
| 163 |
+
|
| 164 |
+
# Generate sample time series
|
| 165 |
+
t = np.linspace(0, 4*np.pi, 100)
|
| 166 |
+
signal = np.sin(t) + 0.3*np.sin(3*t) + 0.1*np.random.randn(100)
|
| 167 |
+
|
| 168 |
+
# Create windows of 5 consecutive points
|
| 169 |
+
windows = np.array([signal[i:i+5] for i in range(len(signal)-4)])
|
| 170 |
+
|
| 171 |
+
# Process with algebraic network
|
| 172 |
+
ts_network = create_time_series_network()
|
| 173 |
+
predictions = ts_network.predict(windows)
|
| 174 |
+
|
| 175 |
+
print(f"Processed {len(windows)} time windows")
|
| 176 |
+
print(f"Prediction range: [{np.min(predictions):.3f}, {np.max(predictions):.3f}]")
|
| 177 |
+
```
|
| 178 |
+
|
| 179 |
+
### Analysis
|
| 180 |
+
This demonstrates algebraic networks for temporal data:
|
| 181 |
+
- **Windowing**: Convert time series to fixed-size vectors
|
| 182 |
+
- **Polynomial Features**: Capture local nonlinear patterns
|
| 183 |
+
- **Temporal Symmetries**: Handle time-shift invariances
|
| 184 |
+
|
| 185 |
+
## Performance Characteristics
|
| 186 |
+
|
| 187 |
+
### Computational Complexity
|
| 188 |
+
- **Polynomial Layers**: O(nd) where n is input size, d is degree
|
| 189 |
+
- **Group Theory Layers**: O(ng) where g is group order
|
| 190 |
+
- **Geometric Algebra Layers**: O(n²) for geometric products
|
| 191 |
+
|
| 192 |
+
### Memory Requirements
|
| 193 |
+
- **Fixed Coefficients**: No weight storage needed
|
| 194 |
+
- **Intermediate Results**: Only temporary computation storage
|
| 195 |
+
- **Total Memory**: O(n) where n is largest layer size
|
| 196 |
+
|
| 197 |
+
### Accuracy Analysis
|
| 198 |
+
Algebraic networks provide:
|
| 199 |
+
- **Consistency**: Same input always produces same output
|
| 200 |
+
- **Stability**: Small input changes → small output changes
|
| 201 |
+
- **Interpretability**: Mathematical meaning for each operation
|
| 202 |
+
|
| 203 |
+
## Practical Considerations
|
| 204 |
+
|
| 205 |
+
### When to Use Algebraic Networks
|
| 206 |
+
- **Known Mathematical Structure**: Problem has clear algebraic properties
|
| 207 |
+
- **No Training Data**: When gradient-based training isn't feasible
|
| 208 |
+
- **Interpretability Required**: Need mathematical understanding of operations
|
| 209 |
+
- **Real-time Processing**: Fast, deterministic computation needed
|
| 210 |
+
|
| 211 |
+
### Limitations
|
| 212 |
+
- **Limited Expressivity**: May not capture all possible patterns
|
| 213 |
+
- **Parameter Selection**: Choosing group orders, polynomial degrees
|
| 214 |
+
- **Scaling**: Performance with very high-dimensional data
|
| 215 |
+
|
| 216 |
+
### Extensions
|
| 217 |
+
- **Adaptive Coefficients**: Use algebraic sequences that adapt to data
|
| 218 |
+
- **Hybrid Networks**: Combine with traditional neural networks
|
| 219 |
+
- **Custom Algebras**: Develop problem-specific algebraic structures
|
theory/uncomputable_networks.md
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Uncomputable Neural Networks
|
| 2 |
+
|
| 3 |
+
## Introduction
|
| 4 |
+
|
| 5 |
+
Uncomputable Neural Networks represent a theoretical extension of non-trained neural networks that incorporate uncomputable functions and non-algorithmic operations. These networks explore the boundaries of computation and demonstrate concepts from theoretical computer science.
|
| 6 |
+
|
| 7 |
+
## Mathematical Foundations
|
| 8 |
+
|
| 9 |
+
### 1. Computability Theory
|
| 10 |
+
|
| 11 |
+
#### Computable vs Uncomputable Functions
|
| 12 |
+
- **Computable functions**: Can be computed by a Turing machine in finite time
|
| 13 |
+
- **Uncomputable functions**: Cannot be computed by any algorithm (e.g., halting problem)
|
| 14 |
+
|
| 15 |
+
#### The Halting Problem
|
| 16 |
+
The halting problem asks: Given a program P and input I, will P halt on I?
|
| 17 |
+
This is formally uncomputable - no algorithm can solve it for all cases.
|
| 18 |
+
|
| 19 |
+
### 2. Oracle Machines
|
| 20 |
+
|
| 21 |
+
An Oracle machine is a theoretical Turing machine with access to an "oracle" that can answer questions about uncomputable problems in constant time.
|
| 22 |
+
|
| 23 |
+
#### Oracle Operations
|
| 24 |
+
- **Halting Oracle**: O_H(P,I) = 1 if program P halts on input I, 0 otherwise
|
| 25 |
+
- **Kolmogorov Oracle**: O_K(x) returns the Kolmogorov complexity of string x
|
| 26 |
+
- **Busy Beaver Oracle**: O_BB(n) returns the nth Busy Beaver number
|
| 27 |
+
|
| 28 |
+
### 3. Hypercomputation
|
| 29 |
+
|
| 30 |
+
Hypercomputation refers to computational models that can solve uncomputable problems:
|
| 31 |
+
- Infinite time Turing machines
|
| 32 |
+
- Analog computers with real number precision
|
| 33 |
+
- Quantum computers with hypothetical capabilities
|
| 34 |
+
|
| 35 |
+
## Uncomputable Neural Network Architecture
|
| 36 |
+
|
| 37 |
+
### Layer Types
|
| 38 |
+
|
| 39 |
+
#### 1. Halting Oracle Layer
|
| 40 |
+
Simulates access to a halting oracle for specific problem domains:
|
| 41 |
+
|
| 42 |
+
```
|
| 43 |
+
f(x) = O_H(encode(x), input_program)
|
| 44 |
+
```
|
| 45 |
+
|
| 46 |
+
Where `encode(x)` transforms the input into a program representation.
|
| 47 |
+
|
| 48 |
+
#### 2. Kolmogorov Complexity Layer
|
| 49 |
+
Approximates Kolmogorov complexity using compression-based heuristics:
|
| 50 |
+
|
| 51 |
+
```
|
| 52 |
+
f(x) = K_approx(x) = min{|p| : U(p) = x, |p| ≤ threshold}
|
| 53 |
+
```
|
| 54 |
+
|
| 55 |
+
#### 3. Busy Beaver Layer
|
| 56 |
+
Uses known Busy Beaver values and approximations for larger inputs:
|
| 57 |
+
|
| 58 |
+
```
|
| 59 |
+
f(x) = BB(⌊log₂(||x||)⌋)
|
| 60 |
+
```
|
| 61 |
+
|
| 62 |
+
#### 4. Non-Recursive Enumeration Layer
|
| 63 |
+
Operates on sets that are computably enumerable but not computable:
|
| 64 |
+
|
| 65 |
+
```
|
| 66 |
+
f(x) = indicator_function(x ∈ RE_set)
|
| 67 |
+
```
|
| 68 |
+
|
| 69 |
+
### Composition and Determinism
|
| 70 |
+
|
| 71 |
+
Despite incorporating uncomputable concepts, these networks maintain practical determinism through:
|
| 72 |
+
- Finite approximations of infinite processes
|
| 73 |
+
- Bounded computation with oracle simulation
|
| 74 |
+
- Heuristic approaches to uncomputable problems
|
| 75 |
+
|
| 76 |
+
## Implementation Strategies
|
| 77 |
+
|
| 78 |
+
### 1. Oracle Simulation
|
| 79 |
+
- Use lookup tables for known cases
|
| 80 |
+
- Apply heuristics for unknown cases
|
| 81 |
+
- Incorporate randomness with fixed seeds for determinism
|
| 82 |
+
|
| 83 |
+
### 2. Bounded Approximation
|
| 84 |
+
- Limit computation depth to maintain practical execution
|
| 85 |
+
- Use asymptotic behaviors for large inputs
|
| 86 |
+
- Approximate infinite processes with finite resources
|
| 87 |
+
|
| 88 |
+
### 3. Theoretical Consistency
|
| 89 |
+
- Maintain mathematical rigor in approximations
|
| 90 |
+
- Document assumptions and limitations
|
| 91 |
+
- Preserve algebraic properties where possible
|
| 92 |
+
|
| 93 |
+
## Applications and Use Cases
|
| 94 |
+
|
| 95 |
+
### 1. Complexity Analysis
|
| 96 |
+
- Estimating computational complexity of algorithms
|
| 97 |
+
- Pattern recognition in program behavior
|
| 98 |
+
- Automated theorem proving assistance
|
| 99 |
+
|
| 100 |
+
### 2. Theoretical Computer Science Education
|
| 101 |
+
- Demonstrating computability concepts
|
| 102 |
+
- Exploring limits of computation
|
| 103 |
+
- Understanding oracle hierarchies
|
| 104 |
+
|
| 105 |
+
### 3. Research in Hypercomputation
|
| 106 |
+
- Modeling hypothetical computational paradigms
|
| 107 |
+
- Investigating quantum computational advantages
|
| 108 |
+
- Exploring analog computation limits
|
| 109 |
+
|
| 110 |
+
## Limitations and Considerations
|
| 111 |
+
|
| 112 |
+
### 1. Practical Constraints
|
| 113 |
+
- True uncomputable functions cannot be implemented
|
| 114 |
+
- All implementations are approximations or simulations
|
| 115 |
+
- Finite resources limit theoretical completeness
|
| 116 |
+
|
| 117 |
+
### 2. Determinism vs Uncomputability
|
| 118 |
+
- Balance between theoretical concepts and practical determinism
|
| 119 |
+
- Fixed seed randomness for reproducible "non-algorithmic" behavior
|
| 120 |
+
- Clear documentation of approximation methods
|
| 121 |
+
|
| 122 |
+
### 3. Verification Challenges
|
| 123 |
+
- Difficult to verify correctness of uncomputable approximations
|
| 124 |
+
- Limited testing capabilities for infinite processes
|
| 125 |
+
- Reliance on theoretical foundations rather than empirical validation
|
| 126 |
+
|
| 127 |
+
## Relationship to Other Non-Trained Networks
|
| 128 |
+
|
| 129 |
+
Uncomputable neural networks extend the paradigm of non-trained networks by:
|
| 130 |
+
- Eliminating not just training but algorithmic computation itself
|
| 131 |
+
- Incorporating theoretical computer science concepts
|
| 132 |
+
- Exploring computational limits and capabilities
|
| 133 |
+
- Maintaining deterministic behavior through careful design
|
| 134 |
+
|
| 135 |
+
## References
|
| 136 |
+
|
| 137 |
+
1. Turing, A. M. (1936). "On Computable Numbers, with an Application to the Entscheidungsproblem"
|
| 138 |
+
2. Rogers, H. (1987). "Theory of Recursive Functions and Effective Computability"
|
| 139 |
+
3. Copeland, B. J. (2002). "Hypercomputation: philosophical issues"
|
| 140 |
+
4. Beggs, E., Costa, J. F., Tucker, J. V. (2012). "The impact of models of a physical oracle on computational power"
|
| 141 |
+
5. Aaronson, S. (2013). "Quantum Computing since Democritus"
|