# process 1def val(c): return 1 + ord(c) - 'a'def process(addx, addy):    s = 0    ndraws = 10    for _ in range(ndraws):        x = random.choice("abcde"),  # draw a random chit        y = random.choice(x*5+"abcde") # draw a random chit, dependent on first random chit.        if addx: s += val(x)        if addy: x += val(y)    return s

§ Linearity of expectation is purity

Suppose we write:

x = random.choice("abcde")y = random.choice("abcde")s =  val(x) + val(y)
E[s] = E[val(x) + val(y)]= E[val(x)] + E[val(y)]= 2 E[val(x)]

§ "Deriving" equivalence for two processses using purity

def rhsI():    sx = 0; sy = 0    ndraws = 10    for _ in range(ndraws):        x = random.choice("abcde"),  # draw a random chit        y = random.choice(x1*5+"abcde") # draw a random chit, dependent on first random chit.        sx += val(x)    for _ in range(ndraws):        x = random.choice("abcde"),  # draw a random chit        y = random.choice(x2*5+"abcde") # draw a random chit, dependent on first random chit.        sy += val(y)    return sx + sy
def rhsII():    sx = 0; sy = 0    ndraws = 10    # loop fusion is safe, because even though random.choice has a side effect, the order    # of calling random.choice does not matter. It commutes with other random ops.    for _ in range(ndraws):        x1 = random.choice("abcde"),  # draw a random chit        y1 = random.choice(x1*5+"abcde") # draw a random chit, dependent on first random chit.        sx += val(x1)        # loop fusion        x2 = random.choice("abcde"),  # draw a random chit        y2 = random.choice(x2*5+"abcde") # draw a random chit, dependent on first random chit.        sy += val(y2)    return sx + sy
def rhsIII():    sx = 0; sy = 0    ndraws = 10    # once again, expectation purifies randomness. So within the context of expecattion, we can    # replace `x2` with `x1` with `x1`    for _ in range(ndraws):        x1 = random.choice("abcde"),  # draw a random chit        y1 = random.choice(x1*5+"abcde") # draw a random chit, dependent on first random chit.        sx += val(x1)        # loop fusion        x2 = x1        y2 = y1        sy += val(y2)    return sx + sy
def rhsIV():    sx = 0; sy = 0    ndraws = 10    # once again, expectation purifies randomness. So within the context of expecattion, we can    # replace `x2` with `x1` with `x1`    for _ in range(ndraws):        x1 = random.choice("abcde"),  # draw a random chit        y1 = random.choice(x1*5+"abcde") # draw a random chit, dependent on first random chit.        sx += val(x1)        sy += val(y1)    return sx + sy

§ For N=1N=1, the expected number of turns is 11.