@@ -36,10 +36,10 @@ use crate::experiment_runner::unified_report::{
3636} ;
3737use crate :: OptimizationProblem ;
3838use anyhow:: Context ;
39+ use serde_json;
3940use std:: collections:: HashMap ;
4041use std:: fs;
4142use std:: path:: Path ;
42- use serde_json;
4343
4444/// Data structure for family performance comparison
4545#[ derive( Debug , Clone ) ]
@@ -166,7 +166,6 @@ impl ReportGenerator {
166166 // Generate optimizer specifications section
167167 html_content. push_str ( & generate_optimizer_specifications_section ( all_results) ?) ;
168168
169-
170169 let md_path = Path :: new ( & output_dir) . join ( "benchmark_report.md" ) ;
171170 println ! ( "Saving Markdown report to: {}" , md_path. display( ) ) ;
172171 // Ensure parent directory exists
@@ -182,7 +181,7 @@ impl ReportGenerator {
182181 generate_latex_tables ( & latex_dir. to_string_lossy ( ) , all_results, self ) . await ?;
183182 // Generate optimizer specifications JSON
184183 generate_optimizer_specifications_json ( & data_dir. to_string_lossy ( ) , all_results) ?;
185-
184+
186185 // Generate comprehensive LaTeX document
187186 generate_comprehensive_latex_document ( & self . config , all_results, & latex_dir, self ) ?;
188187 println ! ( "Report generation complete!" ) ;
@@ -567,9 +566,13 @@ This section provides detailed JSON specifications for all optimizers used in th
567566"# ,
568567 ) ;
569568 // Group by family and create summary table
570- let mut family_groups: std:: collections:: HashMap < String , Vec < & OptimizerSpecification > > = std:: collections:: HashMap :: new ( ) ;
569+ let mut family_groups: std:: collections:: HashMap < String , Vec < & OptimizerSpecification > > =
570+ std:: collections:: HashMap :: new ( ) ;
571571 for spec in optimizer_specs. values ( ) {
572- family_groups. entry ( spec. family . clone ( ) ) . or_insert_with ( Vec :: new) . push ( spec) ;
572+ family_groups
573+ . entry ( spec. family . clone ( ) )
574+ . or_insert_with ( Vec :: new)
575+ . push ( spec) ;
573576 }
574577 for ( family, specs) in family_groups {
575578 let variant_names: Vec < String > = specs. iter ( ) . map ( |s| s. name . clone ( ) ) . collect ( ) ;
@@ -617,7 +620,8 @@ fn generate_optimizer_specifications_json(
617620 metadata : SpecificationMetadata {
618621 generated_at : chrono:: Utc :: now ( ) ,
619622 total_optimizers : optimizer_specs. len ( ) ,
620- families : optimizer_specs. values ( )
623+ families : optimizer_specs
624+ . values ( )
621625 . map ( |s| s. family . clone ( ) )
622626 . collect :: < std:: collections:: HashSet < _ > > ( )
623627 . into_iter ( )
@@ -631,9 +635,16 @@ fn generate_optimizer_specifications_json(
631635 if let Some ( parent) = json_path. parent ( ) {
632636 fs:: create_dir_all ( parent) ?;
633637 }
634- fs:: write ( & json_path, json_content)
635- . with_context ( || format ! ( "Failed to write optimizer specifications to: {}" , json_path. display( ) ) ) ?;
636- println ! ( "Generated optimizer specifications: {}" , json_path. display( ) ) ;
638+ fs:: write ( & json_path, json_content) . with_context ( || {
639+ format ! (
640+ "Failed to write optimizer specifications to: {}" ,
641+ json_path. display( )
642+ )
643+ } ) ?;
644+ println ! (
645+ "Generated optimizer specifications: {}" ,
646+ json_path. display( )
647+ ) ;
637648 Ok ( ( ) )
638649}
639650/// Specification for a single optimizer
@@ -742,7 +753,8 @@ fn extract_numeric_param(optimizer_name: &str, param_name: &str) -> Option<f64>
742753 if let Some ( equals_pos) = after_param. find ( '=' ) {
743754 let after_equals = & after_param[ equals_pos + 1 ..] ;
744755 // Find the end of the number (next non-numeric character)
745- let end = after_equals. find ( |c : char | !c. is_ascii_digit ( ) && c != '.' && c != 'e' && c != '-' && c != '+' )
756+ let end = after_equals
757+ . find ( |c : char | !c. is_ascii_digit ( ) && c != '.' && c != 'e' && c != '-' && c != '+' )
746758 . unwrap_or ( after_equals. len ( ) ) ;
747759 if let Ok ( value) = after_equals[ ..end] . parse :: < f64 > ( ) {
748760 return Some ( value) ;
@@ -768,46 +780,74 @@ fn generate_optimizer_description(optimizer_name: &str) -> String {
768780 }
769781}
770782/// Extract parameter specifications for an optimizer
771- fn extract_optimizer_parameters ( optimizer_name : & str ) -> std:: collections:: HashMap < String , ParameterSpec > {
783+ fn extract_optimizer_parameters (
784+ optimizer_name : & str ,
785+ ) -> std:: collections:: HashMap < String , ParameterSpec > {
772786 let mut params = std:: collections:: HashMap :: new ( ) ;
773787 if optimizer_name. starts_with ( "QQN" ) {
774- params. insert ( "c1" . to_string ( ) , ParameterSpec {
775- value : serde_json:: json!( extract_numeric_param( optimizer_name, "c1" ) . unwrap_or( 1e-4 ) ) ,
776- description : "Armijo condition parameter for line search" . to_string ( ) ,
777- parameter_type : "float" . to_string ( ) ,
778- valid_range : Some ( "(0, 1)" . to_string ( ) ) ,
779- } ) ;
788+ params. insert (
789+ "c1" . to_string ( ) ,
790+ ParameterSpec {
791+ value : serde_json:: json!(
792+ extract_numeric_param( optimizer_name, "c1" ) . unwrap_or( 1e-4 )
793+ ) ,
794+ description : "Armijo condition parameter for line search" . to_string ( ) ,
795+ parameter_type : "float" . to_string ( ) ,
796+ valid_range : Some ( "(0, 1)" . to_string ( ) ) ,
797+ } ,
798+ ) ;
780799 params. insert ( "c2" . to_string ( ) , ParameterSpec {
781800 value : serde_json:: json!( extract_numeric_param( optimizer_name, "c2" ) . unwrap_or( 0.9 ) ) ,
782801 description : "Wolfe condition parameter for line search" . to_string ( ) ,
783802 parameter_type : "float" . to_string ( ) ,
784803 valid_range : Some ( "(c1, 1)" . to_string ( ) ) ,
785804 } ) ;
786- params. insert ( "lbfgs_history" . to_string ( ) , ParameterSpec {
787- value : serde_json:: json!( extract_numeric_param( optimizer_name, "history" ) . unwrap_or( 10.0 ) as i32 ) ,
788- description : "Number of previous iterations to store for L-BFGS approximation" . to_string ( ) ,
789- parameter_type : "integer" . to_string ( ) ,
790- valid_range : Some ( "[1, 50]" . to_string ( ) ) ,
791- } ) ;
805+ params. insert (
806+ "lbfgs_history" . to_string ( ) ,
807+ ParameterSpec {
808+ value : serde_json:: json!(
809+ extract_numeric_param( optimizer_name, "history" ) . unwrap_or( 10.0 ) as i32
810+ ) ,
811+ description : "Number of previous iterations to store for L-BFGS approximation"
812+ . to_string ( ) ,
813+ parameter_type : "integer" . to_string ( ) ,
814+ valid_range : Some ( "[1, 50]" . to_string ( ) ) ,
815+ } ,
816+ ) ;
792817 } else if optimizer_name. starts_with ( "Adam" ) {
793- params. insert ( "learning_rate" . to_string ( ) , ParameterSpec {
794- value : serde_json:: json!( extract_numeric_param( optimizer_name, "lr" ) . unwrap_or( 0.001 ) ) ,
795- description : "Learning rate for parameter updates" . to_string ( ) ,
796- parameter_type : "float" . to_string ( ) ,
797- valid_range : Some ( "(0, 1]" . to_string ( ) ) ,
798- } ) ;
799- params. insert ( "beta1" . to_string ( ) , ParameterSpec {
800- value : serde_json:: json!( extract_numeric_param( optimizer_name, "beta1" ) . unwrap_or( 0.9 ) ) ,
801- description : "Exponential decay rate for first moment estimates" . to_string ( ) ,
802- parameter_type : "float" . to_string ( ) ,
803- valid_range : Some ( "[0, 1)" . to_string ( ) ) ,
804- } ) ;
805- params. insert ( "beta2" . to_string ( ) , ParameterSpec {
806- value : serde_json:: json!( extract_numeric_param( optimizer_name, "beta2" ) . unwrap_or( 0.999 ) ) ,
807- description : "Exponential decay rate for second moment estimates" . to_string ( ) ,
808- parameter_type : "float" . to_string ( ) ,
809- valid_range : Some ( "[0, 1)" . to_string ( ) ) ,
810- } ) ;
818+ params. insert (
819+ "learning_rate" . to_string ( ) ,
820+ ParameterSpec {
821+ value : serde_json:: json!(
822+ extract_numeric_param( optimizer_name, "lr" ) . unwrap_or( 0.001 )
823+ ) ,
824+ description : "Learning rate for parameter updates" . to_string ( ) ,
825+ parameter_type : "float" . to_string ( ) ,
826+ valid_range : Some ( "(0, 1]" . to_string ( ) ) ,
827+ } ,
828+ ) ;
829+ params. insert (
830+ "beta1" . to_string ( ) ,
831+ ParameterSpec {
832+ value : serde_json:: json!(
833+ extract_numeric_param( optimizer_name, "beta1" ) . unwrap_or( 0.9 )
834+ ) ,
835+ description : "Exponential decay rate for first moment estimates" . to_string ( ) ,
836+ parameter_type : "float" . to_string ( ) ,
837+ valid_range : Some ( "[0, 1)" . to_string ( ) ) ,
838+ } ,
839+ ) ;
840+ params. insert (
841+ "beta2" . to_string ( ) ,
842+ ParameterSpec {
843+ value : serde_json:: json!(
844+ extract_numeric_param( optimizer_name, "beta2" ) . unwrap_or( 0.999 )
845+ ) ,
846+ description : "Exponential decay rate for second moment estimates" . to_string ( ) ,
847+ parameter_type : "float" . to_string ( ) ,
848+ valid_range : Some ( "[0, 1)" . to_string ( ) ) ,
849+ } ,
850+ ) ;
811851 }
812852 // Add more parameter specifications for other optimizer types as needed
813853 params
@@ -824,7 +864,6 @@ fn get_family_description(family: &str) -> String {
824864 }
825865}
826866
827-
828867/// Escape special LaTeX characters
829868pub ( crate ) fn escape_latex ( text : & str ) -> String {
830869 // Proper LaTeX escaping that avoids compilation errors
@@ -1664,4 +1703,4 @@ All raw experimental data, convergence plots, and additional analysis files are
16641703 latex_path. display( )
16651704 ) ;
16661705 Ok ( ( ) )
1667- }
1706+ }
0 commit comments