input: Write a python function to optimize a cost function using Particle Swarm Optimization (PSO).
  assert isinstance(pso_optimize(lambda x: -sum(xi**2 for xi in x), 5, 10, [-10, -10], [10, 10]), tuple)
  assert len(pso_optimize(lambda x: -sum(xi**2 for xi in x), 5, 10, [-10, -10], [10, 10])) == 2
  assert isinstance(pso_optimize(lambda x: -sum(xi**2 for xi in x), 5, 10, [-10, -10], [10, 10])[0], list)
  assert isinstance(pso_optimize(lambda x: -sum(xi**2 for xi in x), 5, 10, [-10, -10], [10, 10])[1], (int, float))
output: def pso_optimize(cost_func, num_particles, num_iterations, bounds_min, bounds_max):
      import random
  
      # Initialize particle positions and velocities
      particles = [
          [random.uniform(bounds_min[i], bounds_max[i]) for i in range(len(bounds_min))]
          for _ in range(num_particles)
      ]
      velocities = [
          [random.uniform(-1, 1) for _ in range(len(bounds_min))] for _ in range(num_particles)
      ]
  
      # Initialize personal best positions and global best position
      p_best_positions = particles[:]
      p_best_scores = [cost_func(p) for p in particles]
      g_best_position = p_best_positions[p_best_scores.index(max(p_best_scores))]
      g_best_score = max(p_best_scores)
  
      # PSO parameters
      w = 0.5  # inertia weight
      c1 = 1.5  # cognitive (particle) weight
      c2 = 1.5  # social (swarm) weight
  
      for _ in range(num_iterations):
          for i in range(num_particles):
              for j in range(len(particles[i])):
                  r1 = random.random()
                  r2 = random.random()
  
                  # Update velocity
                  velocities[i][j] = (
                      w * velocities[i][j]
                      + c1 * r1 * (p_best_positions[i][j] - particles[i][j])
                      + c2 * r2 * (g_best_position[j] - particles[i][j])
                  )
                  # Update position
                  particles[i][j] += velocities[i][j]
  
                  # Ensure particles stay within bounds
                  particles[i][j] = max(bounds_min[j], min(particles[i][j], bounds_max[j]))
  
              # Update personal best
              score = cost_func(particles[i])
              if score > p_best_scores[i]:
                  p_best_positions[i] = particles[i][:]
                  p_best_scores[i] = score
  
                  # Update global best
                  if score > g_best_score:
                      g_best_position = particles[i][:]
                      g_best_score = score
  
      return g_best_position, g_best_score