def state2bin(s, num_bins, limits):
    """
    :param s: a state.  (possibly multidimensional) ndarray, with dimension d =
        dimensionality of state space.
    :param num_bins: the total number of bins in the discretization
    :param limits: 2 x d ndarray, where row[0] is a row vector of the lower
        limit of each discrete dimension, and row[1] are corresponding upper
        limits.
    Returns the bin number (index) corresponding to state s given a
    discretization num_bins between each column of limits[0] and limits[1].
    The return value has same dimensionality as ``s``. \n
    Note that ``s`` may be continuous. \n
    \n
    Examples: \n
    s = 0, limits = [-1,5], num_bins = 6 => 1 \n
    s = .001, limits = [-1,5], num_bins = 6 => 1 \n
    s = .4, limits = [-.5,.5], num_bins = 3 => 2 \n

    """

    if s == limits[1]:
        return num_bins - 1
    width = limits[1] - limits[0]
    if s > limits[1]:
        print(
            "Tools.py: WARNING: ", s, " > ", limits[1], ". Using the chopped value of s"
        )
        print("Ignoring", limits[1] - s)
        s = limits[1]
    elif s < limits[0]:
        print(
            "Tools.py: WARNING: ", s, " < ", limits[0], ". Using the chopped value of s"
        )
        s = limits[0]
    return int((s - limits[0]) * num_bins / (width * 1.0))