Home > other >  How to identify the index that corresponds to a particular ordering of N boolean values in an array?
How to identify the index that corresponds to a particular ordering of N boolean values in an array?

Time:11-30

Suppose I perform n=3 coin-flips, for which each sub_state=True if the flip returns tails (T) or sub_state=False if the flip returns heads (H). Then, there are 2 ** 3 = 8 possible states since each sub_state can only take on 2 values (True or False) and there are 3 coin-flip trials.

The 8 states enumerated arbitrarily are:

  1. T-T-T
  2. H-T-T
  3. T-H-T
  4. T-T-H
  5. H-H-T
  6. H-T-H
  7. T-H-H
  8. H-H-H

Knowing the particular series of coin-flip trials (ie, H-T-T) reveals which state is currently occupied.

I would like to write a function; this function takes sub_states as input, where sub_states is a boolean array of size n (ie, [False, True, True] corresponding to H-T-T), and returns as output the corresponding index (ie, 2 - 1 = 1).

I am not sure how to approach this problem. I think there may be way to do this using binary numbers 01 that correspond to each of the 2**n states, or maybe a simpler way with numpy magic and itertools. What are some approaches or methods I can use to solve this problem?

import numpy as np

def get_state_index(sub_states):
    """
    Suppose sub_states is a list of
    boolean values of length 3. Then,
    there are 2 ** 3 = 8 possible states.

    sub_states = [False, True, True]
    ==> state_index = 1

        state 0:
            coin-flips: T-T-T
            sub-states: [True, True, True]

        state 1:
            coin-flips: H-T-T
            sub-states: [False, True, True]

        state 2:
            coin-flips: T-H-T
            sub-states: [True, False, True]

        state 3:
            coin-flips: T-T-H
            sub-states: [True, True, False]

        state 4:
            coin-flips: H-H-T
            sub-states: [False, False, True]

        state 5:
            coin-flips: H-T-H
            sub-states: [False, True, False]

        state 6:
            coin-flips: T-H-H
            sub-states: [True, False, False]

        state 7:
            coin-flips: H-H-H
            sub-states: [False, False, False]
    """
    raise ValueError("not yet implemented")
    state_index = ...
    return state_index

if __name__ == '__main__':

    ## initialize sub-states
    sub_states = np.full(
        3,
        False,
        dtype=bool)
    sub_states[1] = True
    sub_states[2] = True

    ## initialize states
    states = np.full(
        2 ** sub_states.size, # len([True, False]) == 2
        False,
        dtype=bool)
    ##
    # i = get_state_index(sub_states)
    ##
    states[i] = True
    print(states)

CodePudding user response:

With a little less arbitrary ordering:

state_index = sum(state * 2 ** pos for pos, state in enumerate(sub_states))

every False counts as a zero, every True as a one. Multiply them with their positional values in binary representation, and sum the result, effectively interpreting them as a binary number (though with least-significant-bit-first). For example, [False, False, True] is 0*1 0*2 1*4, equivalent to 0b100. You could also get the same result by converting each element into a string 0 or 1, smushing them together and then interpreting them as a binary:

state_index = int(''.join(str(int(state)) for state in reversed(sub_states)), 2)

(reversed is there just to get the same result as above, with LSB-first. If you prefer MSB-first, remove reversed from this snippet, or add it into the previous one.)

  • Related