docs: private void initializeCommonOptions(OptionParser parser) {
      helpOpt = parser.acceptsAll(Arrays.asList("help", "h"), "Print this help message.");
  
      randomSeed = parser.accepts("randomSeed", "Seed to use for generating random numbers. "
          + "Program execution may still be nondeterministic, if multithreading is used.").
          withRequiredArg().ofType(Long.class).defaultsTo(0L);
      
      noPrintOptions = parser.accepts("noPrintOptions", "Don't print out the command-line options "
          + "passed in to this program or final runtime statistics.");
  
      if (opts.contains(CommonOptions.STOCHASTIC_GRADIENT)) {
        sgdIterations = parser.accepts("iterations",
            "Number of iterations (passes over the data) for stochastic gradient descent.").
            withRequiredArg().ofType(Long.class).defaultsTo(10L);
        sgdBatchSize = parser.accepts("batchSize",
            "Minibatch size, i.e., the number of examples processed per gradient computation. If unspecified, defaults to using the entire data set (gradient descent).")
            .withRequiredArg().ofType(Integer.class);
        sgdInitialStep = parser.accepts("initialStepSize",
            "Initial step size for stochastic gradient descent.")
            .withRequiredArg().ofType(Double.class).defaultsTo(1.0);
        sgdNoDecayStepSize = parser.accepts("noDecayStepSize",
            "Don't use a 1/sqrt(t) step size decay during stochastic gradient descent.");
        sgdNoReturnAveragedParameters = parser.accepts("noReturnAveragedParameters", 
            "Get the average of the parameter iterates of stochastic gradient descent.");
        sgdL2Regularization = parser.accepts("l2Regularization",
            "Regularization parameter for the L2 norm of the parameter vector.")
            .withRequiredArg().ofType(Double.class).defaultsTo(0.0);
        sgdRegularizationFrequency = parser.accepts("regularizationFrequency",
            "Fraction of iterations on which to apply regularization. Must be between 0 and 1")
            .withRequiredArg().ofType(Double.class).defaultsTo(1.0);
        sgdClipGradients = parser.accepts("clipGradients", "Clip gradients to a max l2 norm of the given value.")
            .withRequiredArg().ofType(Double.class).defaultsTo(Double.MAX_VALUE);
        sgdAdagrad = parser.accepts("adagrad", "Use the adagrad algorithm for stochastic gradient descent.");
      }
  
      if (opts.contains(CommonOptions.LBFGS)) {
        lbfgs = parser.accepts("lbfgs");
        lbfgsIterations = parser.accepts("lbfgsIterations",
            "Maximum number of iterations (passes over the data) for LBFGS.").
            withRequiredArg().ofType(Integer.class).defaultsTo(100);
        lbfgsHessianRank = parser.accepts("lbfgsHessianRank",
            "Rank (number of vectors) of LBFGS's inverse Hessian approximation.")
            .withRequiredArg().ofType(Integer.class).defaultsTo(30);
        lbfgsL2Regularization = parser.accepts("lbfgsL2Regularization",
            "L2 regularization imposed by LBFGS")
            .withRequiredArg().ofType(Double.class).defaultsTo(0.0);
  
        // Providing either of these options triggers the use of minibatch LBFGS
        lbfgsMinibatchIterations = parser.accepts("lbfgsMinibatchIterations",
            "If specified, run LBFGS on minibatches of the data with the specified number of iterations per minibatch.")
            .withRequiredArg().ofType(Integer.class).defaultsTo(-1);
        lbfgsMinibatchSize = parser.accepts("lbfgsMinibatchSize",
            "If specified, run LBFGS on minibatches of the data with the specified number of examples per minibatch.")
            .withRequiredArg().ofType(Integer.class).defaultsTo(-1);
  
        lbfgsAdaptiveMinibatches = parser.accepts("lbfgsAdaptiveMinibatches",
            "If given, LBFGS is run on minibatches of exponentially increasing size.");
      }
  
      if (opts.contains(CommonOptions.STOCHASTIC_GRADIENT) || opts.contains(CommonOptions.LBFGS)) {
        logInterval = parser.accepts("logInterval",
            "Number of training iterations between logging outputs.")
            .withRequiredArg().ofType(Integer.class).defaultsTo(1);
        
        logParametersInterval = parser.accepts("logParametersInterval",
            "Number of training iterations between serializing parameters to disk during training. "
            + "If unspecified, model parameters are not serialized to disk during training.")
            .withRequiredArg().ofType(Integer.class).defaultsTo(-1);
        logParametersDir = parser.accepts("logParametersDir", "Directory where serialized model "
            + "parameters are stored. Must be specified if logParametersInterval is specified.")
            .withRequiredArg().ofType(String.class);
  
        logBrief = parser.accepts("logBrief", "Hides training output.");
      }
  
      if (opts.contains(CommonOptions.MAP_REDUCE)) {
        mrMaxThreads = parser.accepts("maxThreads",
            "Maximum number of threads to use during parallel execution.")
            .withRequiredArg().ofType(Integer.class).defaultsTo(Runtime.getRuntime().availableProcessors());
        mrMaxBatchesPerThread = parser.accepts("maxBatchesPerThread",
            "Number of batches of items to create per thread.")
            .withRequiredArg().ofType(Integer.class).defaultsTo(20);
      }
  
      if (opts.contains(CommonOptions.FUNCTIONAL_GRADIENT_ASCENT)) {
        fgaIterations = parser.accepts("fgaIterations",
            "Number of iterations of functional gradient ascent to perform.").withRequiredArg()
            .ofType(Integer.class).defaultsTo(10);
        fgaBatchSize = parser.accepts("fgaBatchSize",
            "Number of examples to process before each functional gradient update. If not provided, use the entire data set.")
            .withRequiredArg().ofType(Integer.class);
        fgaInitialStep = parser.accepts("fgaInitialStepSize",
            "Initial step size for functional gradient ascent.")
            .withRequiredArg().ofType(Double.class).defaultsTo(1.0);
        fgaNoDecayStepSize = parser.accepts("fgaNoDecayStepSize",
            "Don't use a 1/sqrt(t) step size decay during functional gradient ascent.");
      }
  
      if (opts.contains(CommonOptions.REGRESSION_TREE)) {
        rtreeMaxDepth = parser.accepts("rtreeMaxDepth", "Maximum depth of trained regression trees")
            .withRequiredArg().ofType(Integer.class).required();
      }
    }