@@ -792,6 +792,7 @@ def run(self, X_start: np.ndarray = None) -> Spot:
792792
793793 Args:
794794 X_start (numpy.ndarray, optional): initial design. Defaults to None.
795+ The initial design must have shape (n, k), where n is the number of points and k is the number of dimensions.
795796
796797 Returns:
797798 Spot: The `Spot` instance configured and updated based on the optimization process.
@@ -906,6 +907,7 @@ def initialize_design(self, X_start=None) -> None:
906907
907908 Args:
908909 X_start (numpy.ndarray, optional): initial design. Defaults to None.
910+ Must be of shape (n, k), where n is the number of points and k is the number of dimensions.
909911
910912 Attributes:
911913 self.X (numpy.ndarray): initial design
@@ -965,7 +967,7 @@ def initialize_design_matrix(self, X_start=None) -> None:
965967
966968 Args:
967969 X_start (numpy.ndarray, optional): User-provided starting points
968- for the design. Shape should be (n_samples, n_features).
970+ for the design. Shape should be (n= n_samples, k= n_features).
969971 Defaults to None.
970972
971973 Returns:
@@ -975,7 +977,7 @@ def initialize_design_matrix(self, X_start=None) -> None:
975977 Raises:
976978 Exception: If the resulting design matrix has zero rows.
977979
978- Note :
980+ Notes :
979981 * If `X_start` is not in the expected shape, it is ignored.
980982
981983 Examples:
@@ -1035,15 +1037,19 @@ def initialize_design_matrix(self, X_start=None) -> None:
10351037 self .X = repair_non_numeric (X0 , self .var_type )
10361038
10371039 def _store_mo (self , y_mo ) -> None :
1038- # store y_mo in self.y_mo (append new values)
1039- if self .y_mo is None :
1040- self .y_mo = np . atleast_2d ( y_mo )
1040+ # store y_mo in self.y_mo (append new values) if mo, otherwise self.y_mo is None
1041+ if self .y_mo is None and y_mo . ndim == 2 :
1042+ self .y_mo = y_mo
10411043 else : # append new values
1042- print (f"y_mo: { y_mo } " )
1043- print (f"self.y_mo: { self .y_mo } " )
1044- print (f"y_mo.shape: { y_mo .shape } " )
1045- print (f"self.y_mo.shape: { self .y_mo .shape } " )
1046- self .y_mo = np .concatenate ((self .y_mo , y_mo ), axis = 1 )
1044+ # before stacking the arrays, check if the number of columns is the same in the mo case
1045+ if y_mo .ndim == 2 and self .y_mo .ndim == 2 :
1046+ if self .y_mo .shape [1 ] != y_mo .shape [1 ]:
1047+ print (f"Shape of y_mo: { y_mo .shape } " )
1048+ print (f"y_mo: { y_mo } " )
1049+ print (f"Shape of self.y_mo: { self .y_mo .shape } " )
1050+ print (f"self.y_mo: { self .y_mo } " )
1051+ raise ValueError (f"Number of columns (objectives) in y_mo ({ y_mo .shape [1 ]} ) " f"does not match the number of columns in self.y_mo ({ self .y_mo .shape [1 ]} )" )
1052+ self .y_mo = np .vstack ((self .y_mo , y_mo ))
10471053
10481054 def _mo2so (self , y_mo ) -> None :
10491055 """
@@ -1056,33 +1062,28 @@ def _mo2so(self, y_mo) -> None:
10561062
10571063 Args:
10581064 y_mo (numpy.ndarray):
1059- A 2D array of shape (m, n ), where ``m`` is
1060- the number of objectives and ``n`` is the number of data points.
1061-
1065+ If multi-objective values are present, this is an array of shape (n, m ), where ``m`` is
1066+ the number of objectives and ``n`` is the number of data points.
1067+ Otherwise, it is an array of shape (n,) with single-objective values.
10621068 Returns:
10631069 numpy.ndarray:
1064- A 1D array of shape (n,) with single-objective values if ``m > 1``. If only one
1065- objective is present (``m == 1``), no transformation is performed.
1070+ A 1D array of shape (n,) with single-objective values.
10661071
10671072 """
1068- n , k = get_shape (y_mo )
1069- # Ensure that y_mo is a (n, k) numpy array
1070- y_mo = np .atleast_2d (y_mo )
1071- # TODO
1072- # self._store_mo(y_mo)
1073- m = y_mo .shape [0 ] # Number of objectives
1074- if m > 1 :
1073+ n , m = get_shape (y_mo )
1074+ self ._store_mo (y_mo )
1075+ # do not use m as a condition, because m can be None, use ndim instead
1076+ if y_mo .ndim == 2 :
10751077 if self .fun_control ["fun_mo2so" ] is not None :
10761078 y0 = self .fun_control ["fun_mo2so" ](y_mo )
10771079 else :
1078- # Select the first row of an (m, k) array
1079- y0 = y_mo [0 , :]
1080+ # Select the first column of an (n,m) array
1081+ if y_mo .size > 0 :
1082+ y0 = y_mo [:, 0 ]
1083+ else :
1084+ y0 = y_mo
10801085 else :
1081- if k is None :
1082- y0 = y_mo .flatten ()
1083- else :
1084- y0 = y_mo # Keep as 2D array for single-objective case
1085-
1086+ y0 = y_mo
10861087 return y0
10871088
10881089 def evaluate_initial_design (self ) -> None :
@@ -1138,6 +1139,9 @@ def evaluate_initial_design(self) -> None:
11381139 logger .debug ("In Spot() evaluate_initial_design(), before calling self.fun: fun_control: %s" , self .fun_control )
11391140
11401141 y_mo = self .fun (X = X_all , fun_control = self .fun_control )
1142+ if self .verbosity > 1 :
1143+ print (f"y_mo as returned from fun(): { y_mo } " )
1144+ print (f"y_mo shape: { y_mo .shape } " )
11411145
11421146 # Convert multi-objective values to single-objective values
11431147 # TODO: Store y_mo in self.y_mo (append new values)
@@ -1470,9 +1474,8 @@ def update_design(self) -> None:
14701474 # (S-18): Evaluating New Solutions:
14711475 y_mo = self .fun (X = X_all , fun_control = self .fun_control )
14721476 # Convert multi-objective values to single-objective values:
1473- # TODO: Store y_mo in self.y_mo (append new values)
14741477 y0 = self ._mo2so (y_mo )
1475-
1478+ # Apply penalty for NA values works only on so values:
14761479 y0 = apply_penalty_NA (y0 , self .fun_control ["penalty_NA" ], verbosity = self .verbosity )
14771480 X0 , y0 = remove_nan (X0 , y0 , stop_on_zero_return = False )
14781481 # Append New Solutions (only if they are not nan):
@@ -1709,6 +1712,7 @@ def generate_random_point(self):
17091712 # TODO: Store y_mo in self.y_mo (append new values)
17101713 y_mo = self .fun (X = X_all , fun_control = self .fun_control )
17111714 y0 = self ._mo2so (y_mo )
1715+ # Apply penalty for NA values works only on so values:
17121716 y0 = apply_penalty_NA (y0 , self .fun_control ["penalty_NA" ], verbosity = self .verbosity )
17131717 X0 , y0 = remove_nan (X0 , y0 , stop_on_zero_return = False )
17141718 return X0 , y0
@@ -2045,8 +2049,8 @@ def plot_model(self, y_min=None, y_max=None) -> None:
20452049 X_test = np .linspace (self .lower [0 ], self .upper [0 ], 100 )
20462050 y_mo = self .fun (X = X_test .reshape (- 1 , 1 ), fun_control = self .fun_control )
20472051 # convert multi-objective values to single-objective values
2048- # TODO: Store y_mo in self.y_mo (append new values)
20492052 y_test = self ._mo2so (y_mo )
2053+ # Apply penalty for NA values works only on so values:
20502054 y_test = apply_penalty_NA (y_test , self .fun_control ["penalty_NA" ], verbosity = self .verbosity )
20512055 if isinstance (self .surrogate , Kriging ):
20522056 y_hat = self .surrogate .predict (X_test [:, np .newaxis ], return_val = "y" )
0 commit comments