code: def generate_calculus_integrate_sample(vlist, ops, min_depth, max_depth,
                                         functions):
    
    var_index = random.randrange(len(vlist))
    var = vlist[var_index]
    consts = vlist[:var_index] + vlist[var_index + 1:]
  
    depth = random.randrange(min_depth, max_depth + 1)
    expr = random_expr_with_required_var(depth, var, consts, ops)
  
    expr_str = str(expr)
    sample = var + ":" + expr_str
    target = format_sympy_expr(
        sympy.integrate(expr_str, sympy.Symbol(var)), functions=functions)
    return sample, target
docs: Randomly generate a symbolic integral dataset sample.
  
    Given an input expression, produce the indefinite integral.
  
    Args:
      vlist: Variable list. List of chars that can be used in the expression.
      ops: List of ExprOp instances. The allowed operators for the expression.
      min_depth: Expression trees will not have a smaller depth than this. 0 means
          there is just a variable. 1 means there is one operation.
      max_depth: Expression trees will not have a larger depth than this. To make
          all trees have the same depth, set this equal to `min_depth`.
      functions: Defines special functions. A dict mapping human readable string
          names, like "log", "exp", "sin", "cos", etc., to single chars. Each
          function gets a unique token, like "L" for "log".
  
    Returns:
      sample: String representation of the input. Will be of the form
          'var:expression'.
      target: String representation of the solution.