code: public final Solution<T> cluster(final JavaRDD<T> input_data) {
          if (k <= 0) {
              throw new IllegalStateException("k must be > 0!");
          }
  
          if (similarity == null) {
              throw new IllegalStateException("Similarity is not defined!");
          }
  
          if (budget == null) {
              throw new IllegalStateException("No budget is defined!");
          }
  
          JavaRDD<T> data = input_data.cache();
  
          // Keep track of best solution
          Solution<T> solution = new Solution<>(data.count());
          logger.debug("Dataset contains {} objects", solution.getDatasetSize());
  
          neighbor_generator.init(k);
          points_supplier = new RandomPointsSupplier<>(
                  data, solution.getDatasetSize());
  
          // Select random initial solution and evaluate
          ArrayList<T> random_medoids = points_supplier.pick(k);
          solution.setNewMedoids(random_medoids, evaluate(data, random_medoids));
          solution.incComputedSimilarities(k * solution.getDatasetSize());
  
          while (true) {
              logger.trace("Trial {}", solution.getTrials());
  
              // Select neighbor solution
              CountingSimilarity<T> counting_sim =
                      new CountingSimilarity<>(similarity);
  
              ArrayList<T> candidate;
              try {
                  candidate = neighbor_generator.getNeighbor(
                          new NeighborGeneratorHelper<>(this),
                          solution,
                          counting_sim);
              } catch (NoNeighborFoundException ex) {
                  solution.incComputedSimilarities(counting_sim.getCount());
                  break;
              }
              solution.incComputedSimilarities(counting_sim.getCount());
  
              // Evaluate
              double candidate_similarity = evaluate(data, candidate);
              solution.incComputedSimilarities(k * solution.getDatasetSize());
              neighbor_generator.notifyCandidateSolutionCost(
                      candidate, candidate_similarity);
  
              if (candidate_similarity > solution.getTotalSimilarity()) {
                  solution.setNewMedoids(candidate, candidate_similarity);
                  solution.incIterations();
                  neighbor_generator.notifyNewSolution(
                          candidate, candidate_similarity);
              }
  
              solution.incTrials();
  
              if (budget.isExhausted(solution)) {
                  break;
              }
          }
  
          solution.end();
          logger.debug("Found solution {}", solution);
          return solution;
  
      }
docs: Cluster the data according to defined parameters.
  @param input_data
  @return