1
+
2
+
3
+ #[ macro_export]
4
+ macro_rules! build_concrete_late_acceptance_base {
5
+
6
+ ( $me_base_name: ident, $individual_variant: ident, $score_type: ty) => {
7
+ #[ pyclass]
8
+ pub struct $me_base_name {
9
+
10
+ pub late_acceptance_size: usize ,
11
+ pub late_scores: VecDeque <$score_type>,
12
+ pub tabu_entity_rate: f64 ,
13
+
14
+ pub metaheuristic_kind: String ,
15
+ pub metaheuristic_name: String ,
16
+
17
+ pub group_mutation_rates_map: HashMap <String , f64 >,
18
+ pub discrete_ids: Option <Vec <usize >>,
19
+ pub mover: Mover ,
20
+ pub variables_manager: VariablesManager ,
21
+ }
22
+
23
+ #[ pymethods]
24
+ impl $me_base_name {
25
+
26
+ #[ new]
27
+ #[ pyo3( signature = ( variables_manager_py, late_acceptance_size, tabu_entity_rate, semantic_groups_map, mutation_rate_multiplier=None , move_probas=None , discrete_ids=None ) ) ]
28
+ pub fn new(
29
+ variables_manager_py: VariablesManagerPy ,
30
+ late_acceptance_size: usize ,
31
+ tabu_entity_rate: f64 ,
32
+ semantic_groups_map: HashMap <String , Vec <usize >>,
33
+ mutation_rate_multiplier: Option <f64 >,
34
+ move_probas: Option <Vec <f64 >>,
35
+ discrete_ids: Option <Vec <usize >>,
36
+ ) -> Self {
37
+
38
+ let current_mutation_rate_multiplier;
39
+ match mutation_rate_multiplier {
40
+ Some ( x) => current_mutation_rate_multiplier = mutation_rate_multiplier. unwrap( ) ,
41
+ None => current_mutation_rate_multiplier = 0.0 ,
42
+ }
43
+ let mut group_mutation_rates_map: HashMap <String , f64 > = HashMap :: new( ) ;
44
+ for group_name in semantic_groups_map. keys( ) {
45
+ let group_size = semantic_groups_map[ group_name] . len( ) ;
46
+ let current_group_mutation_rate = current_mutation_rate_multiplier * ( 1.0 / ( group_size as f64 ) ) ;
47
+ group_mutation_rates_map. insert( group_name. clone( ) , current_group_mutation_rate) ;
48
+ }
49
+
50
+ Self {
51
+ late_acceptance_size: late_acceptance_size,
52
+ tabu_entity_rate: tabu_entity_rate,
53
+ late_scores: VecDeque :: new( ) ,
54
+
55
+
56
+ metaheuristic_kind: "LocalSearch" . to_string( ) ,
57
+ metaheuristic_name: "LateAcceptance" . to_string( ) ,
58
+
59
+ group_mutation_rates_map: group_mutation_rates_map. clone( ) ,
60
+ discrete_ids: discrete_ids. clone( ) ,
61
+ mover: Mover :: new( tabu_entity_rate, HashMap :: new( ) , HashMap :: new( ) , HashMap :: new( ) , group_mutation_rates_map. clone( ) , move_probas) ,
62
+ variables_manager: VariablesManager :: new( variables_manager_py. variables_vec. clone( ) ) ,
63
+ }
64
+ }
65
+
66
+ fn sample_candidates_plain(
67
+ & mut self ,
68
+ population: Vec <$individual_variant>,
69
+ current_top_individual: $individual_variant,
70
+ ) -> Vec <Vec <f64 >> {
71
+
72
+ if self . mover. tabu_entity_size_map. len( ) == 0 {
73
+ let semantic_groups_map = self . variables_manager. semantic_groups_map. clone( ) ;
74
+ for ( group_name, group_ids) in semantic_groups_map {
75
+ self . mover. tabu_ids_sets_map. insert( group_name. clone( ) , HashSet :: new( ) ) ;
76
+ self . mover. tabu_entity_size_map. insert( group_name. clone( ) , max( ( self . tabu_entity_rate * ( group_ids. len( ) as f64 ) ) . ceil( ) as usize , 1 ) ) ;
77
+ self . mover. tabu_ids_vecdeque_map. insert( group_name. clone( ) , VecDeque :: new( ) ) ;
78
+ }
79
+ }
80
+
81
+ let mut candidate = population[ 0 ] . variable_values. clone( ) ;
82
+ let ( changed_candidate, changed_columns, candidate_deltas) = self . mover. do_move( & mut candidate, & self . variables_manager, false ) ;
83
+ candidate = changed_candidate. unwrap( ) ;
84
+ self . variables_manager. fix_variables( & mut candidate, changed_columns) ;
85
+ let candidate = vec![ candidate; 1 ] ;
86
+
87
+ return candidate;
88
+
89
+ }
90
+
91
+ fn sample_candidates_incremental(
92
+ & mut self ,
93
+ population: Vec <$individual_variant>,
94
+ current_top_individual: $individual_variant,
95
+ ) -> ( Vec <f64 >, Vec <Vec <( usize , f64 ) >>) {
96
+
97
+ if self . mover. tabu_entity_size_map. len( ) == 0 {
98
+ let semantic_groups_map = self . variables_manager. semantic_groups_map. clone( ) ;
99
+ for ( group_name, group_ids) in semantic_groups_map {
100
+ self . mover. tabu_ids_sets_map. insert( group_name. clone( ) , HashSet :: new( ) ) ;
101
+ self . mover. tabu_entity_size_map. insert( group_name. clone( ) , max( ( self . tabu_entity_rate * ( group_ids. len( ) as f64 ) ) . ceil( ) as usize , 1 ) ) ;
102
+ self . mover. tabu_ids_vecdeque_map. insert( group_name. clone( ) , VecDeque :: new( ) ) ;
103
+ }
104
+ }
105
+
106
+ let mut candidate = population[ 0 ] . variable_values. clone( ) ;
107
+ let ( _, changed_columns, candidate_deltas) = self . mover. do_move( & mut candidate, & self . variables_manager, true ) ;
108
+ let mut candidate_deltas = candidate_deltas. unwrap( ) ;
109
+ self . variables_manager. fix_deltas( & mut candidate_deltas, changed_columns. clone( ) ) ;
110
+ let changed_columns = changed_columns. unwrap( ) ;
111
+ let candidate_deltas: Vec <( usize , f64 ) > = changed_columns. iter( ) . zip( candidate_deltas. iter( ) ) . map( |( col_id, delta_value) | ( * col_id, * delta_value) ) . collect( ) ;
112
+ let deltas = vec![ candidate_deltas; 1 ] ;
113
+
114
+ return ( candidate, deltas) ;
115
+ }
116
+
117
+ fn build_updated_population(
118
+ & mut self ,
119
+ current_population: Vec <$individual_variant>,
120
+ candidates: Vec <$individual_variant>,
121
+ ) -> Vec <$individual_variant> {
122
+
123
+ let candidate_to_compare_score;
124
+ if self . late_scores. len( ) == 0 {
125
+ candidate_to_compare_score = current_population[ 0 ] . score. clone( ) ;
126
+ } else {
127
+ candidate_to_compare_score = self . late_scores. back( ) . unwrap( ) . clone( ) ;
128
+ }
129
+
130
+ let new_population;
131
+ let candidate_score = candidates[ 0 ] . score. clone( ) ;
132
+ if ( candidate_score <= candidate_to_compare_score) || ( candidate_score <= current_population[ 0 ] . score) {
133
+ let best_candidate = candidates[ 0 ] . clone( ) ;
134
+ new_population = vec![ best_candidate; 1 ] ;
135
+ self . late_scores. push_front( candidate_score) ;
136
+ if self . late_scores. len( ) > self . late_acceptance_size {
137
+ self . late_scores. pop_back( ) ;
138
+ }
139
+ } else {
140
+ new_population = current_population. clone( ) ;
141
+ }
142
+
143
+ return new_population;
144
+ }
145
+
146
+ fn build_updated_population_incremental(
147
+ & mut self ,
148
+ current_population: Vec <$individual_variant>,
149
+ sample: Vec <f64 >,
150
+ deltas: Vec <Vec <( usize , f64 ) >>,
151
+ scores: Vec <$score_type>,
152
+ ) -> Vec <$individual_variant> {
153
+
154
+ let late_native_score;
155
+ if self . late_scores. len( ) == 0 {
156
+ late_native_score = current_population[ 0 ] . score. clone( ) ;
157
+ } else {
158
+ late_native_score = self . late_scores. back( ) . unwrap( ) . clone( ) ;
159
+ }
160
+
161
+ let candidate_score = scores[ 0 ] . clone( ) ;
162
+
163
+ let mut sample = sample;
164
+ let new_population: Vec <$individual_variant>;
165
+ if ( candidate_score <= late_native_score) || ( candidate_score <= current_population[ 0 ] . score) {
166
+ let best_deltas = & deltas[ 0 ] ;
167
+ for ( var_id, new_value) in best_deltas {
168
+ sample[ * var_id] = * new_value;
169
+ }
170
+ let best_candidate = $individual_variant:: new( sample. clone( ) , candidate_score. clone( ) ) ;
171
+ new_population = vec![ best_candidate; 1 ] ;
172
+ self . late_scores. push_front( candidate_score) ;
173
+ if self . late_scores. len( ) > self . late_acceptance_size {
174
+ self . late_scores. pop_back( ) ;
175
+ }
176
+ } else {
177
+ new_population = current_population. clone( ) ;
178
+ }
179
+
180
+ return new_population;
181
+ }
182
+
183
+ #[ getter]
184
+ fn get_metaheuristic_kind( & self ) -> String {
185
+ self . metaheuristic_kind. clone( )
186
+ }
187
+
188
+ #[ getter]
189
+ fn get_metaheuristic_name( & self ) -> String {
190
+ self . metaheuristic_name. clone( )
191
+ }
192
+
193
+ }
194
+ } ;
195
+ }
0 commit comments