testGradientIncidental :: Test
testGradientIncidental = testCase "testGradientIncidental" $ do
    let grads = do
            x <- TF.render $ TF.scalar (3 :: Float)
            b <- TF.render $ TF.scalar (4 :: Float)
            w <- TF.render $ TF.diag $ TF.vector [ 1.0 :: Float ]
            let incidental = b `TF.mul` w
            let y = (x `TF.mul` b) `TF.add` incidental
            TF.gradients y [x]

    -- Assert that the gradients are right.
    [dx] <- TF.runSession $ grads >>= TF.run
    4 @=? TF.unScalar dx
    -- Assert that the graph has the expected ops.
    let graphDef = TF.asGraphDef grads
    putStrLn $ showMessage graphDef
    let ops = graphDef ^.. node . traverse . op
        expected = [ "Add"
                   , "BroadcastGradientArgs"
                   , "BroadcastGradientArgs"
                   , "Const"
                   , "Const"
                   , "Const"
                   , "Const"
                   , "Diag"
                   , "Fill"
                   , "Mul"
                   , "Mul"
                   , "Mul"
                   , "Mul"
                   , "Reshape"
                   , "Reshape"
                   , "Reshape"
                   , "Reshape"
                   , "Shape"
                   , "Shape"
                   , "Shape"
                   , "Shape"
                   , "Shape"
                   , "Sum"
                   , "Sum"
                   , "Sum"
                   , "Sum"
                   ]
    sort expected @=? sort ops
testGradientIncidental :: Test
testGradientIncidental = testCase "testGradientIncidental" $ do
    let grads = do
            x <- TF.render $ TF.scalar (3 :: Float)
            b <- TF.render $ TF.scalar (4 :: Float)
            w <- TF.render $ TF.diag $ TF.vector [ 1.0 :: Float ]
            let incidental = b `TF.mul` w
            let y = (x `TF.mul` b) `TF.add` incidental
            TF.gradients y [x]

    -- Assert that the gradients are right.
    [dx] <- TF.runSession $ grads >>= TF.run
    4 @=? TF.unScalar dx
    -- Assert that the graph has the expected ops.
    let graphDef = TF.asGraphDef grads
    putStrLn $ showMessage graphDef
    let ops = graphDef ^.. node . traverse . op
        expected = [ "Add"
                   , "BroadcastGradientArgs"
                   , "BroadcastGradientArgs"
                   , "Const"
                   , "Const"
                   , "Const"
                   , "Const"
                   , "Diag"
                   , "Fill"
                   , "Mul"
                   , "Mul"
                   , "Mul"
                   , "Mul"
                   , "Reshape"
                   , "Reshape"
                   , "Reshape"
                   , "Reshape"
                   , "Shape"
                   , "Shape"
                   , "Shape"
                   , "Shape"
                   , "Shape"
                   , "Sum"
                   , "Sum"
                   , "Sum"
                   , "Sum"
                   ]
    sort expected @=? sort ops
testGradientIncidental = testCase "testGradientIncidental" $ do
    let grads = do
            x <- TF.render $ TF.scalar (3 :: Float)
            b <- TF.render $ TF.scalar (4 :: Float)
            w <- TF.render $ TF.diag $ TF.vector [ 1.0 :: Float ]
            let incidental = b `TF.mul` w
            let y = (x `TF.mul` b) `TF.add` incidental
            TF.gradients y [x]

    -- Assert that the gradients are right.
    [dx] <- TF.runSession $ grads >>= TF.run
    4 @=? TF.unScalar dx
    -- Assert that the graph has the expected ops.
    let graphDef = TF.asGraphDef grads
    putStrLn $ showMessage graphDef
    let ops = graphDef ^.. node . traverse . op
        expected = [ "Add"
                   , "BroadcastGradientArgs"
                   , "BroadcastGradientArgs"
                   , "Const"
                   , "Const"
                   , "Const"
                   , "Const"
                   , "Diag"
                   , "Fill"
                   , "Mul"
                   , "Mul"
                   , "Mul"
                   , "Mul"
                   , "Reshape"
                   , "Reshape"
                   , "Reshape"
                   , "Reshape"
                   , "Shape"
                   , "Shape"
                   , "Shape"
                   , "Shape"
                   , "Shape"
                   , "Sum"
                   , "Sum"
                   , "Sum"
                   , "Sum"
                   ]
    sort expected @=? sort ops