""" Generate human-readable optimization reports from incremental history JSON. This script should be run automatically at the end of optimization, or manually to generate a report for any completed optimization study. """ import json import sys from pathlib import Path from typing import Dict, Any, List import numpy as np def generate_optimization_report(history_file: Path, target_value: float = None, tolerance: float = 0.1) -> str: """ Generate a comprehensive human-readable optimization report. Args: history_file: Path to optimization_history_incremental.json target_value: Target objective value (if applicable) tolerance: Acceptable tolerance for success (default 0.1) Returns: Report text as a string """ # Load history with open(history_file) as f: history = json.load(f) if not history: return "No optimization history found." report = [] report.append('=' * 80) report.append('OPTIMIZATION REPORT') report.append('=' * 80) report.append('') # Study information study_dir = history_file.parent.parent.parent study_name = study_dir.name report.append('STUDY INFORMATION') report.append('-' * 80) report.append(f'Study: {study_name}') report.append(f'Total trials: {len(history)}') report.append('') # Design variables first_trial = history[0] design_vars = list(first_trial['design_variables'].keys()) report.append('DESIGN VARIABLES') report.append('-' * 80) for var in design_vars: values = [t['design_variables'][var] for t in history] report.append(f' {var}:') report.append(f' Range: {min(values):.4f} - {max(values):.4f}') report.append(f' Mean: {np.mean(values):.4f}') report.append('') # Objective results results = list(first_trial['results'].keys()) report.append('OBJECTIVE RESULTS') report.append('-' * 80) for result in results: values = [t['results'][result] for t in history] report.append(f' {result}:') report.append(f' Range: {min(values):.4f} - {max(values):.4f}') report.append(f' Mean: {np.mean(values):.4f}') report.append(f' Std dev: {np.std(values):.4f}') report.append('') # Best trial objectives = [t['objective'] for t in history] best_trial = history[np.argmin(objectives)] report.append('BEST TRIAL') report.append('-' * 80) report.append(f'Trial #{best_trial["trial_number"]}') report.append(f' Objective value: {best_trial["objective"]:.4f}') report.append(' Design variables:') for var, value in best_trial['design_variables'].items(): report.append(f' {var}: {value:.4f}') report.append(' Results:') for result, value in best_trial['results'].items(): report.append(f' {result}: {value:.4f}') report.append('') # Top 5 trials report.append('TOP 5 TRIALS (by objective value)') report.append('-' * 80) sorted_history = sorted(history, key=lambda x: x['objective']) for i, trial in enumerate(sorted_history[:5], 1): report.append(f'{i}. Trial #{trial["trial_number"]}: Objective = {trial["objective"]:.4f}') vars_str = ', '.join([f'{k}={v:.2f}' for k, v in trial['design_variables'].items()]) report.append(f' {vars_str}') report.append('') # Success assessment (if target provided) if target_value is not None: report.append('SUCCESS ASSESSMENT') report.append('-' * 80) best_objective = min(objectives) error = abs(best_objective - target_value) if error <= tolerance: report.append(f'[SUCCESS] Target {target_value} achieved within tolerance {tolerance}!') report.append(f' Best objective: {best_objective:.4f}') report.append(f' Error: {error:.4f}') else: report.append(f'[INCOMPLETE] Target {target_value} not achieved') report.append(f' Best objective: {best_objective:.4f}') report.append(f' Error: {error:.4f}') report.append(f' Need {error - tolerance:.4f} improvement') report.append('') report.append('=' * 80) return '\n'.join(report) def main(): """Command-line interface for report generation.""" if len(sys.argv) < 2: print("Usage: python generate_report.py [target_value] [tolerance]") print("Example: python generate_report.py studies/my_study/2_substudies/results/optimization_history_incremental.json 115.0 0.1") sys.exit(1) history_file = Path(sys.argv[1]) if not history_file.exists(): print(f"Error: History file not found: {history_file}") sys.exit(1) target_value = float(sys.argv[2]) if len(sys.argv) > 2 else None tolerance = float(sys.argv[3]) if len(sys.argv) > 3 else 0.1 # Generate report report = generate_optimization_report(history_file, target_value, tolerance) # Save report report_file = history_file.parent / 'OPTIMIZATION_REPORT.txt' with open(report_file, 'w') as f: f.write(report) # Print to console print(report) print() print(f"Report saved to: {report_file}") if __name__ == '__main__': main()