google / tangent

Source-to-Source Debuggable Derivatives in Pure Python
Apache License 2.0
2.32k stars 434 forks source link

NameError: name 'bi' is not defined #69

Open jameshensman opened 6 years ago

jameshensman commented 6 years ago

The code that tangent writes tries to use an undefined variable

To replicate:

def foo(d, n):
    S = np.zeros((n, n))
    for i in range(n):
        S[i, 2] = 1.
        if i==2:
            S[i, i] += d[i]
    return S

g = tangent.grad(foo)

Using tangent's verbose setting, the code generated is:

def dfoodd(d, n, bS=1.0):
    # Initialize the tape
    _stack = tangent.Stack()
    d_i = None
    t2 = None
    t = n, n
    S = np.zeros(t)
    i2 = 0
    for i in range(n):
        _i = i
        i2 += 1
        tangent.push(_stack, t2, '_f906a3c2')
        t2 = i, 2
        tangent.push(_stack, S[t2], '_40e2ac70')
        S[t2] = 1.0
        cond = i == 2
        if cond:
            tangent.push(_stack, d_i, '_c9e01b45')
            d_i = bi
            t3 = i, i
            S_t = S[t3]
            tangent.push(_stack, S[t3], '_e70dae8e')
            S[t3] = S_t + d_i
            tangent.push(_stack, t3, '_e61bf5ac')
        tangent.push(_stack, cond, '_60e612f2')
        tangent.push(_stack, _i, '_eae234b4')
    tangent.push(_stack, i2, '_f52e32af')
    bd = tangent.init_grad(d)
    bd_i = tangent.init_grad(d_i)
    assert tangent.shapes_match(S, bS
        ), 'Shape mismatch between return value (%s) and seed derivative (%s)' % (
        numpy.shape(S), numpy.shape(bS))

    # Beginning of backward pass
    i2 = tangent.pop(_stack, '_f52e32af')
    for _ in range(i2):
        i = tangent.pop(_stack, '_eae234b4')
        cond = tangent.pop(_stack, '_60e612f2')
        if cond:
            # Grad of: S[t3] = S_t + d_i
            t3 = tangent.pop(_stack, '_e61bf5ac')
            _S = S[t3]
            S[t3] = tangent.pop(_stack, '_e70dae8e')
            _bd_i = tangent.unbroadcast(bS[t3], d_i)
            bS[t3] = tangent.init_grad(S[t3], allow_lazy_initializer=True)
            bd_i = tangent.add_grad(bd_i, _bd_i)

            # Grad of: t2 = i, 2
            _d_i = d_i
            d_i = tangent.pop(_stack, '_c9e01b45')
            _bd = bd_i
            bd_i = tangent.init_grad(d_i, allow_lazy_initializer=True)
            bd[i] = tangent.add_grad(bd[i], _bd)
        S[t2] = tangent.pop(_stack, '_40e2ac70')
        bS[t2] = tangent.init_grad(S[t2], allow_lazy_initializer=True)
        t2 = tangent.pop(_stack, '_f906a3c2')
    return bd
jameshensman commented 6 years ago

Actually, it seems to be even simpler than that. here's an imprved MWE:

def foo(d, i):
    return d[i]

raises same exception!

alexbw commented 6 years ago

Nice, thanks for the extremely succinct reproducing case! I’ll take a look at it and try to get a fix ASAP

On Thu, Mar 22, 2018 at 11:01 AM James Hensman notifications@github.com wrote:

Actually, it seems to be even simpler than that. here's an imprved MWE:

def foo(d, i): return d[i]

raises same exception!

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/google/tangent/issues/69#issuecomment-375403028, or mute the thread https://github.com/notifications/unsubscribe-auth/AAJ4j5c5Bog6Go1pR1_MYZlq0VcebDz4ks5tg-cWgaJpZM4S3hte .