input: Write a python function to optimize a function with a given dimension using gradient descent.
  assert len(optimize(lambda x: sum(xi**2 for xi in x), 2)) == 2
  assert len(optimize(lambda x: sum(xi**2 for xi in x), 3)) == 3
  assert len(optimize(lambda x: sum(xi**2 for xi in x), 5)) == 5
output: def optimize(func, dim, learning_rate=0.01, tolerance=1e-6, max_iter=10000):
      import numpy as np
  
      # Initialize a random starting point
      x = np.random.randn(dim)
  
      for _ in range(max_iter):
          # Compute the gradient
          grad = np.zeros(dim)
          for i in range(dim):
              x[i] += tolerance
              f_plus = func(x)
              x[i] -= 2 * tolerance
              f_minus = func(x)
              grad[i] = (f_plus - f_minus) / (2 * tolerance)
              x[i] += tolerance
  
          # Update the point
          x = x - learning_rate * grad
  
          # Check for convergence
          if np.linalg.norm(grad) < tolerance:
              break
  
      return x.tolist()