feat: Add MLP surrogate with Turbo Mode for 100x faster optimization
Neural Acceleration (MLP Surrogate): - Add run_nn_optimization.py with hybrid FEA/NN workflow - MLP architecture: 4-layer (64->128->128->64) with BatchNorm/Dropout - Three workflow modes: - --all: Sequential export->train->optimize->validate - --hybrid-loop: Iterative Train->NN->Validate->Retrain cycle - --turbo: Aggressive single-best validation (RECOMMENDED) - Turbo mode: 5000 NN trials + 50 FEA validations in ~12 minutes - Separate nn_study.db to avoid overloading dashboard Performance Results (bracket_pareto_3obj study): - NN prediction errors: mass 1-5%, stress 1-4%, stiffness 5-15% - Found minimum mass designs at boundary (angle~30deg, thick~30mm) - 100x speedup vs pure FEA exploration Protocol Operating System: - Add .claude/skills/ with Bootstrap, Cheatsheet, Context Loader - Add docs/protocols/ with operations (OP_01-06) and system (SYS_10-14) - Update SYS_14_NEURAL_ACCELERATION.md with MLP Turbo Mode docs NX Automation: - Add optimization_engine/hooks/ for NX CAD/CAE automation - Add study_wizard.py for guided study creation - Fix FEM mesh update: load idealized part before UpdateFemodel() New Study: - bracket_pareto_3obj: 3-objective Pareto (mass, stress, stiffness) - 167 FEA trials + 5000 NN trials completed - Demonstrates full hybrid workflow 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
341
docs/protocols/system/SYS_10_IMSO.md
Normal file
341
docs/protocols/system/SYS_10_IMSO.md
Normal file
@@ -0,0 +1,341 @@
|
||||
# SYS_10: Intelligent Multi-Strategy Optimization (IMSO)
|
||||
|
||||
<!--
|
||||
PROTOCOL: Intelligent Multi-Strategy Optimization
|
||||
LAYER: System
|
||||
VERSION: 2.1
|
||||
STATUS: Active
|
||||
LAST_UPDATED: 2025-12-05
|
||||
PRIVILEGE: user
|
||||
LOAD_WITH: []
|
||||
-->
|
||||
|
||||
## Overview
|
||||
|
||||
Protocol 10 implements adaptive optimization that automatically characterizes the problem landscape and selects the best optimization algorithm. This two-phase approach combines automated landscape analysis with algorithm-specific optimization.
|
||||
|
||||
**Key Innovation**: Adaptive characterization phase that intelligently determines when enough exploration has been done, then transitions to the optimal algorithm.
|
||||
|
||||
---
|
||||
|
||||
## When to Use
|
||||
|
||||
| Trigger | Action |
|
||||
|---------|--------|
|
||||
| Single-objective optimization | Use this protocol |
|
||||
| "adaptive", "intelligent", "IMSO" mentioned | Load this protocol |
|
||||
| User unsure which algorithm to use | Recommend this protocol |
|
||||
| Complex landscape suspected | Use this protocol |
|
||||
|
||||
**Do NOT use when**: Multi-objective optimization needed (use SYS_11 instead)
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| Parameter | Default | Range | Description |
|
||||
|-----------|---------|-------|-------------|
|
||||
| `min_trials` | 10 | 5-50 | Minimum characterization trials |
|
||||
| `max_trials` | 30 | 10-100 | Maximum characterization trials |
|
||||
| `confidence_threshold` | 0.85 | 0.0-1.0 | Stopping confidence level |
|
||||
| `check_interval` | 5 | 1-10 | Trials between checks |
|
||||
|
||||
**Landscape → Algorithm Mapping**:
|
||||
|
||||
| Landscape Type | Primary Strategy | Fallback |
|
||||
|----------------|------------------|----------|
|
||||
| smooth_unimodal | GP-BO | CMA-ES |
|
||||
| smooth_multimodal | GP-BO | TPE |
|
||||
| rugged_unimodal | TPE | CMA-ES |
|
||||
| rugged_multimodal | TPE | - |
|
||||
| noisy | TPE | - |
|
||||
|
||||
---
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ PHASE 1: ADAPTIVE CHARACTERIZATION STUDY │
|
||||
│ ───────────────────────────────────────────────────────── │
|
||||
│ Sampler: Random/Sobol (unbiased exploration) │
|
||||
│ Trials: 10-30 (adapts to problem complexity) │
|
||||
│ │
|
||||
│ Every 5 trials: │
|
||||
│ → Analyze landscape metrics │
|
||||
│ → Check metric convergence │
|
||||
│ → Calculate characterization confidence │
|
||||
│ → Decide if ready to stop │
|
||||
│ │
|
||||
│ Stop when: │
|
||||
│ ✓ Confidence ≥ 85% │
|
||||
│ ✓ OR max trials reached (30) │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ TRANSITION: LANDSCAPE ANALYSIS & STRATEGY SELECTION │
|
||||
│ ───────────────────────────────────────────────────────── │
|
||||
│ Analyze: │
|
||||
│ - Smoothness (0-1) │
|
||||
│ - Multimodality (number of modes) │
|
||||
│ - Parameter correlation │
|
||||
│ - Noise level │
|
||||
│ │
|
||||
│ Classify & Recommend: │
|
||||
│ smooth_unimodal → GP-BO (best) or CMA-ES │
|
||||
│ smooth_multimodal → GP-BO │
|
||||
│ rugged_multimodal → TPE │
|
||||
│ rugged_unimodal → TPE or CMA-ES │
|
||||
│ noisy → TPE (most robust) │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ PHASE 2: OPTIMIZATION STUDY │
|
||||
│ ───────────────────────────────────────────────────────── │
|
||||
│ Sampler: Recommended from Phase 1 │
|
||||
│ Warm Start: Initialize from best characterization point │
|
||||
│ Trials: User-specified (default 50) │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Core Components
|
||||
|
||||
### 1. Adaptive Characterization (`adaptive_characterization.py`)
|
||||
|
||||
**Confidence Calculation**:
|
||||
```python
|
||||
confidence = (
|
||||
0.40 * metric_stability_score + # Are metrics converging?
|
||||
0.30 * parameter_coverage_score + # Explored enough space?
|
||||
0.20 * sample_adequacy_score + # Enough samples for complexity?
|
||||
0.10 * landscape_clarity_score # Clear classification?
|
||||
)
|
||||
```
|
||||
|
||||
**Stopping Criteria**:
|
||||
- **Minimum trials**: 10 (baseline data requirement)
|
||||
- **Maximum trials**: 30 (prevent over-characterization)
|
||||
- **Confidence threshold**: 85% (high confidence required)
|
||||
- **Check interval**: Every 5 trials
|
||||
|
||||
**Adaptive Behavior**:
|
||||
```python
|
||||
# Simple problem (smooth, unimodal, low noise):
|
||||
if smoothness > 0.6 and unimodal and noise < 0.3:
|
||||
required_samples = 10 + dimensionality
|
||||
# Stops at ~10-15 trials
|
||||
|
||||
# Complex problem (multimodal with N modes):
|
||||
if multimodal and n_modes > 2:
|
||||
required_samples = 10 + 5 * n_modes + 2 * dimensionality
|
||||
# Continues to ~20-30 trials
|
||||
```
|
||||
|
||||
### 2. Landscape Analyzer (`landscape_analyzer.py`)
|
||||
|
||||
**Metrics Computed**:
|
||||
|
||||
| Metric | Method | Interpretation |
|
||||
|--------|--------|----------------|
|
||||
| Smoothness (0-1) | Spearman correlation | >0.6: Good for CMA-ES, GP-BO |
|
||||
| Multimodality | DBSCAN clustering | Detects distinct good regions |
|
||||
| Correlation | Parameter-objective correlation | Identifies influential params |
|
||||
| Noise (0-1) | Local consistency check | True simulation instability |
|
||||
|
||||
**Landscape Classifications**:
|
||||
- `smooth_unimodal`: Single smooth bowl
|
||||
- `smooth_multimodal`: Multiple smooth regions
|
||||
- `rugged_unimodal`: Single rugged region
|
||||
- `rugged_multimodal`: Multiple rugged regions
|
||||
- `noisy`: High noise level
|
||||
|
||||
### 3. Strategy Selector (`strategy_selector.py`)
|
||||
|
||||
**Algorithm Characteristics**:
|
||||
|
||||
**GP-BO (Gaussian Process Bayesian Optimization)**:
|
||||
- Best for: Smooth, expensive functions (like FEA)
|
||||
- Explicit surrogate model with uncertainty quantification
|
||||
- Acquisition function balances exploration/exploitation
|
||||
|
||||
**CMA-ES (Covariance Matrix Adaptation Evolution Strategy)**:
|
||||
- Best for: Smooth unimodal problems
|
||||
- Fast convergence to local optimum
|
||||
- Adapts search distribution to landscape
|
||||
|
||||
**TPE (Tree-structured Parzen Estimator)**:
|
||||
- Best for: Multimodal, rugged, or noisy problems
|
||||
- Robust to noise and discontinuities
|
||||
- Good global exploration
|
||||
|
||||
### 4. Intelligent Optimizer (`intelligent_optimizer.py`)
|
||||
|
||||
**Workflow**:
|
||||
1. Create characterization study (Random/Sobol sampler)
|
||||
2. Run adaptive characterization with stopping criterion
|
||||
3. Analyze final landscape
|
||||
4. Select optimal strategy
|
||||
5. Create optimization study with recommended sampler
|
||||
6. Warm-start from best characterization point
|
||||
7. Run optimization
|
||||
8. Generate intelligence report
|
||||
|
||||
---
|
||||
|
||||
## Configuration
|
||||
|
||||
Add to `optimization_config.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"intelligent_optimization": {
|
||||
"enabled": true,
|
||||
"characterization": {
|
||||
"min_trials": 10,
|
||||
"max_trials": 30,
|
||||
"confidence_threshold": 0.85,
|
||||
"check_interval": 5
|
||||
},
|
||||
"landscape_analysis": {
|
||||
"min_trials_for_analysis": 10
|
||||
},
|
||||
"strategy_selection": {
|
||||
"allow_cmaes": true,
|
||||
"allow_gpbo": true,
|
||||
"allow_tpe": true
|
||||
}
|
||||
},
|
||||
"trials": {
|
||||
"n_trials": 50
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Usage Example
|
||||
|
||||
```python
|
||||
from pathlib import Path
|
||||
from optimization_engine.intelligent_optimizer import IntelligentOptimizer
|
||||
|
||||
# Create optimizer
|
||||
optimizer = IntelligentOptimizer(
|
||||
study_name="my_optimization",
|
||||
study_dir=Path("studies/my_study/2_results"),
|
||||
config=optimization_config,
|
||||
verbose=True
|
||||
)
|
||||
|
||||
# Define design variables
|
||||
design_vars = {
|
||||
'parameter1': (lower_bound, upper_bound),
|
||||
'parameter2': (lower_bound, upper_bound)
|
||||
}
|
||||
|
||||
# Run Protocol 10
|
||||
results = optimizer.optimize(
|
||||
objective_function=my_objective,
|
||||
design_variables=design_vars,
|
||||
n_trials=50,
|
||||
target_value=target,
|
||||
tolerance=0.1
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Performance Benefits
|
||||
|
||||
**Efficiency**:
|
||||
- **Simple problems**: Early stop at ~10-15 trials (33% reduction)
|
||||
- **Complex problems**: Extended characterization at ~20-30 trials
|
||||
- **Right algorithm**: Uses optimal strategy for landscape type
|
||||
|
||||
**Example Performance** (Circular Plate Frequency Tuning):
|
||||
- TPE alone: ~95 trials to target
|
||||
- Random search: ~150+ trials
|
||||
- **Protocol 10**: ~56 trials (**41% reduction**)
|
||||
|
||||
---
|
||||
|
||||
## Intelligence Reports
|
||||
|
||||
Protocol 10 generates three tracking files:
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `characterization_progress.json` | Metric evolution, confidence progression, stopping decision |
|
||||
| `intelligence_report.json` | Final landscape classification, parameter correlations, strategy recommendation |
|
||||
| `strategy_transitions.json` | Phase transitions, algorithm switches, performance metrics |
|
||||
|
||||
**Location**: `studies/{study_name}/2_results/intelligent_optimizer/`
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Symptom | Cause | Solution |
|
||||
|---------|-------|----------|
|
||||
| Characterization takes too long | Complex landscape | Increase `max_trials` or accept longer characterization |
|
||||
| Wrong algorithm selected | Insufficient exploration | Lower `confidence_threshold` or increase `min_trials` |
|
||||
| Poor convergence | Mismatch between landscape and algorithm | Review `intelligence_report.json`, consider manual override |
|
||||
| "No characterization data" | Study not using Protocol 10 | Enable `intelligent_optimization.enabled: true` |
|
||||
|
||||
---
|
||||
|
||||
## Cross-References
|
||||
|
||||
- **Depends On**: None
|
||||
- **Used By**: [OP_01_CREATE_STUDY](../operations/OP_01_CREATE_STUDY.md), [OP_02_RUN_OPTIMIZATION](../operations/OP_02_RUN_OPTIMIZATION.md)
|
||||
- **Integrates With**: [SYS_13_DASHBOARD_TRACKING](./SYS_13_DASHBOARD_TRACKING.md)
|
||||
- **See Also**: [SYS_11_MULTI_OBJECTIVE](./SYS_11_MULTI_OBJECTIVE.md) for multi-objective optimization
|
||||
|
||||
---
|
||||
|
||||
## Implementation Files
|
||||
|
||||
- `optimization_engine/intelligent_optimizer.py` - Main orchestrator
|
||||
- `optimization_engine/adaptive_characterization.py` - Stopping criterion
|
||||
- `optimization_engine/landscape_analyzer.py` - Landscape metrics
|
||||
- `optimization_engine/strategy_selector.py` - Algorithm recommendation
|
||||
|
||||
---
|
||||
|
||||
## Version History
|
||||
|
||||
| Version | Date | Changes |
|
||||
|---------|------|---------|
|
||||
| 2.1 | 2025-11-20 | Fixed strategy selector timing, multimodality detection, added simulation validation |
|
||||
| 2.0 | 2025-11-20 | Added adaptive characterization, two-study architecture |
|
||||
| 1.0 | 2025-11-19 | Initial implementation |
|
||||
|
||||
### Version 2.1 Bug Fixes Detail
|
||||
|
||||
**Fix #1: Strategy Selector - Use Characterization Trial Count**
|
||||
|
||||
*Problem*: Strategy selector used total trial count (including pruned) instead of characterization trial count, causing wrong algorithm selection after characterization.
|
||||
|
||||
*Solution* (`strategy_selector.py`): Use `char_trials = landscape.get('total_trials', trials_completed)` for decisions.
|
||||
|
||||
**Fix #2: Improved Multimodality Detection**
|
||||
|
||||
*Problem*: False multimodality detected on smooth continuous surfaces (2 modes detected when problem was unimodal).
|
||||
|
||||
*Solution* (`landscape_analyzer.py`): Added heuristic - if only 2 modes with smoothness > 0.6 and noise < 0.2, reclassify as unimodal (smooth continuous manifold).
|
||||
|
||||
**Fix #3: Simulation Validation**
|
||||
|
||||
*Problem*: 20% pruning rate due to extreme parameters causing mesh/solver failures.
|
||||
|
||||
*Solution*: Created `simulation_validator.py` with:
|
||||
- Hard limits (reject invalid parameters)
|
||||
- Soft limits (warn about risky parameters)
|
||||
- Aspect ratio checks
|
||||
- Model-specific validation rules
|
||||
|
||||
*Impact*: Reduced pruning rate from 20% to ~5%.
|
||||
338
docs/protocols/system/SYS_11_MULTI_OBJECTIVE.md
Normal file
338
docs/protocols/system/SYS_11_MULTI_OBJECTIVE.md
Normal file
@@ -0,0 +1,338 @@
|
||||
# SYS_11: Multi-Objective Support
|
||||
|
||||
<!--
|
||||
PROTOCOL: Multi-Objective Optimization Support
|
||||
LAYER: System
|
||||
VERSION: 1.0
|
||||
STATUS: Active (MANDATORY)
|
||||
LAST_UPDATED: 2025-12-05
|
||||
PRIVILEGE: user
|
||||
LOAD_WITH: []
|
||||
-->
|
||||
|
||||
## Overview
|
||||
|
||||
**ALL** optimization engines in Atomizer **MUST** support both single-objective and multi-objective optimization without requiring code changes. This protocol ensures system robustness and prevents runtime failures when handling Pareto optimization.
|
||||
|
||||
**Key Requirement**: Code must work with both `study.best_trial` (single) and `study.best_trials` (multi) APIs.
|
||||
|
||||
---
|
||||
|
||||
## When to Use
|
||||
|
||||
| Trigger | Action |
|
||||
|---------|--------|
|
||||
| 2+ objectives defined in config | Use NSGA-II sampler |
|
||||
| "pareto", "multi-objective" mentioned | Load this protocol |
|
||||
| "tradeoff", "competing goals" | Suggest multi-objective approach |
|
||||
| "minimize X AND maximize Y" | Configure as multi-objective |
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference
|
||||
|
||||
**Single vs. Multi-Objective API**:
|
||||
|
||||
| Operation | Single-Objective | Multi-Objective |
|
||||
|-----------|-----------------|-----------------|
|
||||
| Best trial | `study.best_trial` | `study.best_trials[0]` |
|
||||
| Best params | `study.best_params` | `trial.params` |
|
||||
| Best value | `study.best_value` | `trial.values` (tuple) |
|
||||
| Direction | `direction='minimize'` | `directions=['minimize', 'maximize']` |
|
||||
| Sampler | TPE, CMA-ES, GP | NSGA-II (mandatory) |
|
||||
|
||||
---
|
||||
|
||||
## The Problem This Solves
|
||||
|
||||
Previously, optimization components only supported single-objective. When used with multi-objective studies:
|
||||
|
||||
1. Trials run successfully
|
||||
2. Trials saved to database
|
||||
3. **CRASH** when compiling results
|
||||
- `study.best_trial` raises RuntimeError
|
||||
- No tracking files generated
|
||||
- Silent failures
|
||||
|
||||
**Root Cause**: Optuna has different APIs:
|
||||
|
||||
```python
|
||||
# Single-Objective (works)
|
||||
study.best_trial # Returns Trial object
|
||||
study.best_params # Returns dict
|
||||
study.best_value # Returns float
|
||||
|
||||
# Multi-Objective (RAISES RuntimeError)
|
||||
study.best_trial # ❌ RuntimeError
|
||||
study.best_params # ❌ RuntimeError
|
||||
study.best_value # ❌ RuntimeError
|
||||
study.best_trials # ✓ Returns LIST of Pareto-optimal trials
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Solution Pattern
|
||||
|
||||
### 1. Always Check Study Type
|
||||
|
||||
```python
|
||||
is_multi_objective = len(study.directions) > 1
|
||||
```
|
||||
|
||||
### 2. Use Conditional Access
|
||||
|
||||
```python
|
||||
if is_multi_objective:
|
||||
best_trials = study.best_trials
|
||||
if best_trials:
|
||||
# Select representative trial (e.g., first Pareto solution)
|
||||
representative_trial = best_trials[0]
|
||||
best_params = representative_trial.params
|
||||
best_value = representative_trial.values # Tuple
|
||||
best_trial_num = representative_trial.number
|
||||
else:
|
||||
best_params = {}
|
||||
best_value = None
|
||||
best_trial_num = None
|
||||
else:
|
||||
# Single-objective: safe to use standard API
|
||||
best_params = study.best_params
|
||||
best_value = study.best_value
|
||||
best_trial_num = study.best_trial.number
|
||||
```
|
||||
|
||||
### 3. Return Rich Metadata
|
||||
|
||||
Always include in results:
|
||||
|
||||
```python
|
||||
{
|
||||
'best_params': best_params,
|
||||
'best_value': best_value, # float or tuple
|
||||
'best_trial': best_trial_num,
|
||||
'is_multi_objective': is_multi_objective,
|
||||
'pareto_front_size': len(study.best_trials) if is_multi_objective else 1,
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Implementation Checklist
|
||||
|
||||
When creating or modifying any optimization component:
|
||||
|
||||
- [ ] **Study Creation**: Support `directions` parameter
|
||||
```python
|
||||
if len(objectives) > 1:
|
||||
directions = [obj['type'] for obj in objectives] # ['minimize', 'maximize']
|
||||
study = optuna.create_study(directions=directions, ...)
|
||||
else:
|
||||
study = optuna.create_study(direction='minimize', ...)
|
||||
```
|
||||
|
||||
- [ ] **Result Compilation**: Check `len(study.directions) > 1`
|
||||
- [ ] **Best Trial Access**: Use conditional logic
|
||||
- [ ] **Logging**: Print Pareto front size for multi-objective
|
||||
- [ ] **Reports**: Handle tuple objectives in visualization
|
||||
- [ ] **Testing**: Test with BOTH single and multi-objective cases
|
||||
|
||||
---
|
||||
|
||||
## Configuration
|
||||
|
||||
**Multi-Objective Config Example**:
|
||||
|
||||
```json
|
||||
{
|
||||
"objectives": [
|
||||
{
|
||||
"name": "stiffness",
|
||||
"type": "maximize",
|
||||
"description": "Structural stiffness (N/mm)",
|
||||
"unit": "N/mm"
|
||||
},
|
||||
{
|
||||
"name": "mass",
|
||||
"type": "minimize",
|
||||
"description": "Total mass (kg)",
|
||||
"unit": "kg"
|
||||
}
|
||||
],
|
||||
"optimization_settings": {
|
||||
"sampler": "NSGAIISampler",
|
||||
"n_trials": 50
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Objective Function Return Format**:
|
||||
|
||||
```python
|
||||
# Single-objective: return float
|
||||
def objective_single(trial):
|
||||
# ... compute ...
|
||||
return objective_value # float
|
||||
|
||||
# Multi-objective: return tuple
|
||||
def objective_multi(trial):
|
||||
# ... compute ...
|
||||
return (stiffness, mass) # tuple of floats
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Semantic Directions
|
||||
|
||||
Use semantic direction values - no negative tricks:
|
||||
|
||||
```python
|
||||
# ✅ CORRECT: Semantic directions
|
||||
objectives = [
|
||||
{"name": "stiffness", "type": "maximize"},
|
||||
{"name": "mass", "type": "minimize"}
|
||||
]
|
||||
# Return: (stiffness, mass) - both positive values
|
||||
|
||||
# ❌ WRONG: Negative trick
|
||||
def objective(trial):
|
||||
return (-stiffness, mass) # Don't negate to fake maximize
|
||||
```
|
||||
|
||||
Optuna handles directions correctly when you specify `directions=['maximize', 'minimize']`.
|
||||
|
||||
---
|
||||
|
||||
## Testing Protocol
|
||||
|
||||
Before marking any optimization component complete:
|
||||
|
||||
### Test 1: Single-Objective
|
||||
```python
|
||||
# Config with 1 objective
|
||||
directions = None # or ['minimize']
|
||||
# Run optimization
|
||||
# Verify: completes without errors
|
||||
```
|
||||
|
||||
### Test 2: Multi-Objective
|
||||
```python
|
||||
# Config with 2+ objectives
|
||||
directions = ['minimize', 'minimize']
|
||||
# Run optimization
|
||||
# Verify: completes without errors
|
||||
# Verify: ALL tracking files generated
|
||||
```
|
||||
|
||||
### Test 3: Verify Outputs
|
||||
- `2_results/study.db` exists
|
||||
- `2_results/intelligent_optimizer/` has tracking files
|
||||
- `2_results/optimization_summary.json` exists
|
||||
- No RuntimeError in logs
|
||||
|
||||
---
|
||||
|
||||
## NSGA-II Configuration
|
||||
|
||||
For multi-objective optimization, use NSGA-II:
|
||||
|
||||
```python
|
||||
import optuna
|
||||
from optuna.samplers import NSGAIISampler
|
||||
|
||||
sampler = NSGAIISampler(
|
||||
population_size=50, # Pareto front population
|
||||
mutation_prob=None, # Auto-computed
|
||||
crossover_prob=0.9, # Recombination rate
|
||||
swapping_prob=0.5, # Gene swapping probability
|
||||
seed=42 # Reproducibility
|
||||
)
|
||||
|
||||
study = optuna.create_study(
|
||||
directions=['maximize', 'minimize'],
|
||||
sampler=sampler,
|
||||
study_name="multi_objective_study",
|
||||
storage="sqlite:///study.db"
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Pareto Front Handling
|
||||
|
||||
### Accessing Pareto Solutions
|
||||
|
||||
```python
|
||||
if is_multi_objective:
|
||||
pareto_trials = study.best_trials
|
||||
print(f"Found {len(pareto_trials)} Pareto-optimal solutions")
|
||||
|
||||
for trial in pareto_trials:
|
||||
print(f"Trial {trial.number}: {trial.values}")
|
||||
print(f" Params: {trial.params}")
|
||||
```
|
||||
|
||||
### Selecting Representative Solution
|
||||
|
||||
```python
|
||||
# Option 1: First Pareto solution
|
||||
representative = study.best_trials[0]
|
||||
|
||||
# Option 2: Weighted selection
|
||||
def weighted_selection(trials, weights):
|
||||
best_score = float('inf')
|
||||
best_trial = None
|
||||
for trial in trials:
|
||||
score = sum(w * v for w, v in zip(weights, trial.values))
|
||||
if score < best_score:
|
||||
best_score = score
|
||||
best_trial = trial
|
||||
return best_trial
|
||||
|
||||
# Option 3: Knee point (maximum distance from ideal line)
|
||||
# Requires more complex computation
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Symptom | Cause | Solution |
|
||||
|---------|-------|----------|
|
||||
| RuntimeError on `best_trial` | Multi-objective study using single API | Use conditional check pattern |
|
||||
| Empty Pareto front | No feasible solutions | Check constraints, relax if needed |
|
||||
| Only 1 Pareto solution | Objectives not conflicting | Verify objectives are truly competing |
|
||||
| NSGA-II with single objective | Wrong config | Use TPE/CMA-ES for single-objective |
|
||||
|
||||
---
|
||||
|
||||
## Cross-References
|
||||
|
||||
- **Depends On**: None (mandatory for all)
|
||||
- **Used By**: All optimization components
|
||||
- **Integrates With**:
|
||||
- [SYS_10_IMSO](./SYS_10_IMSO.md) (selects NSGA-II for multi-objective)
|
||||
- [SYS_13_DASHBOARD_TRACKING](./SYS_13_DASHBOARD_TRACKING.md) (Pareto visualization)
|
||||
- **See Also**: [OP_04_ANALYZE_RESULTS](../operations/OP_04_ANALYZE_RESULTS.md) for Pareto analysis
|
||||
|
||||
---
|
||||
|
||||
## Implementation Files
|
||||
|
||||
Files that implement this protocol:
|
||||
- `optimization_engine/intelligent_optimizer.py` - `_compile_results()` method
|
||||
- `optimization_engine/study_continuation.py` - Result handling
|
||||
- `optimization_engine/hybrid_study_creator.py` - Study creation
|
||||
|
||||
Files requiring this protocol:
|
||||
- [ ] `optimization_engine/study_continuation.py`
|
||||
- [ ] `optimization_engine/hybrid_study_creator.py`
|
||||
- [ ] `optimization_engine/intelligent_setup.py`
|
||||
- [ ] `optimization_engine/llm_optimization_runner.py`
|
||||
|
||||
---
|
||||
|
||||
## Version History
|
||||
|
||||
| Version | Date | Changes |
|
||||
|---------|------|---------|
|
||||
| 1.0 | 2025-11-20 | Initial release, mandatory for all engines |
|
||||
435
docs/protocols/system/SYS_13_DASHBOARD_TRACKING.md
Normal file
435
docs/protocols/system/SYS_13_DASHBOARD_TRACKING.md
Normal file
@@ -0,0 +1,435 @@
|
||||
# SYS_13: Real-Time Dashboard Tracking
|
||||
|
||||
<!--
|
||||
PROTOCOL: Real-Time Dashboard Tracking
|
||||
LAYER: System
|
||||
VERSION: 1.0
|
||||
STATUS: Active
|
||||
LAST_UPDATED: 2025-12-05
|
||||
PRIVILEGE: user
|
||||
LOAD_WITH: [SYS_10_IMSO, SYS_11_MULTI_OBJECTIVE]
|
||||
-->
|
||||
|
||||
## Overview
|
||||
|
||||
Protocol 13 implements a comprehensive real-time web dashboard for monitoring optimization studies. It provides live visualization of optimizer state, Pareto fronts, parallel coordinates, and trial history with automatic updates every trial.
|
||||
|
||||
**Key Feature**: Every trial completion writes state to JSON, enabling live browser updates.
|
||||
|
||||
---
|
||||
|
||||
## When to Use
|
||||
|
||||
| Trigger | Action |
|
||||
|---------|--------|
|
||||
| "dashboard", "visualization" mentioned | Load this protocol |
|
||||
| "real-time", "monitoring" requested | Enable dashboard tracking |
|
||||
| Multi-objective study | Dashboard shows Pareto front |
|
||||
| Want to see progress visually | Point to `localhost:3000` |
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference
|
||||
|
||||
**Dashboard URLs**:
|
||||
| Service | URL | Purpose |
|
||||
|---------|-----|---------|
|
||||
| Frontend | `http://localhost:3000` | Main dashboard |
|
||||
| Backend API | `http://localhost:8000` | REST API |
|
||||
| Optuna Dashboard | `http://localhost:8080` | Alternative viewer |
|
||||
|
||||
**Start Commands**:
|
||||
```bash
|
||||
# Backend
|
||||
cd atomizer-dashboard/backend
|
||||
python -m uvicorn api.main:app --reload --port 8000
|
||||
|
||||
# Frontend
|
||||
cd atomizer-dashboard/frontend
|
||||
npm run dev
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
Trial Completion (Optuna)
|
||||
│
|
||||
▼
|
||||
Realtime Callback (optimization_engine/realtime_tracking.py)
|
||||
│
|
||||
▼
|
||||
Write optimizer_state.json
|
||||
│
|
||||
▼
|
||||
Backend API /optimizer-state endpoint
|
||||
│
|
||||
▼
|
||||
Frontend Components (2s polling)
|
||||
│
|
||||
▼
|
||||
User sees live updates in browser
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Backend Components
|
||||
|
||||
### 1. Real-Time Tracking System (`realtime_tracking.py`)
|
||||
|
||||
**Purpose**: Write JSON state files after every trial completion.
|
||||
|
||||
**Integration** (in `intelligent_optimizer.py`):
|
||||
```python
|
||||
from optimization_engine.realtime_tracking import create_realtime_callback
|
||||
|
||||
# Create callback
|
||||
callback = create_realtime_callback(
|
||||
tracking_dir=results_dir / "intelligent_optimizer",
|
||||
optimizer_ref=self,
|
||||
verbose=True
|
||||
)
|
||||
|
||||
# Register with Optuna
|
||||
study.optimize(objective, n_trials=n_trials, callbacks=[callback])
|
||||
```
|
||||
|
||||
**Data Structure** (`optimizer_state.json`):
|
||||
```json
|
||||
{
|
||||
"timestamp": "2025-11-21T15:27:28.828930",
|
||||
"trial_number": 29,
|
||||
"total_trials": 50,
|
||||
"current_phase": "adaptive_optimization",
|
||||
"current_strategy": "GP_UCB",
|
||||
"is_multi_objective": true,
|
||||
"study_directions": ["maximize", "minimize"]
|
||||
}
|
||||
```
|
||||
|
||||
### 2. REST API Endpoints
|
||||
|
||||
**Base**: `/api/optimization/studies/{study_id}/`
|
||||
|
||||
| Endpoint | Method | Returns |
|
||||
|----------|--------|---------|
|
||||
| `/metadata` | GET | Objectives, design vars, constraints with units |
|
||||
| `/optimizer-state` | GET | Current phase, strategy, progress |
|
||||
| `/pareto-front` | GET | Pareto-optimal solutions (multi-objective) |
|
||||
| `/history` | GET | All trial history |
|
||||
| `/` | GET | List all studies |
|
||||
|
||||
**Unit Inference**:
|
||||
```python
|
||||
def _infer_objective_unit(objective: Dict) -> str:
|
||||
name = objective.get("name", "").lower()
|
||||
desc = objective.get("description", "").lower()
|
||||
|
||||
if "frequency" in name or "hz" in desc:
|
||||
return "Hz"
|
||||
elif "stiffness" in name or "n/mm" in desc:
|
||||
return "N/mm"
|
||||
elif "mass" in name or "kg" in desc:
|
||||
return "kg"
|
||||
# ... more patterns
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Frontend Components
|
||||
|
||||
### 1. OptimizerPanel (`components/OptimizerPanel.tsx`)
|
||||
|
||||
**Displays**:
|
||||
- Current phase (Characterization, Exploration, Exploitation, Adaptive)
|
||||
- Current strategy (TPE, GP, NSGA-II, etc.)
|
||||
- Progress bar with trial count
|
||||
- Multi-objective indicator
|
||||
|
||||
```
|
||||
┌─────────────────────────────────┐
|
||||
│ Intelligent Optimizer Status │
|
||||
├─────────────────────────────────┤
|
||||
│ Phase: [Adaptive Optimization] │
|
||||
│ Strategy: [GP_UCB] │
|
||||
│ Progress: [████████░░] 29/50 │
|
||||
│ Multi-Objective: ✓ │
|
||||
└─────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 2. ParetoPlot (`components/ParetoPlot.tsx`)
|
||||
|
||||
**Features**:
|
||||
- Scatter plot of Pareto-optimal solutions
|
||||
- Pareto front line connecting optimal points
|
||||
- **3 Normalization Modes**:
|
||||
- **Raw**: Original engineering values
|
||||
- **Min-Max**: Scales to [0, 1]
|
||||
- **Z-Score**: Standardizes to mean=0, std=1
|
||||
- Tooltip shows raw values regardless of normalization
|
||||
- Color-coded: green=feasible, red=infeasible
|
||||
|
||||
### 3. ParallelCoordinatesPlot (`components/ParallelCoordinatesPlot.tsx`)
|
||||
|
||||
**Features**:
|
||||
- High-dimensional visualization (objectives + design variables)
|
||||
- Interactive trial selection
|
||||
- Normalized [0, 1] axes
|
||||
- Color coding: green (feasible), red (infeasible), yellow (selected)
|
||||
|
||||
```
|
||||
Stiffness Mass support_angle tip_thickness
|
||||
│ │ │ │
|
||||
│ ╱─────╲ ╱ │
|
||||
│ ╱ ╲─────────╱ │
|
||||
│ ╱ ╲ │
|
||||
```
|
||||
|
||||
### 4. Dashboard Layout
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────┐
|
||||
│ Study Selection │
|
||||
├──────────────────────────────────────────────────┤
|
||||
│ Metrics Grid (Best, Avg, Trials, Pruned) │
|
||||
├──────────────────────────────────────────────────┤
|
||||
│ [OptimizerPanel] [ParetoPlot] │
|
||||
├──────────────────────────────────────────────────┤
|
||||
│ [ParallelCoordinatesPlot - Full Width] │
|
||||
├──────────────────────────────────────────────────┤
|
||||
│ [Convergence] [Parameter Space] │
|
||||
├──────────────────────────────────────────────────┤
|
||||
│ [Recent Trials Table] │
|
||||
└──────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Configuration
|
||||
|
||||
**In `optimization_config.json`**:
|
||||
```json
|
||||
{
|
||||
"dashboard_settings": {
|
||||
"enabled": true,
|
||||
"port": 8000,
|
||||
"realtime_updates": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Study Requirements**:
|
||||
- Must use Protocol 10 (IntelligentOptimizer) for optimizer state
|
||||
- Must have `optimization_config.json` with objectives and design_variables
|
||||
- Real-time tracking enabled automatically with Protocol 10
|
||||
|
||||
---
|
||||
|
||||
## Usage Workflow
|
||||
|
||||
### 1. Start Dashboard
|
||||
|
||||
```bash
|
||||
# Terminal 1: Backend
|
||||
cd atomizer-dashboard/backend
|
||||
python -m uvicorn api.main:app --reload --port 8000
|
||||
|
||||
# Terminal 2: Frontend
|
||||
cd atomizer-dashboard/frontend
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### 2. Start Optimization
|
||||
|
||||
```bash
|
||||
cd studies/my_study
|
||||
conda activate atomizer
|
||||
python run_optimization.py --n-trials 50
|
||||
```
|
||||
|
||||
### 3. View Dashboard
|
||||
|
||||
- Open browser to `http://localhost:3000`
|
||||
- Select study from dropdown
|
||||
- Watch real-time updates every trial
|
||||
|
||||
### 4. Interact with Plots
|
||||
|
||||
- Toggle normalization on Pareto plot
|
||||
- Click lines in parallel coordinates to select trials
|
||||
- Hover for detailed trial information
|
||||
|
||||
---
|
||||
|
||||
## Performance
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Backend endpoint latency | ~10ms |
|
||||
| Frontend polling interval | 2 seconds |
|
||||
| Real-time write overhead | <5ms per trial |
|
||||
| Dashboard initial load | <500ms |
|
||||
|
||||
---
|
||||
|
||||
## Integration with Other Protocols
|
||||
|
||||
### Protocol 10 Integration
|
||||
- Real-time callback integrated into `IntelligentOptimizer.optimize()`
|
||||
- Tracks phase transitions (characterization → adaptive optimization)
|
||||
- Reports strategy changes
|
||||
|
||||
### Protocol 11 Integration
|
||||
- Pareto front endpoint checks `len(study.directions) > 1`
|
||||
- Dashboard conditionally renders Pareto plots
|
||||
- Uses Optuna's `study.best_trials` for Pareto front
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Symptom | Cause | Solution |
|
||||
|---------|-------|----------|
|
||||
| "No Pareto front data yet" | Single-objective or no trials | Wait for trials, check objectives |
|
||||
| OptimizerPanel shows "Not available" | Not using Protocol 10 | Enable IntelligentOptimizer |
|
||||
| Units not showing | Missing unit in config | Add `unit` field or use pattern in description |
|
||||
| Dashboard not updating | Backend not running | Start backend with uvicorn |
|
||||
| CORS errors | Backend/frontend mismatch | Check ports, restart both |
|
||||
|
||||
---
|
||||
|
||||
## Cross-References
|
||||
|
||||
- **Depends On**: [SYS_10_IMSO](./SYS_10_IMSO.md), [SYS_11_MULTI_OBJECTIVE](./SYS_11_MULTI_OBJECTIVE.md)
|
||||
- **Used By**: [OP_03_MONITOR_PROGRESS](../operations/OP_03_MONITOR_PROGRESS.md)
|
||||
- **See Also**: Optuna Dashboard for alternative visualization
|
||||
|
||||
---
|
||||
|
||||
## Implementation Files
|
||||
|
||||
**Backend**:
|
||||
- `atomizer-dashboard/backend/api/main.py` - FastAPI app
|
||||
- `atomizer-dashboard/backend/api/routes/optimization.py` - Endpoints
|
||||
- `optimization_engine/realtime_tracking.py` - Callback system
|
||||
|
||||
**Frontend**:
|
||||
- `atomizer-dashboard/frontend/src/pages/Dashboard.tsx` - Main page
|
||||
- `atomizer-dashboard/frontend/src/components/OptimizerPanel.tsx`
|
||||
- `atomizer-dashboard/frontend/src/components/ParetoPlot.tsx`
|
||||
- `atomizer-dashboard/frontend/src/components/ParallelCoordinatesPlot.tsx`
|
||||
|
||||
---
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### Backend API Example (FastAPI)
|
||||
|
||||
```python
|
||||
@router.get("/studies/{study_id}/pareto-front")
|
||||
async def get_pareto_front(study_id: str):
|
||||
"""Get Pareto-optimal solutions for multi-objective studies."""
|
||||
study = optuna.load_study(study_name=study_id, storage=storage)
|
||||
|
||||
if len(study.directions) == 1:
|
||||
return {"is_multi_objective": False}
|
||||
|
||||
return {
|
||||
"is_multi_objective": True,
|
||||
"pareto_front": [
|
||||
{
|
||||
"trial_number": t.number,
|
||||
"values": t.values,
|
||||
"params": t.params,
|
||||
"user_attrs": dict(t.user_attrs)
|
||||
}
|
||||
for t in study.best_trials
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Frontend OptimizerPanel (React/TypeScript)
|
||||
|
||||
```typescript
|
||||
export function OptimizerPanel({ studyId }: { studyId: string }) {
|
||||
const [state, setState] = useState<OptimizerState | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchState = async () => {
|
||||
const res = await fetch(`/api/optimization/studies/${studyId}/optimizer-state`);
|
||||
setState(await res.json());
|
||||
};
|
||||
fetchState();
|
||||
const interval = setInterval(fetchState, 1000);
|
||||
return () => clearInterval(interval);
|
||||
}, [studyId]);
|
||||
|
||||
return (
|
||||
<Card title="Optimizer Status">
|
||||
<div>Phase: {state?.current_phase}</div>
|
||||
<div>Strategy: {state?.current_strategy}</div>
|
||||
<ProgressBar value={state?.trial_number} max={state?.total_trials} />
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Callback Integration
|
||||
|
||||
**CRITICAL**: Every `study.optimize()` call must include the realtime callback:
|
||||
|
||||
```python
|
||||
# In IntelligentOptimizer
|
||||
self.realtime_callback = create_realtime_callback(
|
||||
tracking_dir=self.tracking_dir,
|
||||
optimizer_ref=self,
|
||||
verbose=self.verbose
|
||||
)
|
||||
|
||||
# Register with ALL optimize calls
|
||||
self.study.optimize(
|
||||
objective_function,
|
||||
n_trials=check_interval,
|
||||
callbacks=[self.realtime_callback] # Required for real-time updates
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Chart Library Options
|
||||
|
||||
The dashboard supports two chart libraries:
|
||||
|
||||
| Feature | Recharts | Plotly |
|
||||
|---------|----------|--------|
|
||||
| Load Speed | Fast | Slower (lazy loaded) |
|
||||
| Interactivity | Basic | Advanced |
|
||||
| Export | Screenshot | PNG/SVG native |
|
||||
| 3D Support | No | Yes |
|
||||
| Real-time Updates | Better | Good |
|
||||
|
||||
**Recommendation**: Use Recharts during active optimization, Plotly for post-analysis.
|
||||
|
||||
### Quick Start
|
||||
|
||||
```bash
|
||||
# Both backend and frontend
|
||||
python start_dashboard.py
|
||||
|
||||
# Or manually:
|
||||
cd atomizer-dashboard/backend && python -m uvicorn main:app --port 8000
|
||||
cd atomizer-dashboard/frontend && npm run dev
|
||||
```
|
||||
|
||||
Access at: `http://localhost:3003`
|
||||
|
||||
---
|
||||
|
||||
## Version History
|
||||
|
||||
| Version | Date | Changes |
|
||||
|---------|------|---------|
|
||||
| 1.2 | 2025-12-05 | Added chart library options |
|
||||
| 1.1 | 2025-12-05 | Added implementation code snippets |
|
||||
| 1.0 | 2025-11-21 | Initial release with real-time tracking |
|
||||
564
docs/protocols/system/SYS_14_NEURAL_ACCELERATION.md
Normal file
564
docs/protocols/system/SYS_14_NEURAL_ACCELERATION.md
Normal file
@@ -0,0 +1,564 @@
|
||||
# SYS_14: Neural Network Acceleration
|
||||
|
||||
<!--
|
||||
PROTOCOL: Neural Network Surrogate Acceleration
|
||||
LAYER: System
|
||||
VERSION: 2.0
|
||||
STATUS: Active
|
||||
LAST_UPDATED: 2025-12-06
|
||||
PRIVILEGE: user
|
||||
LOAD_WITH: [SYS_10_IMSO, SYS_11_MULTI_OBJECTIVE]
|
||||
-->
|
||||
|
||||
## Overview
|
||||
|
||||
Atomizer provides **neural network surrogate acceleration** enabling 100-1000x faster optimization by replacing expensive FEA evaluations with instant neural predictions.
|
||||
|
||||
**Two approaches available**:
|
||||
1. **MLP Surrogate** (Simple, integrated) - 4-layer MLP trained on FEA data, runs within study
|
||||
2. **GNN Field Predictor** (Advanced) - Graph neural network for full field predictions
|
||||
|
||||
**Key Innovation**: Train once on FEA data, then explore 5,000-50,000+ designs in the time it takes to run 50 FEA trials.
|
||||
|
||||
---
|
||||
|
||||
## When to Use
|
||||
|
||||
| Trigger | Action |
|
||||
|---------|--------|
|
||||
| >50 trials needed | Consider neural acceleration |
|
||||
| "neural", "surrogate", "NN" mentioned | Load this protocol |
|
||||
| "fast", "acceleration", "speed" needed | Suggest neural acceleration |
|
||||
| Training data available | Enable surrogate |
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference
|
||||
|
||||
**Performance Comparison**:
|
||||
|
||||
| Metric | Traditional FEA | Neural Network | Improvement |
|
||||
|--------|-----------------|----------------|-------------|
|
||||
| Time per evaluation | 10-30 minutes | 4.5 milliseconds | **2,000-500,000x** |
|
||||
| Trials per hour | 2-6 | 800,000+ | **1000x** |
|
||||
| Design exploration | ~50 designs | ~50,000 designs | **1000x** |
|
||||
|
||||
**Model Types**:
|
||||
|
||||
| Model | Purpose | Use When |
|
||||
|-------|---------|----------|
|
||||
| **MLP Surrogate** | Direct objective prediction | Simple studies, quick setup |
|
||||
| Field Predictor GNN | Full displacement/stress fields | Need field visualization |
|
||||
| Parametric Predictor GNN | Direct objective prediction | Complex geometry, need accuracy |
|
||||
| Ensemble | Uncertainty quantification | Need confidence bounds |
|
||||
|
||||
---
|
||||
|
||||
## MLP Surrogate (Recommended for Quick Start)
|
||||
|
||||
### Overview
|
||||
|
||||
The MLP (Multi-Layer Perceptron) surrogate is a simple but effective neural network that predicts objectives directly from design parameters. It's integrated into the study workflow via `run_nn_optimization.py`.
|
||||
|
||||
### Architecture
|
||||
|
||||
```
|
||||
Input Layer (N design variables)
|
||||
↓
|
||||
Linear(N, 64) + ReLU + BatchNorm + Dropout(0.1)
|
||||
↓
|
||||
Linear(64, 128) + ReLU + BatchNorm + Dropout(0.1)
|
||||
↓
|
||||
Linear(128, 128) + ReLU + BatchNorm + Dropout(0.1)
|
||||
↓
|
||||
Linear(128, 64) + ReLU + BatchNorm + Dropout(0.1)
|
||||
↓
|
||||
Linear(64, M objectives)
|
||||
```
|
||||
|
||||
**Parameters**: ~34,000 trainable
|
||||
|
||||
### Workflow Modes
|
||||
|
||||
#### 1. Standard Hybrid Mode (`--all`)
|
||||
|
||||
Run all phases sequentially:
|
||||
```bash
|
||||
python run_nn_optimization.py --all
|
||||
```
|
||||
|
||||
Phases:
|
||||
1. **Export**: Extract training data from existing FEA trials
|
||||
2. **Train**: Train MLP surrogate (300 epochs default)
|
||||
3. **NN-Optimize**: Run 1000 NN trials with NSGA-II
|
||||
4. **Validate**: Validate top 10 candidates with FEA
|
||||
|
||||
#### 2. Hybrid Loop Mode (`--hybrid-loop`)
|
||||
|
||||
Iterative refinement:
|
||||
```bash
|
||||
python run_nn_optimization.py --hybrid-loop --iterations 5 --nn-trials 500
|
||||
```
|
||||
|
||||
Each iteration:
|
||||
1. Train/retrain surrogate from current FEA data
|
||||
2. Run NN optimization
|
||||
3. Validate top candidates with FEA
|
||||
4. Add validated results to training set
|
||||
5. Repeat until convergence (max error < 5%)
|
||||
|
||||
#### 3. Turbo Mode (`--turbo`) ⚡ RECOMMENDED
|
||||
|
||||
Aggressive single-best validation:
|
||||
```bash
|
||||
python run_nn_optimization.py --turbo --nn-trials 5000 --batch-size 100 --retrain-every 10
|
||||
```
|
||||
|
||||
Strategy:
|
||||
- Run NN in small batches (100 trials)
|
||||
- Validate ONLY the single best candidate with FEA
|
||||
- Add to training data immediately
|
||||
- Retrain surrogate every N FEA validations
|
||||
- Repeat until total NN budget exhausted
|
||||
|
||||
**Example**: 5,000 NN trials with batch=100 → 50 FEA validations in ~12 minutes
|
||||
|
||||
### Configuration
|
||||
|
||||
```json
|
||||
{
|
||||
"neural_acceleration": {
|
||||
"enabled": true,
|
||||
"min_training_points": 50,
|
||||
"auto_train": true,
|
||||
"epochs": 300,
|
||||
"validation_split": 0.2,
|
||||
"nn_trials": 1000,
|
||||
"validate_top_n": 10,
|
||||
"model_file": "surrogate_best.pt",
|
||||
"separate_nn_database": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Important**: `separate_nn_database: true` stores NN trials in `nn_study.db` instead of `study.db` to avoid overloading the dashboard with thousands of NN-only results.
|
||||
|
||||
### Typical Accuracy
|
||||
|
||||
| Objective | Expected Error |
|
||||
|-----------|----------------|
|
||||
| Mass | 1-5% |
|
||||
| Stress | 1-4% |
|
||||
| Stiffness | 5-15% |
|
||||
|
||||
### Output Files
|
||||
|
||||
```
|
||||
2_results/
|
||||
├── study.db # Main FEA + validated results (dashboard)
|
||||
├── nn_study.db # NN-only results (not in dashboard)
|
||||
├── surrogate_best.pt # Trained model weights
|
||||
├── training_data.json # Normalized training data
|
||||
├── nn_optimization_state.json # NN optimization state
|
||||
├── nn_pareto_front.json # NN-predicted Pareto front
|
||||
├── validation_report.json # FEA validation results
|
||||
└── turbo_report.json # Turbo mode results (if used)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## GNN Field Predictor (Advanced)
|
||||
|
||||
### Core Components
|
||||
|
||||
| Component | File | Purpose |
|
||||
|-----------|------|---------|
|
||||
| BDF/OP2 Parser | `neural_field_parser.py` | Convert NX files to neural format |
|
||||
| Data Validator | `validate_parsed_data.py` | Physics and quality checks |
|
||||
| Field Predictor | `field_predictor.py` | GNN for full field prediction |
|
||||
| Parametric Predictor | `parametric_predictor.py` | GNN for direct objectives |
|
||||
| Physics Loss | `physics_losses.py` | Physics-informed training |
|
||||
| Neural Surrogate | `neural_surrogate.py` | Integration with Atomizer |
|
||||
| Neural Runner | `runner_with_neural.py` | Optimization with NN acceleration |
|
||||
|
||||
### Workflow Diagram
|
||||
|
||||
```
|
||||
Traditional:
|
||||
Design → NX Model → Mesh → Solve (30 min) → Results → Objective
|
||||
|
||||
Neural (after training):
|
||||
Design → Neural Network (4.5 ms) → Results → Objective
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Neural Model Types
|
||||
|
||||
### 1. Field Predictor GNN
|
||||
|
||||
**Use Case**: When you need full field predictions (stress distribution, deformation shape).
|
||||
|
||||
```
|
||||
Input Features (12D per node):
|
||||
├── Node coordinates (x, y, z)
|
||||
├── Material properties (E, nu, rho)
|
||||
├── Boundary conditions (fixed/free per DOF)
|
||||
└── Load information (force magnitude, direction)
|
||||
|
||||
GNN Layers (6 message passing):
|
||||
├── MeshGraphConv (custom for FEA topology)
|
||||
├── Layer normalization
|
||||
├── ReLU activation
|
||||
└── Dropout (0.1)
|
||||
|
||||
Output (per node):
|
||||
├── Displacement (6 DOF: Tx, Ty, Tz, Rx, Ry, Rz)
|
||||
└── Von Mises stress (1 value)
|
||||
```
|
||||
|
||||
**Parameters**: ~718,221 trainable
|
||||
|
||||
### 2. Parametric Predictor GNN (Recommended)
|
||||
|
||||
**Use Case**: Direct optimization objective prediction (fastest option).
|
||||
|
||||
```
|
||||
Design Parameters (ND) → Design Encoder (MLP) → GNN Backbone → Scalar Heads
|
||||
|
||||
Output (objectives):
|
||||
├── mass (grams)
|
||||
├── frequency (Hz)
|
||||
├── max_displacement (mm)
|
||||
└── max_stress (MPa)
|
||||
```
|
||||
|
||||
**Parameters**: ~500,000 trainable
|
||||
|
||||
### 3. Ensemble Models
|
||||
|
||||
**Use Case**: Uncertainty quantification.
|
||||
|
||||
1. Train 3-5 models with different random seeds
|
||||
2. At inference, run all models
|
||||
3. Use mean for prediction, std for uncertainty
|
||||
4. High uncertainty → trigger FEA validation
|
||||
|
||||
---
|
||||
|
||||
## Training Pipeline
|
||||
|
||||
### Step 1: Collect Training Data
|
||||
|
||||
Enable export in workflow config:
|
||||
|
||||
```json
|
||||
{
|
||||
"training_data_export": {
|
||||
"enabled": true,
|
||||
"export_dir": "atomizer_field_training_data/my_study"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Output structure:
|
||||
```
|
||||
atomizer_field_training_data/my_study/
|
||||
├── trial_0001/
|
||||
│ ├── input/model.bdf # Nastran input
|
||||
│ ├── output/model.op2 # Binary results
|
||||
│ └── metadata.json # Design params + objectives
|
||||
├── trial_0002/
|
||||
│ └── ...
|
||||
└── study_summary.json
|
||||
```
|
||||
|
||||
**Recommended**: 100-500 FEA samples for good generalization.
|
||||
|
||||
### Step 2: Parse to Neural Format
|
||||
|
||||
```bash
|
||||
cd atomizer-field
|
||||
python batch_parser.py ../atomizer_field_training_data/my_study
|
||||
```
|
||||
|
||||
Creates HDF5 + JSON files per trial.
|
||||
|
||||
### Step 3: Train Model
|
||||
|
||||
**Parametric Predictor** (recommended):
|
||||
```bash
|
||||
python train_parametric.py \
|
||||
--train_dir ../training_data/parsed \
|
||||
--val_dir ../validation_data/parsed \
|
||||
--epochs 200 \
|
||||
--hidden_channels 128 \
|
||||
--num_layers 4
|
||||
```
|
||||
|
||||
**Field Predictor**:
|
||||
```bash
|
||||
python train.py \
|
||||
--train_dir ../training_data/parsed \
|
||||
--epochs 200 \
|
||||
--model FieldPredictorGNN \
|
||||
--hidden_channels 128 \
|
||||
--num_layers 6 \
|
||||
--physics_loss_weight 0.3
|
||||
```
|
||||
|
||||
### Step 4: Validate
|
||||
|
||||
```bash
|
||||
python validate.py --checkpoint runs/my_model/checkpoint_best.pt
|
||||
```
|
||||
|
||||
Expected output:
|
||||
```
|
||||
Validation Results:
|
||||
├── Mean Absolute Error: 2.3% (mass), 1.8% (frequency)
|
||||
├── R² Score: 0.987
|
||||
├── Inference Time: 4.5ms ± 0.8ms
|
||||
└── Physics Violations: 0.2%
|
||||
```
|
||||
|
||||
### Step 5: Deploy
|
||||
|
||||
```json
|
||||
{
|
||||
"neural_surrogate": {
|
||||
"enabled": true,
|
||||
"model_checkpoint": "atomizer-field/runs/my_model/checkpoint_best.pt",
|
||||
"confidence_threshold": 0.85
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Configuration
|
||||
|
||||
### Full Neural Configuration Example
|
||||
|
||||
```json
|
||||
{
|
||||
"study_name": "bracket_neural_optimization",
|
||||
|
||||
"surrogate_settings": {
|
||||
"enabled": true,
|
||||
"model_type": "parametric_gnn",
|
||||
"model_path": "models/bracket_surrogate.pt",
|
||||
"confidence_threshold": 0.85,
|
||||
"validation_frequency": 10,
|
||||
"fallback_to_fea": true
|
||||
},
|
||||
|
||||
"training_data_export": {
|
||||
"enabled": true,
|
||||
"export_dir": "atomizer_field_training_data/bracket_study",
|
||||
"export_bdf": true,
|
||||
"export_op2": true,
|
||||
"export_fields": ["displacement", "stress"]
|
||||
},
|
||||
|
||||
"neural_optimization": {
|
||||
"initial_fea_trials": 50,
|
||||
"neural_trials": 5000,
|
||||
"retraining_interval": 500,
|
||||
"uncertainty_threshold": 0.15
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Configuration Parameters
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
|-----------|------|---------|-------------|
|
||||
| `enabled` | bool | false | Enable neural surrogate |
|
||||
| `model_type` | string | "parametric_gnn" | Model architecture |
|
||||
| `model_path` | string | - | Path to trained model |
|
||||
| `confidence_threshold` | float | 0.85 | Min confidence for predictions |
|
||||
| `validation_frequency` | int | 10 | FEA validation every N trials |
|
||||
| `fallback_to_fea` | bool | true | Use FEA when uncertain |
|
||||
|
||||
---
|
||||
|
||||
## Hybrid FEA/Neural Workflow
|
||||
|
||||
### Phase 1: FEA Exploration (50-100 trials)
|
||||
- Run standard FEA optimization
|
||||
- Export training data automatically
|
||||
- Build landscape understanding
|
||||
|
||||
### Phase 2: Neural Training
|
||||
- Parse collected data
|
||||
- Train parametric predictor
|
||||
- Validate accuracy
|
||||
|
||||
### Phase 3: Neural Acceleration (1000s of trials)
|
||||
- Use neural network for rapid exploration
|
||||
- Periodic FEA validation
|
||||
- Retrain if distribution shifts
|
||||
|
||||
### Phase 4: FEA Refinement (10-20 trials)
|
||||
- Validate top candidates with FEA
|
||||
- Ensure results are physically accurate
|
||||
- Generate final Pareto front
|
||||
|
||||
---
|
||||
|
||||
## Adaptive Iteration Loop
|
||||
|
||||
For complex optimizations, use iterative refinement:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Iteration 1: │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ Initial FEA │ -> │ Train NN │ -> │ NN Search │ │
|
||||
│ │ (50-100) │ │ Surrogate │ │ (1000 trials)│ │
|
||||
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
||||
│ │ │
|
||||
│ Iteration 2+: ▼ │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ Validate Top │ -> │ Retrain NN │ -> │ NN Search │ │
|
||||
│ │ NN with FEA │ │ with new data│ │ (1000 trials)│ │
|
||||
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Adaptive Configuration
|
||||
|
||||
```json
|
||||
{
|
||||
"adaptive_settings": {
|
||||
"enabled": true,
|
||||
"initial_fea_trials": 50,
|
||||
"nn_trials_per_iteration": 1000,
|
||||
"fea_validation_per_iteration": 5,
|
||||
"max_iterations": 10,
|
||||
"convergence_threshold": 0.01,
|
||||
"retrain_epochs": 100
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Convergence Criteria
|
||||
|
||||
Stop when:
|
||||
- No improvement for 2-3 consecutive iterations
|
||||
- Reached FEA budget limit
|
||||
- Objective improvement < 1% threshold
|
||||
|
||||
### Output Files
|
||||
|
||||
```
|
||||
studies/my_study/3_results/
|
||||
├── adaptive_state.json # Current iteration state
|
||||
├── surrogate_model.pt # Trained neural network
|
||||
└── training_history.json # NN training metrics
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Loss Functions
|
||||
|
||||
### Data Loss (MSE)
|
||||
Standard prediction error:
|
||||
```python
|
||||
data_loss = MSE(predicted, target)
|
||||
```
|
||||
|
||||
### Physics Loss
|
||||
Enforce physical constraints:
|
||||
```python
|
||||
physics_loss = (
|
||||
equilibrium_loss + # Force balance
|
||||
boundary_loss + # BC satisfaction
|
||||
compatibility_loss # Strain compatibility
|
||||
)
|
||||
```
|
||||
|
||||
### Combined Training
|
||||
```python
|
||||
total_loss = data_loss + 0.3 * physics_loss
|
||||
```
|
||||
|
||||
Physics loss weight typically 0.1-0.5.
|
||||
|
||||
---
|
||||
|
||||
## Uncertainty Quantification
|
||||
|
||||
### Ensemble Method
|
||||
```python
|
||||
# Run N models
|
||||
predictions = [model_i(x) for model_i in ensemble]
|
||||
|
||||
# Statistics
|
||||
mean_prediction = np.mean(predictions)
|
||||
uncertainty = np.std(predictions)
|
||||
|
||||
# Decision
|
||||
if uncertainty > threshold:
|
||||
# Use FEA instead
|
||||
result = run_fea(x)
|
||||
else:
|
||||
result = mean_prediction
|
||||
```
|
||||
|
||||
### Confidence Thresholds
|
||||
|
||||
| Uncertainty | Action |
|
||||
|-------------|--------|
|
||||
| < 5% | Use neural prediction |
|
||||
| 5-15% | Use neural, flag for validation |
|
||||
| > 15% | Fall back to FEA |
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Symptom | Cause | Solution |
|
||||
|---------|-------|----------|
|
||||
| High prediction error | Insufficient training data | Collect more FEA samples |
|
||||
| Out-of-distribution warnings | Design outside training range | Retrain with expanded range |
|
||||
| Slow inference | Large mesh | Use parametric predictor instead |
|
||||
| Physics violations | Low physics loss weight | Increase `physics_loss_weight` |
|
||||
|
||||
---
|
||||
|
||||
## Cross-References
|
||||
|
||||
- **Depends On**: [SYS_10_IMSO](./SYS_10_IMSO.md) for optimization framework
|
||||
- **Used By**: [OP_02_RUN_OPTIMIZATION](../operations/OP_02_RUN_OPTIMIZATION.md), [OP_05_EXPORT_TRAINING_DATA](../operations/OP_05_EXPORT_TRAINING_DATA.md)
|
||||
- **See Also**: [modules/neural-acceleration.md](../../.claude/skills/modules/neural-acceleration.md)
|
||||
|
||||
---
|
||||
|
||||
## Implementation Files
|
||||
|
||||
```
|
||||
atomizer-field/
|
||||
├── neural_field_parser.py # BDF/OP2 parsing
|
||||
├── field_predictor.py # Field GNN
|
||||
├── parametric_predictor.py # Parametric GNN
|
||||
├── train.py # Field training
|
||||
├── train_parametric.py # Parametric training
|
||||
├── validate.py # Model validation
|
||||
├── physics_losses.py # Physics-informed loss
|
||||
└── batch_parser.py # Batch data conversion
|
||||
|
||||
optimization_engine/
|
||||
├── neural_surrogate.py # Atomizer integration
|
||||
└── runner_with_neural.py # Neural runner
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Version History
|
||||
|
||||
| Version | Date | Changes |
|
||||
|---------|------|---------|
|
||||
| 2.0 | 2025-12-06 | Added MLP Surrogate with Turbo Mode |
|
||||
| 1.0 | 2025-12-05 | Initial consolidation from neural docs |
|
||||
Reference in New Issue
Block a user