@@ -505,12 +505,16 @@ def _calculate_gcv(self, weights=None):
505505 """
506506 # start_time = time.time()
507507 self .loginfo ('Calculating leave-one-out cross validation error measure gCV.' )
508+ x_train_unique , y_train_unique = (
509+ self .current_gp_model .x_train , # type: ignore
510+ self .current_gp_model .y_train , # type: ignore
511+ )
508512 loo_predictions = self .current_gp_model .loo_predictions ( # type: ignore
509- self . inputs , self . outputs
513+ x_train_unique , y_train_unique
510514 )
511515 loocv_measure = convergence_metrics .calculate_gcv (
512516 loo_predictions ,
513- self . outputs ,
517+ y_train_unique ,
514518 self .output_length_list ,
515519 weights = weights ,
516520 weight_combination = (2 / 3 , 1 / 3 ),
@@ -521,21 +525,20 @@ def _calculate_gcv(self, weights=None):
521525
522526 def _get_exploitation_candidates (self ):
523527 """
524- Assemble candidate training points for exploitation by sampling from TMCMC stages
525- after the warm start, proportionally to the provided stage weights.
528+ Assemble candidate training points for exploitation.
529+
530+ This is done by sampling from TMCMC stages after the warm start,
531+ proportionally to the provided stage weights.
526532
527533 Returns
528534 -------
529535 np.ndarray:
530536 The exploitation candidate training points of shape (n_candidates, n_parameters).
531537 dict:
532538 Dictionary mapping stage number to the number of points sampled from that stage.
533- """ # noqa: D205
534- # self.loginfo('Assembling candidate training points for exploitation.')
535- stage_weights = np .asarray (
536- self .stage_weights
537- ) # aligned with stages_after_warm_start
538- stage_weights = stage_weights / np .sum (stage_weights )
539+ """
540+ stage_weights = np .asarray (self .stage_weights )
541+ stage_weights /= np .sum (stage_weights ) # Normalize weights
539542
540543 n_candidates = self .num_candidate_training_points
541544 candidate_training_points_exploitation = []
@@ -544,26 +547,29 @@ def _get_exploitation_candidates(self):
544547 for stage_idx , stage_num in enumerate (self .stages_after_warm_start ):
545548 samples_stage = self .results ['model_parameters_dict' ][stage_num ]
546549 n_available = samples_stage .shape [0 ]
550+
547551 n_stage_samples = int (np .round (stage_weights [stage_idx ] * n_candidates ))
552+ if n_stage_samples == 0 :
553+ continue
548554
549- if n_stage_samples >= n_available :
550- selected = samples_stage
551- n_selected = n_available
552- else :
555+ if n_stage_samples <= n_available :
553556 selected_indices = np .random .choice (
554557 n_available , size = n_stage_samples , replace = False
555558 )
556559 selected = samples_stage [selected_indices ]
557- n_selected = n_stage_samples
560+ else :
561+ # Use all available samples
562+ selected = samples_stage
558563
559564 candidate_training_points_exploitation .append (selected )
560- stage_sample_counts [stage_num ] = n_selected
565+ stage_sample_counts [stage_num ] = selected . shape [ 0 ]
561566
567+ # Combine all stage samples
562568 candidate_training_points_exploitation = np .vstack (
563569 candidate_training_points_exploitation
564570 )
565571
566- # Trim if needed
572+ # Optional: globally truncate if total exceeds n_candidates (e.g., due to rounding)
567573 if candidate_training_points_exploitation .shape [0 ] > n_candidates :
568574 trim_indices = np .random .choice (
569575 candidate_training_points_exploitation .shape [0 ],
@@ -573,9 +579,7 @@ def _get_exploitation_candidates(self):
573579 candidate_training_points_exploitation = (
574580 candidate_training_points_exploitation [trim_indices ]
575581 )
576- # self.loginfo(
577- # 'Completed candidate training point selection for exploitation.'
578- # )
582+
579583 return candidate_training_points_exploitation , stage_sample_counts
580584
581585 def _summarize_iteration (self ):
@@ -801,8 +805,13 @@ def _step_1_posterior_approximation(
801805 self .gp_prediction_mean , _ = self .current_gp_model .predict ( # type: ignore
802806 model_parameters
803807 )
808+ # self.loo_predictions = self.current_gp_model.loo_predictions( # type: ignore
809+ # model_parameters, model_outputs
810+ # )
811+
804812 self .loo_predictions = self .current_gp_model .loo_predictions ( # type: ignore
805- model_parameters , model_outputs
813+ self .current_gp_model .x_train , # type: ignore
814+ self .current_gp_model .y_train , # type: ignore
806815 )
807816
808817 self .current_response_approximation = partial (
@@ -856,7 +865,9 @@ def _step_2_bayesian_updating(self, log_prior_fn, log_like_fn):
856865
857866 with self .log_step ('Evaluating warm-start of TMCMC.' ):
858867 if self .iteration_number > 0 :
859- weights = self .kde .evaluate (self .inputs ) # type: ignore
868+ weights = self .kde .evaluate ( # type: ignore
869+ self .current_gp_model .x_train # type: ignore
870+ ) # inputs deduplicated in the gp model
860871 self .gcv = self ._calculate_gcv (weights )
861872 self .warm_start_possible = self .gcv <= self .gcv_threshold
862873
@@ -1058,7 +1069,7 @@ def _step_4_adaptive_training_point_selection(self):
10581069 (0 , self .input_dimension )
10591070 )
10601071
1061- current_inputs = self .inputs . copy ()
1072+ current_inputs = self .current_gp_model . x_train . copy () # type: ignore
10621073 if self .n_exploit > 0 :
10631074 self .exploitation_training_points = (
10641075 current_doe .select_training_points (
0 commit comments