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:
- T-T-T
- H-T-T
- T-H-T
- T-T-H
- H-H-T
- H-T-H
- T-H-H
- 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.)