Coverage for sparkle/CLI/run_portfolio_selector.py: 91%

56 statements  

« prev     ^ index     » next       coverage.py v7.10.7, created at 2025-09-29 10:17 +0000

1#!/usr/bin/env python3 

2"""Sparkle command to execute a portfolio selector.""" 

3 

4import sys 

5import argparse 

6 

7from runrunner import Runner 

8 

9from sparkle.CLI.help import global_variables as gv 

10from sparkle.CLI.help import logging as sl 

11from sparkle.platform.settings_objects import Settings 

12from sparkle.CLI.help import argparse_custom as ac 

13from sparkle.structures import FeatureDataFrame 

14from sparkle.CLI.initialise import check_for_initialise 

15from sparkle.CLI.help.nicknames import resolve_object_name 

16from sparkle.instance import Instance_Set, InstanceSet 

17from sparkle.CLI.compute_features import compute_features 

18from sparkle.selector import SelectionScenario, Extractor 

19 

20 

21def parser_function() -> argparse.ArgumentParser: 

22 """Define the command line arguments.""" 

23 parser = argparse.ArgumentParser( 

24 description="Run a portfolio selector on instance (set): Determine which solver " 

25 "is most likely to perform well and run it on the instance (set)." 

26 ) 

27 parser.add_argument( 

28 *ac.SelectionScenarioArgument.names, **ac.SelectionScenarioArgument.kwargs 

29 ) 

30 parser.add_argument( 

31 *ac.InstanceSetRequiredArgument.names, **ac.InstanceSetRequiredArgument.kwargs 

32 ) 

33 # Settings arguments 

34 parser.add_argument(*ac.SettingsFileArgument.names, **ac.SettingsFileArgument.kwargs) 

35 parser.add_argument(*Settings.OPTION_run_on.args, **Settings.OPTION_run_on.kwargs) 

36 return parser 

37 

38 

39def main(argv: list[str]) -> None: 

40 """Main function of the run portfolio selector command.""" 

41 # Define command line arguments 

42 parser = parser_function() 

43 # Process command line arguments 

44 args = parser.parse_args(argv) 

45 settings = gv.settings(args) 

46 

47 # Log command call 

48 sl.log_command(sys.argv, settings.random_state) 

49 check_for_initialise() 

50 

51 # Compare current settings to latest.ini 

52 prev_settings = Settings(Settings.DEFAULT_previous_settings_path) 

53 Settings.check_settings_changes(settings, prev_settings) 

54 

55 data_set: InstanceSet = resolve_object_name( 

56 args.instance, 

57 gv.file_storage_data_mapping[gv.instances_nickname_path], 

58 settings.DEFAULT_instance_dir, 

59 Instance_Set, 

60 ) 

61 

62 if data_set is None: 

63 print( 

64 "ERROR: The instance (set) could not be found. Please make sure the " 

65 "path is correct." 

66 ) 

67 sys.exit(-1) 

68 

69 run_on = settings.run_on 

70 selector_scenario = SelectionScenario.from_file(args.selection_scenario) 

71 # Create a new feature dataframe for this run, compute the features 

72 test_case_path = selector_scenario.directory / data_set.name 

73 test_case_path.mkdir(exist_ok=True) 

74 feature_dataframe = FeatureDataFrame(test_case_path / "feature_data.csv") 

75 feature_dataframe.remove_instances(feature_dataframe.instances) 

76 for extractor_name in selector_scenario.feature_extractors: 

77 extractor = resolve_object_name( 

78 extractor_name, 

79 gv.file_storage_data_mapping[gv.instances_nickname_path], 

80 settings.DEFAULT_extractor_dir, 

81 Extractor, 

82 ) 

83 feature_dataframe.add_extractor(extractor_name, extractor.features) 

84 

85 feature_dataframe.add_instances(data_set.instances) 

86 feature_dataframe.save_csv() 

87 feature_runs = compute_features(feature_dataframe, recompute=False, run_on=run_on) 

88 

89 # Results need to be stored in the performance data object of the scenario: 

90 # Add the instance set to it 

91 for instance in data_set.instance_names: 

92 selector_scenario.selector_performance_data.add_instance(str(instance)) 

93 selector_scenario.selector_performance_data.save_csv() 

94 

95 selector_run = selector_scenario.selector.run_cli( 

96 scenario_path=selector_scenario.scenario_file, 

97 instance_set=data_set, 

98 feature_data=feature_dataframe.csv_filepath, 

99 run_on=run_on, 

100 slurm_prepend=settings.slurm_job_prepend, 

101 sbatch_options=settings.sbatch_settings, 

102 dependencies=feature_runs, 

103 log_dir=sl.caller_log_dir, 

104 ) 

105 

106 if run_on == Runner.LOCAL: 

107 selector_run.wait() 

108 print("Running Sparkle portfolio selector done!") 

109 else: 

110 print("Sparkle portfolio selector is running ...") 

111 

112 # Write used settings to file 

113 settings.write_used_settings() 

114 sys.exit(0) 

115 

116 

117if __name__ == "__main__": 

118 main(sys.argv[1:])