Bases: Objective
        Computes the B-optimal design metric.
  Refer to the following paper for more details
  
- Approximate Sequential Optimization for Informative Path Planning [Ott et al., 2024]
 
         B-optimality minimizes the trace of the inverse of the covariance matrix 
\(-Tr(K(X, X)^{-1})\). Since optimization 
algorithms typically minimize a function, this objective returns 
\(Tr(K(X, X)^{-1})\), which is then maximized.
              
                Source code in sgptools/objectives.py
                 | class  BOptimal(Objective):     
    """
    Computes the B-optimal design metric.
    Refer to the following paper for more details:
        - Approximate Sequential Optimization for Informative Path Planning [Ott et al., 2024]
    B-optimality minimizes the trace of the inverse of the covariance matrix 
    $-Tr(K(X, X)^{-1})$. Since optimization 
    algorithms typically minimize a function, this objective returns 
    $Tr(K(X, X)^{-1})$, which is then maximized.
    """       
    def __call__(self, X: tf.Tensor) -> tf.Tensor:
        """
        Computes the trace of the inverse of the covariance matrix $Tr(K(X, X)^{-1})$.
        Args:
            X (tf.Tensor): The input points (e.g., sensing locations) for which
                           the objective is to be computed. Shape: (M, D).
        Returns:
            tf.Tensor: The computed B-optimal metric value.
        Usage:
            ```python
            import gpflow
            import numpy as np
            # Assume kernel is defined
            # X_objective = np.random.rand(100, 2) # Not used by B-Optimal but required by base class
            # kernel = gpflow.kernels.SquaredExponential()
            # noise_variance = 0.1
            b_optimal_objective = BOptimal(
                X_objective=X_objective,
                kernel=kernel,
                noise_variance=noise_variance
            )
            X_sensing = tf.constant(np.random.rand(10, 2), dtype=tf.float64)
            b_optimal_value = b_optimal_objective(X_sensing)
            ```
        """
        # K(X, X)
        K_X_X = self.kernel(X)
        inv_K_X_X = tf.linalg.inv(self.jitter_fn(K_X_X))
        trace_inv_K_X_X = tf.linalg.trace(inv_K_X_X)
        return trace_inv_K_X_X
  | 
 
               
  
    
        Computes the trace of the inverse of the covariance matrix \(Tr(K(X, X)^{-1})\).
Parameters:
    
      
        
          | Name | 
          Type | 
          Description | 
          Default | 
        
      
      
          
            
                X
             | 
            
                  Tensor
             | 
            
              
                The input points (e.g., sensing locations) for which
           the objective is to be computed. Shape: (M, D). 
               
             | 
            
                required
             | 
          
      
    
    Returns:
    
      
        
          | Type | 
          Description | 
        
      
      
          
            
                  Tensor
             | 
            
              
                tf.Tensor: The computed B-optimal metric value. 
               
             | 
          
      
    
  Usage
  import gpflow
import numpy as np
# Assume kernel is defined
# X_objective = np.random.rand(100, 2) # Not used by B-Optimal but required by base class
# kernel = gpflow.kernels.SquaredExponential()
# noise_variance = 0.1
b_optimal_objective = BOptimal(
    X_objective=X_objective,
    kernel=kernel,
    noise_variance=noise_variance
)
X_sensing = tf.constant(np.random.rand(10, 2), dtype=tf.float64)
b_optimal_value = b_optimal_objective(X_sensing)
 
 
            
              Source code in sgptools/objectives.py
               | def __call__(self, X: tf.Tensor) -> tf.Tensor:
    """
    Computes the trace of the inverse of the covariance matrix $Tr(K(X, X)^{-1})$.
    Args:
        X (tf.Tensor): The input points (e.g., sensing locations) for which
                       the objective is to be computed. Shape: (M, D).
    Returns:
        tf.Tensor: The computed B-optimal metric value.
    Usage:
        ```python
        import gpflow
        import numpy as np
        # Assume kernel is defined
        # X_objective = np.random.rand(100, 2) # Not used by B-Optimal but required by base class
        # kernel = gpflow.kernels.SquaredExponential()
        # noise_variance = 0.1
        b_optimal_objective = BOptimal(
            X_objective=X_objective,
            kernel=kernel,
            noise_variance=noise_variance
        )
        X_sensing = tf.constant(np.random.rand(10, 2), dtype=tf.float64)
        b_optimal_value = b_optimal_objective(X_sensing)
        ```
    """
    # K(X, X)
    K_X_X = self.kernel(X)
    inv_K_X_X = tf.linalg.inv(self.jitter_fn(K_X_X))
    trace_inv_K_X_X = tf.linalg.trace(inv_K_X_X)
    return trace_inv_K_X_X
  |