Files
Atomizer/archive/scripts/create_intelligent_study.py

598 lines
18 KiB
Python
Raw Normal View History

"""
Create a new circular plate frequency tuning study using Protocol 10.
This script creates a complete study configured for intelligent multi-strategy
optimization (IMSO) to test the self-tuning framework.
"""
import json
import shutil
from pathlib import Path
# Study configuration
STUDY_NAME = "circular_plate_frequency_tuning_intelligent_optimizer"
BASE_DIR = Path(__file__).parent
STUDIES_DIR = BASE_DIR / "studies"
STUDY_DIR = STUDIES_DIR / STUDY_NAME
# Source model files (copy from examples)
SOURCE_MODEL_DIR = BASE_DIR / "examples" / "Models" / "Circular Plate"
def create_study_structure():
"""Create complete study directory structure."""
print(f"Creating study: {STUDY_NAME}")
# Create directories
setup_dir = STUDY_DIR / "1_setup"
model_dir = setup_dir / "model"
results_dir = STUDY_DIR / "2_results"
reports_dir = STUDY_DIR / "3_reports"
for directory in [setup_dir, model_dir, results_dir, reports_dir]:
directory.mkdir(parents=True, exist_ok=True)
print(f" Created: {directory.relative_to(BASE_DIR)}")
return setup_dir, model_dir, results_dir, reports_dir
def copy_model_files(model_dir):
"""Copy model files from examples."""
print("\nCopying model files...")
model_files = [
"Circular_Plate.prt",
"Circular_Plate_sim1.sim",
"Circular_Plate_fem1.fem",
"Circular_Plate_fem1_i.prt"
]
for filename in model_files:
source = SOURCE_MODEL_DIR / filename
dest = model_dir / filename
if source.exists():
shutil.copy2(source, dest)
print(f" Copied: {filename}")
else:
print(f" WARNING: Source not found: {filename}")
return list(model_dir.glob("*"))
def create_workflow_config(setup_dir):
"""Create workflow configuration."""
print("\nCreating workflow configuration...")
workflow = {
"study_name": STUDY_NAME,
"optimization_request": "Tune the first natural frequency mode to exactly 115 Hz using intelligent multi-strategy optimization",
"design_variables": [
{
"parameter": "inner_diameter",
"bounds": [50, 150],
"units": "mm",
"description": "Inner diameter of circular plate"
},
{
"parameter": "plate_thickness",
"bounds": [2, 10],
"units": "mm",
"description": "Thickness of circular plate"
}
],
"objectives": [
{
"name": "frequency_error",
"goal": "minimize",
"extraction": {
"action": "extract_first_natural_frequency",
"params": {
"mode_number": 1,
"target_frequency": 115.0
}
}
}
],
"constraints": [
{
"name": "frequency_tolerance",
"type": "less_than",
"threshold": 0.1,
"description": "Error from target must be less than 0.1 Hz"
}
]
}
workflow_file = setup_dir / "workflow_config.json"
with open(workflow_file, 'w', encoding='utf-8') as f:
json.dump(workflow, f, indent=2)
print(f" Saved: {workflow_file.relative_to(BASE_DIR)}")
return workflow
def create_optimization_config(setup_dir):
"""Create Protocol 10 optimization configuration."""
print("\nCreating Protocol 10 optimization configuration...")
config = {
"_description": "Protocol 10: Intelligent Multi-Strategy Optimization - Circular Plate Test",
"_version": "1.0",
"study_name": STUDY_NAME,
"direction": "minimize",
"intelligent_optimization": {
"_description": "Protocol 10 - Automatic landscape analysis and strategy selection",
"enabled": True,
"characterization_trials": 15,
"stagnation_window": 10,
"min_improvement_threshold": 0.001,
"min_analysis_trials": 10,
"reanalysis_interval": 15,
"strategy_preferences": {
"prefer_cmaes_for_smooth": True,
"prefer_tpe_for_multimodal": True,
"enable_hybrid_strategies": False
}
},
"sampler": {
"_description": "Fallback sampler if Protocol 10 disabled",
"type": "TPESampler",
"params": {
"n_startup_trials": 10,
"n_ei_candidates": 24,
"multivariate": True,
"warn_independent_sampling": True
}
},
"pruner": {
"type": "MedianPruner",
"params": {
"n_startup_trials": 5,
"n_warmup_steps": 0
}
},
"adaptive_strategy": {
"_description": "Protocol 8 - Adaptive exploitation based on surrogate confidence",
"enabled": True,
"min_confidence_for_exploitation": 0.65,
"min_trials_for_confidence": 15,
"target_confidence_metrics": {
"convergence_weight": 0.4,
"coverage_weight": 0.3,
"stability_weight": 0.3
}
},
"trials": {
"n_trials": 100,
"timeout": None,
"catch": []
},
"reporting": {
"auto_generate_plots": True,
"include_optuna_visualizations": True,
"include_confidence_report": True,
"include_strategy_performance": True,
"save_intelligence_report": True
},
"verbosity": {
"print_landscape_report": True,
"print_strategy_recommendation": True,
"print_phase_transitions": True,
"print_confidence_updates": True,
"log_to_file": True
},
"optimization_notes": "Protocol 10 Test: Atomizer will automatically characterize the circular plate problem, select the best optimization algorithm (TPE, CMA-ES, or GP-BO), and adapt strategy if stagnation is detected. Expected: smooth_unimodal landscape → CMA-ES recommendation."
}
config_file = setup_dir / "optimization_config.json"
with open(config_file, 'w', encoding='utf-8') as f:
json.dump(config, f, indent=2)
print(f" Saved: {config_file.relative_to(BASE_DIR)}")
return config
def create_runner_script(study_dir, workflow, config):
"""Create optimization runner using Protocol 10."""
print("\nCreating Protocol 10 optimization runner...")
runner_code = '''"""
Intelligent Multi-Strategy Optimization Runner
Study: circular_plate_frequency_tuning_intelligent_optimizer
This runner uses Protocol 10 (IMSO) to automatically:
1. Characterize the optimization landscape
2. Select the best optimization algorithm
3. Adapt strategy dynamically if needed
Generated: 2025-11-19
Protocol: 10 (Intelligent Multi-Strategy Optimization)
"""
import sys
import json
import optuna
from pathlib import Path
# Add optimization engine to path
sys.path.insert(0, str(Path(__file__).parent.parent.parent))
from optimization_engine.core.intelligent_optimizer import IntelligentOptimizer
from optimization_engine.nx.updater import NXParameterUpdater
from optimization_engine.nx.solver import NXSolver
from optimization_engine.extractors.frequency_extractor import extract_first_frequency
from optimization_engine.reporting.markdown_report import generate_markdown_report
def main():
"""Run Protocol 10 intelligent optimization."""
# Setup paths
study_dir = Path(__file__).parent
setup_dir = study_dir / "1_setup"
model_dir = setup_dir / "model"
results_dir = study_dir / "2_results"
reports_dir = study_dir / "3_reports"
# Create directories
results_dir.mkdir(exist_ok=True)
reports_dir.mkdir(exist_ok=True)
# Load configuration
print("\\nLoading configuration...")
with open(setup_dir / "workflow_config.json") as f:
workflow = json.load(f)
with open(setup_dir / "optimization_config.json") as f:
opt_config = json.load(f)
print(f"Study: {workflow['study_name']}")
print(f"Protocol 10: {opt_config['intelligent_optimization']['enabled']}")
# Model files
prt_file = model_dir / "Circular_Plate.prt"
sim_file = model_dir / "Circular_Plate_sim1.sim"
# Initialize NX components
updater = NXParameterUpdater(str(prt_file))
solver = NXSolver()
# Incremental history tracking
history_file = results_dir / "optimization_history_incremental.json"
history = []
def objective(trial):
"""Objective function for optimization."""
# Sample design variables
inner_diameter = trial.suggest_float('inner_diameter', 50, 150)
plate_thickness = trial.suggest_float('plate_thickness', 2, 10)
params = {
'inner_diameter': inner_diameter,
'plate_thickness': plate_thickness
}
print(f"\\n Trial #{trial.number}")
print(f" Inner Diameter: {inner_diameter:.4f} mm")
print(f" Plate Thickness: {plate_thickness:.4f} mm")
# Update CAD model
updater.update_expressions(params)
# Run simulation (use discovered solution name from benchmarking)
result = solver.run_simulation(str(sim_file), solution_name="Solution_Normal_Modes")
if not result['success']:
print(f" Simulation FAILED: {result.get('error', 'Unknown error')}")
raise optuna.TrialPruned()
# Extract frequency
op2_file = result['op2_file']
frequency = extract_first_frequency(op2_file, mode_number=1)
# Calculate objective (error from target)
target_frequency = 115.0
objective_value = abs(frequency - target_frequency)
print(f" Frequency: {frequency:.4f} Hz")
print(f" Target: {target_frequency:.4f} Hz")
print(f" Error: {objective_value:.4f} Hz")
# Save to incremental history
trial_data = {
"trial_number": trial.number,
"design_variables": params,
"results": {"first_frequency": frequency},
"objective": objective_value
}
history.append(trial_data)
with open(history_file, 'w', encoding='utf-8') as f:
json.dump(history, f, indent=2)
return objective_value
# Create intelligent optimizer
print("\\n" + "="*70)
print(" PROTOCOL 10: INTELLIGENT MULTI-STRATEGY OPTIMIZATION")
print("="*70)
optimizer = IntelligentOptimizer(
study_name=workflow['study_name'],
study_dir=results_dir,
config=opt_config,
verbose=True
)
# Extract design variable bounds
design_vars = {
var['parameter']: tuple(var['bounds'])
for var in workflow['design_variables']
}
# Run optimization
results = optimizer.optimize(
objective_function=objective,
design_variables=design_vars,
n_trials=opt_config['trials']['n_trials'],
target_value=115.0,
tolerance=0.1
)
# Save intelligence report
optimizer.save_intelligence_report()
# Generate markdown report
print("\\nGenerating optimization report...")
# Load study for Optuna visualizations
storage = f"sqlite:///{results_dir / 'study.db'}"
study = optuna.load_study(
study_name=workflow['study_name'],
storage=storage
)
report = generate_markdown_report(
history_file=history_file,
target_value=115.0,
tolerance=0.1,
reports_dir=reports_dir,
study=study
)
report_file = reports_dir / "OPTIMIZATION_REPORT.md"
with open(report_file, 'w', encoding='utf-8') as f:
f.write(report)
print(f"\\nReport saved: {report_file}")
# Print final summary
print("\\n" + "="*70)
print(" PROTOCOL 10 TEST COMPLETE")
print("="*70)
print(f"Best Frequency: {results['best_value'] + 115.0:.4f} Hz")
print(f"Best Error: {results['best_value']:.4f} Hz")
print(f"Best Parameters:")
for param, value in results['best_params'].items():
print(f" {param}: {value:.4f}")
if 'landscape_analysis' in results and results['landscape_analysis'].get('ready'):
landscape = results['landscape_analysis']
print(f"\\nLandscape Type: {landscape['landscape_type'].upper()}")
print(f"Recommended Strategy: {results.get('final_strategy', 'N/A').upper()}")
print("="*70)
if __name__ == "__main__":
main()
'''
runner_file = study_dir / "run_optimization.py"
with open(runner_file, 'w', encoding='utf-8') as f:
f.write(runner_code)
print(f" Saved: {runner_file.relative_to(BASE_DIR)}")
return runner_file
def create_readme(study_dir):
"""Create README for the study."""
print("\nCreating README...")
readme = f"""# {STUDY_NAME}
**Protocol 10 Test Study** - Intelligent Multi-Strategy Optimization
## Overview
This study tests Atomizer's Protocol 10 (IMSO) framework on a circular plate frequency tuning problem.
**Goal**: Tune first natural frequency to exactly 115 Hz
**Protocol 10 Features Tested**:
- Automatic landscape characterization (smoothness, multimodality, correlation)
- Intelligent strategy selection (TPE, CMA-ES, or GP-BO)
- Dynamic strategy switching based on stagnation detection
- Comprehensive decision logging for transparency
## Expected Behavior
### Stage 1: Landscape Characterization (Trials 1-15)
- Random exploration to gather data
- Analyze problem characteristics
- Expected classification: `smooth_unimodal` with strong parameter correlation
### Stage 2: Strategy Selection (Trial 15)
- Expected recommendation: **CMA-ES** (92% confidence)
- Reasoning: "Smooth unimodal with strong correlation - CMA-ES converges quickly"
### Stage 3: Adaptive Optimization (Trials 16-100)
- Run with CMA-ES sampler
- Monitor for stagnation
- Switch strategies if needed (unlikely for this problem)
## Study Structure
```
{STUDY_NAME}/
1_setup/
model/ # CAD and simulation files
workflow_config.json # Optimization goals
optimization_config.json # Protocol 10 configuration
2_results/
study.db # Optuna database
optimization_history_incremental.json
intelligent_optimizer/ # Protocol 10 tracking
strategy_transitions.json
strategy_performance.json
intelligence_report.json
3_reports/
OPTIMIZATION_REPORT.md # Final report with visualizations
```
## Running the Optimization
```bash
# Activate environment
conda activate test_env
# Run optimization
python run_optimization.py
```
## What to Look For
### Console Output
**Landscape Analysis Report**:
```
======================================================================
LANDSCAPE ANALYSIS REPORT
======================================================================
Type: SMOOTH_UNIMODAL
Smoothness: 0.7X (smooth)
Multimodal: NO (1 modes)
Parameter Correlation: 0.6X (strong)
```
**Strategy Recommendation**:
```
======================================================================
STRATEGY RECOMMENDATION
======================================================================
Recommended: CMAES
Confidence: 92.0%
Reasoning: Smooth unimodal with strong correlation - CMA-ES converges quickly
```
**Phase Transitions** (if any):
```
======================================================================
STRATEGY TRANSITION
======================================================================
Trial #45
TPE CMAES
Reason: Stagnation detected
```
### Intelligence Report
Check `2_results/intelligent_optimizer/intelligence_report.json` for:
- Complete landscape analysis
- Strategy recommendation reasoning
- All transition events
- Performance breakdown by strategy
### Optimization Report
Check `3_reports/OPTIMIZATION_REPORT.md` for:
- Best result (should be < 0.1 Hz error)
- Convergence plots
- Optuna visualizations
- (Future: Protocol 10 analysis section)
## Expected Results
**Baseline (TPE only)**: ~160 trials to achieve 0.18 Hz error
**Protocol 10 (Intelligent)**: ~60-80 trials to achieve < 0.1 Hz error
**Improvement**: 40-50% faster convergence by selecting optimal algorithm
## Configuration
See [`optimization_config.json`](1_setup/optimization_config.json) for full Protocol 10 settings.
Key parameters:
- `characterization_trials`: 15 (initial exploration)
- `stagnation_window`: 10 (trials to check for stagnation)
- `min_improvement_threshold`: 0.001 (0.1% minimum improvement)
## References
- [PROTOCOL.md](../../PROTOCOL.md) - Complete Protocol 10 documentation
- [Protocol 10 Implementation Summary](../../docs/PROTOCOL_10_IMPLEMENTATION_SUMMARY.md)
- [Example Configuration](../../examples/optimization_config_protocol10.json)
---
*Study created: 2025-11-19*
*Protocol: 10 (Intelligent Multi-Strategy Optimization)*
"""
readme_file = study_dir / "README.md"
with open(readme_file, 'w', encoding='utf-8') as f:
f.write(readme)
print(f" Saved: {readme_file.relative_to(BASE_DIR)}")
def main():
"""Create complete Protocol 10 test study."""
print("\n" + "="*70)
print(" CREATING PROTOCOL 10 TEST STUDY")
print("="*70)
# Create structure
setup_dir, model_dir, results_dir, reports_dir = create_study_structure()
# Copy model files
model_files = copy_model_files(model_dir)
# Create configurations
workflow = create_workflow_config(setup_dir)
config = create_optimization_config(setup_dir)
# Create runner
runner_file = create_runner_script(STUDY_DIR, workflow, config)
# Create README
create_readme(STUDY_DIR)
print("\n" + "="*70)
print(" STUDY CREATION COMPLETE")
print("="*70)
print(f"\nStudy directory: {STUDY_DIR.relative_to(BASE_DIR)}")
print(f"\nTo run optimization:")
print(f" cd {STUDY_DIR.relative_to(BASE_DIR)}")
print(f" python run_optimization.py")
print("\n" + "="*70)
if __name__ == "__main__":
main()