2025-11-26 12:01:50 -05:00
"""
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 ( " \n Copying 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 ( " \n Creating 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 ( " \n Creating 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 ( " \n Creating 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 ) )
refactor: Major reorganization of optimization_engine module structure
BREAKING CHANGE: Module paths have been reorganized for better maintainability.
Backwards compatibility aliases with deprecation warnings are provided.
New Structure:
- core/ - Optimization runners (runner, intelligent_optimizer, etc.)
- processors/ - Data processing
- surrogates/ - Neural network surrogates
- nx/ - NX/Nastran integration (solver, updater, session_manager)
- study/ - Study management (creator, wizard, state, reset)
- reporting/ - Reports and analysis (visualizer, report_generator)
- config/ - Configuration management (manager, builder)
- utils/ - Utilities (logger, auto_doc, etc.)
- future/ - Research/experimental code
Migration:
- ~200 import changes across 125 files
- All __init__.py files use lazy loading to avoid circular imports
- Backwards compatibility layer supports old import paths with warnings
- All existing functionality preserved
To migrate existing code:
OLD: from optimization_engine.nx_solver import NXSolver
NEW: from optimization_engine.nx.solver import NXSolver
OLD: from optimization_engine.runner import OptimizationRunner
NEW: from optimization_engine.core.runner import OptimizationRunner
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 12:30:59 -05:00
from optimization_engine . core . intelligent_optimizer import IntelligentOptimizer
from optimization_engine . nx . updater import NXParameterUpdater
from optimization_engine . nx . solver import NXSolver
2025-11-26 12:01:50 -05:00
from optimization_engine . extractors . frequency_extractor import extract_first_frequency
refactor: Major reorganization of optimization_engine module structure
BREAKING CHANGE: Module paths have been reorganized for better maintainability.
Backwards compatibility aliases with deprecation warnings are provided.
New Structure:
- core/ - Optimization runners (runner, intelligent_optimizer, etc.)
- processors/ - Data processing
- surrogates/ - Neural network surrogates
- nx/ - NX/Nastran integration (solver, updater, session_manager)
- study/ - Study management (creator, wizard, state, reset)
- reporting/ - Reports and analysis (visualizer, report_generator)
- config/ - Configuration management (manager, builder)
- utils/ - Utilities (logger, auto_doc, etc.)
- future/ - Research/experimental code
Migration:
- ~200 import changes across 125 files
- All __init__.py files use lazy loading to avoid circular imports
- Backwards compatibility layer supports old import paths with warnings
- All existing functionality preserved
To migrate existing code:
OLD: from optimization_engine.nx_solver import NXSolver
NEW: from optimization_engine.nx.solver import NXSolver
OLD: from optimization_engine.runner import OptimizationRunner
NEW: from optimization_engine.core.runner import OptimizationRunner
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 12:30:59 -05:00
from optimization_engine . reporting . markdown_report import generate_markdown_report
2025-11-26 12:01:50 -05:00
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 ( " \n Creating 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.7 X ( smooth )
Multimodal : NO ( 1 modes )
Parameter Correlation : 0.6 X ( 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 " \n Study directory: { STUDY_DIR . relative_to ( BASE_DIR ) } " )
print ( f " \n To run optimization: " )
print ( f " cd { STUDY_DIR . relative_to ( BASE_DIR ) } " )
print ( f " python run_optimization.py " )
print ( " \n " + " = " * 70 )
if __name__ == " __main__ " :
main ( )