Guaranteed convergence velocity update.

    Args:
        particle: cipy.algorithms.pso.Particle: Particle to update the velocity
            for.
        social: cipy.algorithms.pso.Particle: The social best for the particle.
        state: cipy.algorithms.pso.State: The state of the PSO algorithm.

    Returns:
        numpy.ndarray: the calculated velocity.

def gc_velocity_update(particle, social, state):
    """ Guaranteed convergence velocity update.

    Args:
        particle: cipy.algorithms.pso.Particle: Particle to update the velocity
            for.
        social: cipy.algorithms.pso.Particle: The social best for the particle.
        state: cipy.algorithms.pso.State: The state of the PSO algorithm.

    Returns:
        numpy.ndarray: the calculated velocity.
    """
    gbest = state.swarm[gbest_idx(state.swarm)].position
    if not np.array_equal(gbest, particle.position):
        return std_velocity(particle, social, state)

    rho = state.params['rho']
    inertia = state.params['inertia']
    v_max = state.params['v_max']
    size = particle.position.size

    r2 = state.rng.uniform(0.0, 1.0, size)
    velocity = __gc_velocity_equation__(inertia, rho, r2, particle, gbest)
    return __clamp__(velocity, v_max)