Section 18.1 says that automatic differentiation is exact for the code that ran, not for the function the programmer meant, and that at a corner the code still returns a number. Section 18.4 adds a second failure: a stored value that changes after it was saved makes the gradient wrong with no error and no warning. The field has no settled convention for what a differentiating system should report when the code has a local slope but the mathematical function has no derivative. Candidates include the slope of the branch that ran, a fixed value such as 0, a NaN, and an error that stops the run.
Take a position on this question: what should a library return at such a point, and how should a user detect a gradient that is silently wrong?
In your answer: name at least two candidate conventions and the case that separates them; propose a test that would expose a mismatch between the code and the function; say what pattern of results would change your mind; state one confound; and connect your proposal to the chapter's two claims, that the derivative is exact for the code and that a recomputed block must repeat its first run.
Rubric. Tick each criterion your answer meets, then save the self-assessment. The platform does not grade it.
Worked solution
There is no single correct answer, so this is a model of the shape a complete answer takes, not a key. A level-3 answer starts from a concrete program. Take at , written first as max(x, -x) and second as sqrt(x*x). The first program has a local slope on each branch: one branch returns 1 and the other returns , and the tie rule decides which one the run reports. The second program forms , then , whose local slope is infinite; the backward multiplication gives NaN. The two programs compute the same function and report different things at the same point. That is the case that separates the conventions.
The answer then states its position. One defensible position is: return the slope of the branch that ran, but mark the result as a convention and offer a mode that raises at a detected corner. The argument for the first part is that training often wants a usable number and a branch is a real instruction; the argument for the second is that a silent convention can hide a modelling mistake. A second position is: return NaN whenever the local slope is not finite, because a NaN propagates and is visible; the cost is that a single corner can destroy a whole batch. A third is: require the user to register a derivative for the operation, so the choice is explicit. The answer names which case distinguishes the positions, and says that the square-root program distinguishes the second from the first.
The test follows. Run the program twice: once with the ordinary trace, and once with a fresh trace built from the same inputs. If the two gradients differ, the cause is a stale stored value rather than a corner convention, and section 18.4's warning applies. If they agree, compare the result with a centred difference at the step from section 18.1. Agreement to the digits that step can reach supports the report; disagreement points to a bug. Then change only the corner case, leaving every other input fixed, and see whether the report changes in the way the convention predicts. A pattern that would refute the preferred convention is a case where the branch slope and the finite difference disagree away from the corner; that would mean the trace recorded an operation that did not run, not merely a convention at a point.
The confound is the tie rule inside max, or the finite-difference step itself. A maximum of two equal values has no distinguished branch, so the reported slope can change when the argument order changes, and that change says nothing about the mathematics. The finite difference has its own best step, and below it the subtraction noise dominates, so a disagreement at a very small step is not evidence about the corner. The answer says how it controls both: keep the argument order fixed, and use the step derived in E2.3 rather than an arbitrary one.
Finally, the answer costs the test. Each run is one forward and one backward pass, so the double-trace check doubles the training cost if it runs at every step; a cheaper design runs it on a fixed schedule or on a small set of coordinates. The answer says how many runs it needs before it can separate the two causes, and what the library should do when neither the trace nor the finite difference can decide: report that the point is undecided rather than return a number that looks ordinary.