code: def solve(self, X, missing_mask):
      X = check_array(X, force_all_finite=False)
  
      observed_mask = ~missing_mask
      X_filled = X
      for i in range(self.max_iters):
          # deviation from original svdImpute algorithm:
          # gradually increase the rank of our approximation
          if self.gradual_rank_increase:
              curr_rank = min(2**i, self.rank)
          else:
              curr_rank = self.rank
          tsvd = TruncatedSVD(curr_rank, algorithm=self.svd_algorithm)
          X_reduced = tsvd.fit_transform(X_filled)
          X_reconstructed = tsvd.inverse_transform(X_reduced)
          X_reconstructed = self.clip(X_reconstructed)
          mae = masked_mae(
              X_true=X, X_pred=X_reconstructed, mask=observed_mask
          )
          if self.verbose:
              print(
                  "[IterativeSVD] Iter %d: observed MAE=%0.6f"
                  % (i + 1, mae)
              )
          converged = self._converged(
              X_old=X_filled,
              X_new=X_reconstructed,
              missing_mask=missing_mask,
          )
          X_filled[missing_mask] = X_reconstructed[missing_mask]
          if converged:
              break
      return X_filled
  
file_path: fancyimpute/fancyimpute/iterative_svd.py
imports: from sklearn.decomposition import TruncatedSVD
  from sklearn.utils import check_array
  import numpy
  from .solver import Solver
  from .common import masked_mae
label_desc: Use image node_id 3 for calling the IterativeSVD obj's underlying member method code with example usage: obj.solve(X, missing_mask) and returns: X_filled