The Elements of Differentiable Programming

Chapter 5Control flows

Control flows, such as conditionals or loops, are an essential part of computer programming, as they allow us to express complex programs. It is therefore natural to ask whether these constructs can be included in a differentiable program. This is what we study in this chapter.

5.1 Comparison operators

Control flows rely on comparison operators, a.k.a. relational operators. Formally, we can define a comparison operator π=op(u1,u2)\pi = \mathrm{op}(u_1, u_2) as a function from u1∈Ru_1 \in \RR and u2∈Ru_2 \in \RR to π∈{0,1}\pi \in \{0,1\}. The binary (Boolean) output π\pi can then be used within a conditional statement (see Section 5.6, Section 5.7) to decide whether to execute one branch or another. We define the following operators, illustrated in Fig. 5.1:

where step ⁣:R→{0,1}\mathrm{step} \colon \RR \to \{0,1\} is the Heaviside step function step(u)≔{1 if u≥00 otherwise. \mathrm{step}(u) \coloneqq \begin{cases} 1 &\mbox{ if } u \ge 0 \\ 0 &\mbox{ otherwise} \end{cases}. The Heaviside step function is piecewise constant. At u=0u=0, the function is discontinuous. At u≠0u \neq 0, it is continuous and has null derivative. Since the comparison operators we presented are all expressed in terms of the step\mathrm{step} function, they are all continuous and differentiable almost everywhere, with null derivative. Therefore, while their derivatives are well-defined almost everywhere, they are uninformative and prevent gradient backpropagation.

Figure 5.1: The greater than and equal to operators are discontinuous functions, leading to black or white pictures. They can be smoothed with appropriate approximations of the Heaviside step function.

5.2 Soft inequality operators

5.2.1 Heuristic definition

To obtain a continuous relaxation of inequality operators, we can heuristically replace the step function in the expression of “greater than” and “less than” by a sigmoid function sigmoidσ\mathrm{sigmoid}_\sigma, where σ>0\sigma > 0 is a scaling parameter. Such a sigmoid function should satisfy the following properties:

Two examples of sigmoids satisfying the aforementioned properties are the logistic function (the CDF of the standard logistic distribution) sigmoidσ(u)≔logisticσ(u)≔11+e−u/σ∈(0,1) \mathrm{sigmoid}_\sigma(u) \coloneqq \logistic_\sigma(u) \coloneqq \frac{1}{1+ e^{-u/\sigma}} \in (0, 1) and the standard Gaussian’s CDF, defined in Eq. (3.1), sigmoidσ(u)≔Φ(u/σ). \mathrm{sigmoid}_\sigma(u) \coloneqq \Phi(u/\sigma). We may then define the soft “greater than” gt(μ1,μ2)=step(μ1−μ2)≈sigmoidσ(μ1−μ2)≕gtσ(μ1,μ2)\begin{align*} \mathrm{gt}(\mu_1, \mu_2) &= \mathrm{step}(\mu_1 - \mu_2) \\ &\approx \sigmoid_\sigma(\mu_1 - \mu_2) \\ &\eqqcolon \mathrm{gt}_\sigma(\mu_1, \mu_2) \end{align*} and the soft “less than” lt(μ1,μ2)=step(μ2−μ1)≈sigmoidσ(μ2−μ1)≕ltσ(μ1,μ2)=1−sigmoidσ(μ1−μ2)=1−gtσ(μ1,μ2).\begin{align*} \mathrm{lt}(\mu_1, \mu_2) &= \mathrm{step}(\mu_2-\mu_1) \\ &\approx \sigmoid_\sigma(\mu_2 - \mu_1) \\ &\eqqcolon \mathrm{lt}_\sigma(\mu_1, \mu_2) \\ &= 1 - \sigmoid_\sigma(\mu_1 - \mu_2) \\ &= 1 - \mathrm{gt}_\sigma(\mu_1, \mu_2). \end{align*} In the limit, we have that sigmoidσ(μ1−μ2)→1\sigmoid_\sigma(\mu_1 - \mu_2) \to 1 when μ1−μ2→∞\mu_1 - \mu_2 \to \infty. In the limit, sigmoidσ\sigmoid_\sigma therefore outputs a value of 11 if μ1\mu_1 and μ2\mu_2 are infinitely apart. Besides the logistic function and the standard Gaussian’s CDF, other sigmoid functions are possible, as discussed in Section 13.6. In particular, with sparse sigmoids, there exists a finite value τ\tau such that μ1−μ2≥τ⟹sigmoidσ(μ1−μ2)=1\mu_1 - \mu_2 \ge \tau \Longrightarrow \sigmoid_\sigma(\mu_1 - \mu_2) = 1.

5.2.2 Stochastic process perspective

When the sigmoid used to replace the step function is the logistic function or the standard Gaussian’s CDF, we can revisit the previous heuristic definition of gtσ(μ1,μ2)\mathrm{gt}_\sigma(\mu_1,\mu_2) and ltσ(μ1,μ2)\mathrm{lt}_\sigma(\mu_1,\mu_2) from a more formal perspective. Indeed, to real values μ1∈R\mu_1 \in \RR and μ2∈R\mu_2 \in \RR, we can associate random variables U1∼pμ1,σ1andU2∼pμ2,σ2, U_1 \sim p_{\mu_1,\sigma_1} \quad \text{and} \quad U_2 \sim p_{\mu_2,\sigma_2}, thereby forming a stochastic process (we assume that σ1\sigma_1 and σ2\sigma_2 are fixed). Alternatively, we can also write (U1,U2)∼pμ1,σ1⊗pμ2,σ2, (U_1, U_2)\sim p_{\mu_1,\sigma_1}\otimes p_{\mu_2,\sigma_2}, where for two distributions p1p_1 and p2p_2, we denote by p1⊗p2p_1 \otimes p_2 their outer product (p1⊗p2)(u1,u2)≔p1(u1)p2(u2)(p_1 \otimes p_2)(u_1, u_2) \coloneqq p_1(u_1)p_2(u_2). We can then define gtσ(μ1,μ2)=E[gt(U1,U2)]=E[step(U1−U2)]=P(U1−U2≥0)=P(U2−U1≤0)=FU2−U1(0),\begin{align*} \mathrm{gt}_\sigma(\mu_1, \mu_2) &= \EE\left[\mathrm{gt}(U_1, U_2)\right] \\ &= \EE\left[\mathrm{step}(U_1 - U_2)\right] \\ &= \PP(U_1 - U_2 \ge 0) \\ &= \PP(U_2 - U_1 \le 0) \\ &= F_{U_2 - U_1}(0), \end{align*} where FXF_X is the cumulative distribution function (CDF) of the random variable XX, and σ\sigma is a function of σ1\sigma_1 and σ2\sigma_2. Similarly, we obtain ltσ(μ1,μ2)=E[lt(U1,U2)]=E[step(U2−U1)]=P(U1−U2≤0)=FU1−U2(0).\begin{align*} \mathrm{lt}_\sigma(\mu_1, \mu_2) &= \EE\left[\mathrm{lt}(U_1, U_2)\right] \\ &= \EE\left[\mathrm{step}(U_2 - U_1)\right] \\ &= \PP(U_1 - U_2 \le 0) \\ &= F_{U_1 - U_2}(0). \end{align*} We see that the soft inequality operators are based on the CDF of the difference between U1U_1 and U2U_2.

For location-scale family distributions (Section 12.4.1), from a perturbation perspective, we can also define noise variables Z1∼p0,1Z_1 \sim p_{0,1} and Z2∼p0,1Z_2 \sim p_{0,1} such that U1=μ1+σ1Z1U_1 = \mu_1 + \sigma_1 Z_1 and U2=μ2+σ2Z2U_2 = \mu_2 + \sigma_2 Z_2 (Section 12.4.1). We then have gtσ(μ1,μ2)=E[gt(μ1+σ1Z1,μ2+σ2Z2)]ltσ(μ1,μ2)=E[lt(μ1+σ1Z1,μ2+σ2Z2)].\begin{align*} \mathrm{gt}_\sigma(\mu_1, \mu_2) &= \EE \left[\mathrm{gt}(\mu_1 + \sigma_1 Z_1, \mu_2 + \sigma_2 Z_2)\right] \\ \mathrm{lt}_\sigma(\mu_1, \mu_2) &= \EE \left[\mathrm{lt}(\mu_1 + \sigma_1 Z_1, \mu_2 + \sigma_2 Z_2)\right]. \end{align*}

Gaussian case

When U1∼Normal(μ1,σ12)U_1 \sim \mathrm{Normal}(\mu_1, \sigma_1^2) and U2∼Normal(μ2,σ22)U_2 \sim \mathrm{Normal}(\mu_2, \sigma_2^2), we have U1−U2∼Normal(μ1−μ2,σ12+σ22).(5.1) U_1 - U_2 \sim \mathrm{Normal}(\mu_1 - \mu_2, \sigma_1^2 + \sigma_2^2). \tag{5.1} Denoting Φ\Phi the standard Gaussian’s CDF, we then obtain gtσ(μ1,μ2)=FU2−U1(0)=Φ(0−(μ2−μ1)σ)=Φ(μ1−μ2σ)ltσ(μ1,μ2)=FU1−U2(0)=Φ(0−(μ1−μ2)σ)=Φ(μ2−μ1σ),\begin{align*} \mathrm{gt}_\sigma(\mu_1, \mu_2) &= F_{U_2 - U_1}(0) \\ &= \Phi\left(\frac{0 - (\mu_2 - \mu_1)}{\sigma}\right) \\ &= \Phi\left(\frac{\mu_1-\mu_2}{\sigma}\right) \\ \mathrm{lt}_\sigma(\mu_1, \mu_2) &= F_{U_1 - U_2}(0) \\ &= \Phi\left(\frac{0 - (\mu_1 - \mu_2)}{\sigma}\right) \\ &= \Phi\left(\frac{\mu_2-\mu_1}{\sigma}\right), \end{align*} where σ≔σ12+σ22\sigma \coloneqq \sqrt{\sigma_1^2 + \sigma_2^2}. The corresponding distribution for Z1Z_1 and Z2Z_2 is Gaussian noise.

Logistic case

When U1∼Gumbel(μ1,σ)U_1 \sim \mathrm{Gumbel}(\mu_1, \sigma) and U2∼Gumbel(μ2,σ)U_2 \sim \mathrm{Gumbel}(\mu_2, \sigma), we have U1−U2∼Logistic(μ1−μ2,σ).(5.2) U_1 - U_2 \sim \mathrm{Logistic}(\mu_1 - \mu_2, \sigma). \tag{5.2} We then obtain (see also Proposition 14.3) gtσ(μ1,μ2)=logistic(μ1−μ2σ)ltσ(μ1,μ2)=logistic(μ2−μ1σ).\begin{align*} \mathrm{gt}_\sigma(\mu_1, \mu_2) &= \mathrm{logistic}\left(\frac{\mu_1-\mu_2}{\sigma}\right) \\ \mathrm{lt}_\sigma(\mu_1, \mu_2) &= \mathrm{logistic}\left(\frac{\mu_2-\mu_1}{\sigma}\right). \end{align*} The corresponding distribution for Z1Z_1 and Z2Z_2 is Gumbel noise.

Recovering hard inequality operators

We easily recover the “hard” inequality operator by gt(μ1,μ2)=E[gt(U1,U2)], \mathrm{gt}(\mu_1, \mu_2) = \EE\left[\mathrm{gt}(U_1, U_2)\right], where Ui∼δμiU_i \sim \delta_{\mu_i} and where δμi\delta_{\mu_i} is the delta distribution that assigns a probability of 11 to μi\mu_i.

5.3 Soft equality operators

5.3.1 Heuristic definition

The equality operator eq(μ1,μ2)\mathrm{eq}(\mu_1,\mu_2) can be seen as an extreme kind of similarity function between numbers, that can only output the values 00 or 11. To define soft equality operators, a natural idea is therefore to replace the equality operator by a more general similarity function. A similarity function should achieve its maximum at μ1=μ2\mu_1 = \mu_2 and it should decrease as μ1\mu_1 and μ2\mu_2 move apart. A common family of similarity functions are kernels. Briefly, a kernel k(μ1,μ2)k(\mu_1, \mu_2) can be seen as the inner product k(μ1,μ2)≔⟨ϕ(μ1),ϕ(μ2)⟩ k(\mu_1, \mu_2) \coloneqq \langle \phi(\mu_1), \phi(\mu_2) \rangle between the embeddings ϕ(μ1)\phi(\mu_1) and ϕ(μ2)\phi(\mu_2) of μ1\mu_1 and μ2\mu_2 in some (potentially infinite-dimensional) space H\cH, a reproducing kernel Hilbert space to be precise; see Schölkopf and Smola (2002; Shawe-Taylor and Cristianini, 2004) for an in-depth review of kernels. To obtain a similarity measure between 00 and 11 approximating the equality operator, we can normalize to obtain eq(μ1,μ2)≈k(μ1,μ2)k(μ1,μ1)k(μ2,μ2)=⟨ϕ(μ1),ϕ(μ2)⟩∥ϕ(μ1)∥∥ϕ(μ2)∥,\begin{align*} \mathrm{eq}(\mu_1, \mu_2) & \approx \frac{k(\mu_1,\mu_2)} {\sqrt{k(\mu_1,\mu_1)k(\mu_2,\mu_2)}} \\ & = \frac{\langle \phi(\mu_1), \phi(\mu_2) \rangle} {\|\phi(\mu_1)\|\|\phi(\mu_2)\|}, \end{align*} where ∥ϕ(μ)∥≔⟨ϕ(μ),ϕ(μ)⟩=κ(μ,μ)\|\phi(\mu)\| \coloneqq \sqrt{\langle \phi(\mu), \phi(\mu)\rangle} = \sqrt{\kappa(\mu, \mu)}. This is the cosine similarity between ϕ(μ1)\phi(\mu_1) and ϕ(μ2)\phi(\mu_2).

A particular kind of kernel is isotropic kernels of the form k(μ1,μ2)≔κ(μ1−μ2), k(\mu_1, \mu_2) \coloneqq \kappa(\mu_1 - \mu_2), that depend only on the difference between inputs. When the kernel has a scale parameter σ>0\sigma > 0, we use the notation κσ\kappa_\sigma. We can then define a soft equality operator as eq(μ1,μ2)≈eqσ(μ1,μ2)≔κσ(μ1−μ2)κσ(0).\begin{align*} \mathrm{eq}(\mu_1, \mu_2) \approx \mathrm{eq}_\sigma(\mu_1, \mu_2) \coloneqq \frac{\kappa_\sigma(\mu_1 - \mu_2)}{\kappa_\sigma(0)}. \end{align*} Several isotropic kernels can be chosen such as the Gaussian kernel κσ(t)≔exp⁡(−t22σ2) \kappa_\sigma(t) \coloneqq \exp\left(-\frac{t^2}{2\sigma^2}\right) or the logistic kernel κσ(t)≔sech2(t2σ), \kappa_\sigma(t) \coloneqq \mathrm{sech}^2\left(\frac{t}{2\sigma}\right), where we defined the hyperbolic secant sech(u)≔2/(exp⁡(u)+exp⁡(−u)). \mathrm{sech}(u) \coloneqq 2 / (\exp(u) + \exp(-u)). As their names suggest, these kernels arise naturally from a probabilistic perspective, that we present below.

The soft equality operators obtained with these kernels are illustrated in Fig. 5.2. Intuitively, we replaced a bar located at μ1=μ2\mu_1=\mu_2 with a bump function. The soft equality operator obtained with the logistic kernel coincides with the expression Petersen et al. (2021) arrive at (see their Eq. 9), in a different manner.

Figure 5.2: Soft equality and soft greater than operators can be defined as normalized kernels (PDF) and as CDF functions, respectively.

5.3.2 Stochastic process perspective

We again adopt the stochastic process perspective, in which we associate random variables U1∼pμ1,σandU2∼pμ2,σ U_1 \sim p_{\mu_1,\sigma} \quad \text{and} \quad U_2 \sim p_{\mu_2,\sigma} to real values μ1∈R\mu_1 \in \RR and μ2∈R\mu_2 \in \RR. However, to handle the equality operator, we cannot simply use the expectation of eq(U1,U2)\mathrm{eq}(U_1, U_2) since E[eq(U1,U2)]=P(U1=U2)=0, \EE[\mathrm{eq}(U_1, U_2)] = \PP(U_1=U_2)= 0, U1U_1 and U2U_2 being independent continuous variables. While we cannot use the probability of U1=U2U_1=U_2, or equivalently of U1−U2=0U_1-U_2=0, we can consider using the probability density function (PDF) fU1−U2f_{U_1-U_2} of U1−U2U_1-U_2 evaluated at 00. To ensure that the maximum is achieved at 00 with value 11, we can normalize the PDF to define eqσ(μ1,μ2)=fU1−U2(0)fU0(0), \mathrm{eq}_\sigma(\mu_1,\mu_2) = \frac{f_{U_1 - U_2}(0)}{f_{U_0}(0)}, where U0∼p0,σU_0 \sim p_{0, \sigma} (we assume that fU0f_{U_0} attains its maximum at 00). It is well-known that the PDF of the sum of two random variables is the convolution of their respective PDFs. We therefore have fU1−U2(t)=(fU1∗f−U2)(t)=∫−∞∞fU1(τ)f−U2(t−τ)dτ.\begin{align*} f_{U_1-U_2}(t) &= (f_{U_1} \ast f_{-U_2})(t) \\ &= \int_{-\infty}^\infty f_{U_1}(\tau) f_{-U_2}(t - \tau) d\tau. \end{align*} In particular, with t=0t=0, if fXf_X is the PDF of a location-scale family distributed random variable, we obtain fU1−U2(0)=(fU1∗f−U2)(0)=∫−∞∞fU1(τ)f−U2(−τ)dτ=∫−∞∞fU1(τ)fU2(τ)dτ≔⟨fU1,fU2⟩≔κ(μ1,μ2).\begin{align*} f_{U_1-U_2}(0) &= (f_{U_1} \ast f_{-U_2})(0) \\ &= \int_{-\infty}^\infty f_{U_1}(\tau) f_{-U_2}(-\tau) d\tau \\ &= \int_{-\infty}^\infty f_{U_1}(\tau) f_{U_2}(\tau) d\tau \\ &\coloneqq \langle f_{U_1}, f_{U_2} \rangle \\ &\coloneqq \kappa(\mu_1,\mu_2). \end{align*} We indeed recover an inner product and therefore a kernel.

CDF and PDF of absolute difference

While P(U1=U2)=0\PP(U_1=U_2) = 0, we can also consider using P(∣U1−U2∣≤ε)=F∣U1−U2∣(ε)\PP(|U_1-U_2| \le \varepsilon) = F_{|U_1-U_2|}(\varepsilon) as an alternative notion of soft equality. For any random variable XX, we have F∣X∣(x)=P(∣X∣≤x)=P(−x≤X≤x)=P(X≤x)−P(X≤−x)=FX(x)−FX(−x).\begin{align*} F_{|X|}(x) &= \PP(|X| \le x) \\ &= \PP(-x \le X \le x) \\ &= \PP(X \le x) - \PP(X \le -x) \\ &= F_X(x) - F_X(-x). \end{align*} Therefore, P(∣U1−U2∣≤ε)=FU1−U2(ε)−FU1−U2(−ε). \PP(|U_1-U_2| \le \varepsilon) = F_{U_1-U_2}(\varepsilon) - F_{U_1-U_2}(-\varepsilon). We can also derive the PDF of ∣X∣|X| as f∣X∣(x)=FX′(x)−FX′(−x)=fX(x)+fX(−x)\begin{align*} f_{|X|}(x) &= F'_X(x) - F'_{X}(-x) \\ &= f_X(x) + f_{X}(-x) \end{align*} and in particular f∣X∣(0)=2fX(0). f_{|X|}(0) = 2 f_X(0). Therefore f∣U1−U2∣(0)=2fU1−U2(0), f_{|U_1-U_2|}(0) = 2 f_{U_1-U_2}(0), further justifying using the PDF of U1−U2U_1 - U_2 evaluated at 00. When XX follows a normal distribution, ∣X∣|X| follows the so-called folded normal distribution.

Gaussian case

When U1∼Normal(μ1,σ12)U_1 \sim \mathrm{Normal}(\mu_1, \sigma_1^2) and U2∼Normal(μ2,σ22)U_2 \sim \mathrm{Normal}(\mu_2, \sigma_2^2), we obtain from Eq. (5.1) fU1−U2(t)=12πexp⁡(−(t−(μ1−μ2))22(σ12+σ22)) f_{U_1 - U_2}(t) = \frac{1}{\sqrt{2\pi}} \exp\left(-\frac{(t - (\mu_1 -\mu_2))^2}{2(\sigma_1^2 + \sigma_2^2)}\right) so that eqσ(μ1,μ2)=exp⁡(−(μ1−μ2)22(σ12+σ22))∈[0,1]. \mathrm{eq}_\sigma(\mu_1,\mu_2) = \exp\left(-\frac{(\mu_1 -\mu_2)^2}{2(\sigma_1^2 + \sigma_2^2)}\right) \in [0,1]. We indeed recover κσ(μ1−μ2)/κσ(0)\kappa_\sigma(\mu_1 - \mu_2) / \kappa_\sigma(0), where κσ\kappa_\sigma is the Gaussian kernel with σ=σ12+σ22\sigma = \sqrt{\sigma_1^2 + \sigma_2^2}. For the CDF of the absolute difference, we obtain P(∣U1−U2∣≤ε)=Φ(ε−(μ1−μ2)σ)−Φ(−ε−(μ1−μ2)σ). \PP(|U_1-U_2| \le \varepsilon) = \Phi\left(\frac{\varepsilon-(\mu_1-\mu_2)}{\sigma}\right) - \Phi\left(\frac{-\varepsilon-(\mu_1-\mu_2)}{\sigma}\right).

Logistic case

When U1∼Gumbel(μ1,σ)U_1 \sim \mathrm{Gumbel}(\mu_1, \sigma) and U2∼Gumbel(μ2,σ)U_2 \sim \mathrm{Gumbel}(\mu_2, \sigma), recalling that sech(u)≔2/(exp⁡(u)+exp⁡(−u)), \mathrm{sech}(u) \coloneqq 2 / (\exp(u) + \exp(-u)), we obtain from Eq. (5.2) fU1−U2(t)=14σsech2(t−(μ1−μ2)2σ) f_{U_1 - U_2}(t) = \frac{1}{4\sigma} \mathrm{sech}^2\left(\frac{t - (\mu_1 - \mu_2)}{2 \sigma}\right) so that eqσ(μ1,μ2)=sech2(μ1−μ22σ)∈[0,1]. \mathrm{eq}_\sigma(\mu_1,\mu_2) = \mathrm{sech}^2\left(\frac{\mu_1 - \mu_2}{2 \sigma}\right) \in [0,1]. We indeed recover κσ(μ1−μ2)/κσ(0)\kappa_\sigma(\mu_1 - \mu_2) / \kappa_\sigma(0), where κσ\kappa_\sigma is the logistic kernel with σ=σ1=σ2\sigma = \sigma_1 = \sigma_2.

5.3.3 Gaussian process perspective

The previous approach relied on mapping μ1\mu_1 and μ2\mu_2 to two independent random variables U1∼pμ1,σ1U_1 \sim p_{\mu_1,\sigma_1} and U2∼pμ2,σ2U_2 \sim p_{\mu_2,\sigma_2} (we assume that σ1\sigma_1 and σ2\sigma_2 are fixed). Instead, we can consider mapping μ1\mu_1 and μ2\mu_2 to two dependent random variables U1U_1 and U2U_2, whose covariance depends on the similarity between μ1\mu_1 and μ2\mu_2. We can do so by using a Gaussian process (Hida and Hitsuda, 1976).

A Gaussian process on R\RR is a stochastic process {Uμ:μ∈R}\{U_\mu: \mu\in \RR\} indexed by μ∈R\mu \in \RR such that any subset of KK random variables (Uμ1,…,UμK)(U_{\mu_1}, \dots, U_{\mu_K}) associated with (μ1,…,μK)∈RK(\mu_1, \ldots, \mu_K) \in \RR^K is a multivariate Gaussian random variable. The Gaussian process is characterized by the mean function μ↦E[Uμ]\mu \mapsto \EE[U_{\mu}], and its covariance function (μi,μj)↦Cov⁡(Uμi,Uμj)(\mu_i,\mu_j) \mapsto \Cov(U_{\mu_i}, U_{\mu_j}). For the mean function, we may simply choose E[Uμ]=μ\EE[U_{\mu}]=\mu. For the covariance function, we need to ensure that the variance of any combination of random variables in the Gaussian process is non-negative. This property is satisfied by kernel functions. We can therefore define Cov⁡(Uμi,Uμj)≔k(μi,μj), \Cov(U_{\mu_i}, U_{\mu_j}) \coloneqq k(\mu_i, \mu_j), for some kernel kk. Equipped with such a mapping from real numbers to random variables, we need a measure of similarity between random variables. A natural choice is their correlation corr(Uμi,Uμj)≔Cov⁡(Uμi,Uμj)Var⁡(Uμi)Var⁡(Uμj)∈[−1,1]. \mathrm{corr}(U_{\mu_i}, U_{\mu_j}) \coloneqq \frac{\Cov(U_{\mu_i}, U_{\mu_j})}{\sqrt{\Var(U_{\mu_i})\Var(U_{\mu_j})}} \in [-1, 1]. We therefore obtain corr(Uμi,Uμj)=k(μi,μj)k(μi,μi)k(μj,μj)=⟨ϕ(μi),ϕ(μj)⟩∥ϕ(μi)∥∥ϕ(μj)∥,\begin{align*} \mathrm{corr}(U_{\mu_i}, U_{\mu_j}) &= \frac{k(\mu_i,\mu_j)}{\sqrt{k(\mu_i,\mu_i)k(\mu_j,\mu_j)}} \\ &= \frac{\langle \phi(\mu_i),\phi(\mu_j) \rangle}{\|\phi(\mu_i)\|\|\phi(\mu_j)\|}, \end{align*} which coincides with the cosine similarity measure we saw before. In the particular case K=2K=2 and when kσ(μ1,μ2)=κ(μ1−μ2)k_\sigma(\mu_1, \mu_2) = \kappa(\mu_1 - \mu_2), we then recover the previous heuristically defined soft equality operator eqσ(μ1,μ2)=corr(Uμ1,Uμ2)=κ(μ1−μ2)κ(0). \mathrm{eq}_\sigma(\mu_1, \mu_2) = \mathrm{corr}(U_{\mu_1}, U_{\mu_2}) = \frac{\kappa(\mu_1 -\mu_2)}{\kappa(0)}.

5.4 Logical operators

Logical operators can be used to perform Boolean algebra. Formally, we can define them as functions from {0,1}×{0,1}\{0,1\} \times \{0,1\} to {0,1}\{0,1\}. The and (logical conjunction a.k.a. logical product), or (logical disjunction a.k.a. logical addition) and not (logical negation a.k.a. logical complement) operators, for example, are defined by and(π,π′)≔{1 if π=π′=10 otherwise or(π,π′)≔{1 if 1∈{π,π′}0 otherwise not(π)≔{0 if π=11 if π=0.\begin{align*} \mathrm{and}(\pi, \pi') &\coloneqq \begin{cases} 1 &\mbox{ if } \pi = \pi' = 1 \\ 0 &\mbox{ otherwise } \end{cases} \\ \mathrm{or}(\pi, \pi') &\coloneqq \begin{cases} 1 &\mbox{ if } 1 \in \{\pi, \pi'\} \\ 0 &\mbox{ otherwise } \end{cases} \\ \mathrm{not}(\pi) &\coloneqq \begin{cases} 0 &\mbox{ if } \pi = 1 \\ 1 &\mbox{ if } \pi = 0 \end{cases}. \end{align*} Classical properties of these operators include

More generally, for a binary vector π=(π1,…,πK)∈{0,1}K\piv = (\pi_1, \dots, \pi_K) \in \{0,1\}^K, we can define all\textbf{all} (universal quantification, ∀\forall) and any\textbf{any} (existential quantification, ∃\exists) operators, which are functions from {0,1}K\{0,1\}^K to {0,1}\{0,1\}, as all(π)≔{1 if π1=⋯=πK=10 otherwise  \mathrm{all}(\piv) \coloneqq \begin{cases} 1 &\mbox{ if } \pi_1 = \dots = \pi_K = 1 \\ 0 &\mbox{ otherwise } \end{cases} and any(π)≔{1 if 1∈{π1,…,πK}0 otherwise . \mathrm{any}(\piv) \coloneqq \begin{cases} 1 &\mbox{ if } 1 \in \{\pi_1, \dots, \pi_K\} \\ 0 &\mbox{ otherwise } \end{cases}.

5.5 Continuous extensions of logical operators

5.5.1 Probabilistic continuous extension

We can equivalently write the and, or and not operators as and(π,π′)=π⋅π′or(π,π′)=π+π′−π⋅π′not(π)=1−π.\begin{align*} \mathrm{and}(\pi, \pi') &= \pi \cdot \pi' \\ \mathrm{or}(\pi, \pi') &= \pi + \pi' - \pi \cdot \pi' \\ \mathrm{not}(\pi) &= 1 - \pi. \end{align*} These are extensions of the previous definitions: we can use them as functions from [0,1]×[0,1]→[0,1][0, 1] \times [0,1] \to [0, 1], as illustrated in Fig. 5.3. This means that we can use the soft comparison operators defined in Section 5.2 to obtain π,π′∈[0,1]\pi, \pi' \in [0,1]. Likewise, we can define continuous extensions of all and any, which are functions from [0,1]K[0,1]^K to [0,1][0,1], as all(π)=∏i=1Kπiany(π)=1−∏i=1K(1−πi).\begin{align*} \mathrm{all}(\piv) &= \prod_{i=1}^K \pi_i \\ \mathrm{any}(\piv) &= 1 - \prod_{i=1}^K (1 - \pi_i). \end{align*}

Figure 5.3: The Boolean and and or operators are functions from {0,1}×{0,1}\{0,1\} \times \{0,1\} to {0,1}\{0,1\} (corners in the figure) but their continuous extensions and(π,π′)≔π⋅π′\mathrm{and}(\pi, \pi') \coloneqq \pi \cdot \pi' as well as or(π,π′)≔π+π′−π⋅π′\mathrm{or}(\pi, \pi') \coloneqq \pi + \pi' - \pi \cdot \pi' define a function from [0,1]×[0,1][0,1] \times [0,1] to [0,1][0,1].

From a probabilistic perspective, if we let YY and Y′Y' be two independent random variables distributed according to Bernoulli distributions with parameters π\pi and π′\pi', then and(π,π′)=P(Y=1∩Y′=1)=P(Y=1)⋅P(Y′=1)or(π,π′)=P(Y=1∪Y′=1)=P(Y=1)+P(Y′=1)−P(Y=1∩Y′=1)=P(Y=1)+P(Y′=1)−P(Y=1)P(Y′=1)not(π)=P(Y≠1)=1−P(Y=1).\begin{align*} \mathrm{and}(\pi, \pi') &= \PP(Y = 1 \cap Y' = 1) = \PP(Y = 1) \cdot \PP(Y' = 1) \\ \mathrm{or}(\pi, \pi') &= \PP(Y = 1 \cup Y' = 1) \\ &= \PP(Y=1) + \PP(Y'=1) - \PP(Y = 1 \cap Y' = 1) \\ &= \PP(Y=1) + \PP(Y'=1) - \PP(Y = 1) \PP(Y' = 1) \\ \mathrm{not}(\pi) &= \PP(Y \neq 1) = 1 - \PP(Y = 1). \end{align*} In probability theory, these correspond to the product rule of two independent variables, the addition rule, and the complement rule.

Likewise, if we let Y=(Y1,…,YK)∈{0,1}KY = (Y_1, \dots, Y_K) \in \{0,1\}^K be a random variable distributed according to a multivariate Bernoulli distribution with parameters π=(π1,…,πK)\piv = (\pi_1, \dots, \pi_K), then all(π)=P(Y1=1∩⋯∩YK=1)=∏i=1KP(Yi=1)any(π)=P(Y1=1∪⋯∪YK=1)=1−P(¬(Y1=1∪⋯∪YK=1))=1−P(Y1≠1∩⋯∩YK≠1)=1−∏i=1K(1−P(Yi=1)).\begin{align*} \textrm{all}(\piv) &= \PP(Y_1 = 1 \cap \dots \cap Y_K = 1) \\ &= \prod_{i=1}^K \PP(Y_i = 1) \\ \textrm{any}(\piv) &= \PP(Y_1 = 1 \cup \dots \cup Y_K = 1) \\ &= 1 - \PP(\neg(Y_1 = 1 \cup \dots \cup Y_K = 1)) \\ &= 1 - \PP(Y_1 \neq 1 \cap \dots \cap Y_K \neq 1) \\ &= 1 - \prod_{i=1}^K (1 - \PP(Y_i=1)). \end{align*} These are the chain rule of probability and the addition rule of probability for KK independent variables.

5.5.2 Triangular norms and co-norms

More generally, in the fuzzy logic literature (Jayaram and Baczynski, 2008; Klir and Yuan, 1995), the concepts of triangular norms and co-norms have been introduced to provide continuous relaxations of the and and or operators, respectively.

Definition 5.1 (Triangular norms and conorms)

A triangular norm, a.k.a. t-norm, is a function from [0,1]×[0,1][0,1] \times [0,1] to [0,1][0,1] which is commutative, associative, neutral w.r.t. 11 and is monotone, meaning that t(π,π′)≤t(τ,τ′)t(\pi, \pi') \le t(\tau, \tau') for all π≤τ\pi \le \tau and π′≤τ′\pi' \le \tau'. A triangular conorm, a.k.a. t-conorm, is defined similarly but is neutral w.r.t.  00.

The previously-defined probabilistic extensions of and\textbf{and} and or are examples of triangular norms and conorms. More examples are given in Table 5.1. Thanks to the associative property of these operators, we can generalize them to vectors π∈[0,1]K\piv \in [0,1]^K to define continuous extensions of the all and any operators, as shown in Table 5.2. For more examples and analysis, see for instance van Krieken (2024, 2 and 3).

Figure 5.4: Alternative relaxations of the Boolean and and or operators using triangular norms (t-norms).

Table 5.1: Examples of triangular norms and conorms, which are continuous relaxations of the and and or operators, respectively. More instances can be obtained by smoothing out the min and max operators.

  t-norm (relaxed and) t-conorm (relaxed or)
Probabilistic π⋅π′\pi \cdot \pi' π+π′−π⋅π′\pi + \pi' - \pi \cdot \pi'
Extremum min⁡(π,π′)\min(\pi, \pi') max⁡(π,π′)\max(\pi, \pi')
Łukasiewicz max⁡(π+π′−1,0)\max(\pi + \pi' - 1, 0) min⁡(π+π′,1)\min(\pi + \pi', 1)

Table 5.2: Continuous extensions of the all and any operators.

  All (∀\forall) Any (∃\exists)
Probabilistic ∏i=1Kπi\prod_{i=1}^K \pi_i 1−∏i=1K(1−πi)1 - \prod_{i=1}^K (1 - \pi_i)
Extremum min⁡(π1,…,πK)\min(\pi_1, \dots, \pi_K) max⁡(π1,…,πK)\max(\pi_1, \dots, \pi_K)
Łukasiewicz max⁡(∑i=1Kπi−(K−1),0)\max(\sum_{i=1}^K \pi_i - (K-1), 0) min⁡(∑i=1Kπi,1)\min(\sum_{i=1}^K \pi_i, 1)

5.6 If-else statements

An if-else statement executes different code depending on a condition. Formally, we can define the ifelse ⁣:{0,1}×V×V→V\mathrm{ifelse} \colon \{0,1\} \times \cV \times \cV \to \cV function by ifelse(π,v1,v0)≔{v1 if π=1v0 if π=0=π⋅v1+(1−π)⋅v0.\begin{align*} \mathrm{ifelse}(\pi, \v_1, \v_0) &\coloneqq \begin{cases} \v_1 &\mbox{ if } \pi = 1 \\ \v_0 &\mbox{ if } \pi = 0 \end{cases} \tag{5.3}\\ &= \pi \cdot \v_1 + (1 - \pi) \cdot \v_0. \end{align*} The π\pi variable is called the predicate. It is a binary (Boolean) variable, making the function ifelse\mathrm{ifelse} undefined if π∉{0,1}\pi \not \in \{0,1\}. The function is therefore discontinuous and nondifferentiable w.r.t. π∈{0,1}\pi \in \{0,1\}. On the other hand, v0∈V\v_0 \in \cV and v1∈V\v_1 \in \cV, which correspond to the false and true branches, can be continuous variables. If π=1\pi=1, the function is linear w.r.t. v1\v_1 and constant w.r.t. v0\v_0. Conversely, if π=0\pi=0, the function is linear w.r.t. v0\v_0 and constant w.r.t. v1\v_1. We now discuss how to differentiate through ifelse\mathrm{ifelse}.

5.6.1 Differentiating through branch variables

For π∈{0,1}\pi \in \{0,1\} fixed, ifelse(π,v1,v0)\mathrm{ifelse}(\pi, \v_1, \v_0) is a valid function w.r.t. v1∈V\v_1 \in \cV and v0∈V\v_0 \in \cV, and can therefore be used as a node in a computational graph (Section 8.3). Due to the linearity w.r.t. v1\v_1 and v0\v_0, we obtain that the Jacobians w.r.t. v1\v_1 and v0\v_0 are ∂v0ifelse(π,v1,v0)≔{0 if π=1I if π=0=(1−π)⋅I\begin{align*} \partial_{\v_0} \mathrm{ifelse}(\pi, \v_1, \v_0) &\coloneqq \begin{cases} 0 &\mbox{ if } \pi = 1 \\ I &\mbox{ if } \pi = 0 \end{cases} \\ &= (1-\pi) \cdot I \end{align*} and ∂v1ifelse(π,v1,v0)≔{I if π=10 if π=0=π⋅I,\begin{align*} \partial_{\v_1} \mathrm{ifelse}(\pi, \v_1, \v_0) &\coloneqq \begin{cases} I &\mbox{ if } \pi = 1 \\ 0 &\mbox{ if } \pi = 0 \end{cases} \\ &= \pi \cdot I, \end{align*} where II is the identity matrix of appropriate size. Most of the time, if-else statements are composed with other functions. Let g1 ⁣:U1→Vg_1 \colon \cU_1 \to \cV and g0 ⁣:U0→Vg_0 \colon \cU_0 \to \cV be differentiable functions. We then define v1≔g1(u1)\v_1 \coloneqq g_1(\u_1) and v0≔g0(u0)\v_0 \coloneqq g_0(\u_0), where u1∈U1\u_1 \in \cU_1 and u0∈U0\u_0 \in \cU_0. The composition of ifelse\mathrm{ifelse}, g1g_1 and g0g_0 is then the function f ⁣:{0,1}×U1×U0→Vf \colon \{0,1\} \times \cU_1 \times \cU_0 \to \cV defined by f(π,u1,u0)≔ifelse(π,g1(u1),g0(u0))=π⋅g1(u1)+(1−π)⋅g0(u0).\begin{align*} f(\pi, \u_1, \u_0) &\coloneqq \mathrm{ifelse}(\pi, g_1(\u_1), g_0(\u_0)) \\ &= \pi \cdot g_1(\u_1) + (1-\pi) \cdot g_0(\u_0). \end{align*} We obtain that the Jacobians are ∂u1f(π,u1,u0)=π⋅∂g1(u1) \partial_{\u_1} f(\pi, \u_1, \u_0) = \pi \cdot \partial g_1(\u_1) and ∂u0f(π,u1,u0)=(1−π)⋅∂g0(u0). \partial_{\u_0} f(\pi, \u_1, \u_0) = (1-\pi) \cdot \partial g_0(\u_0). As long as g1g_1 and g0g_0 are differentiable functions, we can therefore differentiate through the branch variables u1\u_1 and u0\u_0 without any issue. More problematic is the predicate variable π\pi, as we now discuss.

5.6.2 Differentiating through predicate variables

The predicate variable π\pi is binary and therefore cannot be differentiated directly. However, π\pi can be the output of a comparison operator. For example, suppose we want to express the function fh ⁣:R×U1×U0→Vf_h \colon \RR \times \cU_1 \times \cU_0 \to \cV defined by fh(p,u1,u0)≔{g1(u1) if p≥0g0(u0) otherwise . f_h(p, \u_1, \u_0) \coloneqq \begin{cases} g_1(\u_1) &\mbox{ if } p \ge 0 \\ g_0(\u_0) &\mbox{ otherwise } \end{cases}. Using our notation, this can be rewritten as fh(p,u1,u0)≔ifelse(gt(p,0),g1(u1),g0(u0))=ifelse(step(p),g1(u1),g0(u0))=step(p)g1(u1)+(1−step(p))g0(u0).\begin{align*} f_h(p, \u_1, \u_0) &\coloneqq \mathrm{ifelse}(\mathrm{gt}(p, 0), g_1(\u_1), g_0(\u_0)) \\ &= \mathrm{ifelse}(\heavistep(p), g_1(\u_1), g_0(\u_0)) \\ &= \heavistep(p) g_1(\u_1) + (1 - \heavistep(p)) g_0(\u_0). \end{align*} The Heaviside step function has a discontinuity at p=0p=0, but it is continuous and differentiable with derivative step′(p)=0\heavistep'(p) = 0 for all p≠0p \neq 0. The function fhf_h therefore has null derivative w.r.t. p≠0p \neq 0, ∂pfh(p,u1,u0)=∂1fh(p,u1,u0)=step′(p)(g1(u1)−g0(u0))=0.\begin{align*} \partial_p f_h(p, \u_1, \u_0) &= \partial_1 f_h(p, \u_1, \u_0) \\ &= \heavistep'(p)(g_1(\u_1) - g_0(\u_0)) \\ &= \zeros. \end{align*} In other words, while fhf_h has well-defined derivatives w.r.t. pp for p≠0p \neq 0, the derivatives are uninformative. As another example, let us now consider the function gh(u1,u0)≔fh(t(u1),u1,u0), g_h(\u_1, \u_0) \coloneqq f_h(t(\u_1), \u_1, \u_0), for some differentiable function tt. This time, u1\u_1 influences both the predicate and the true branch. Then, using Proposition 2.8, we obtain ∂u1gh(u1,u0)=∂t(u1)∂1fh(t(u1),u1,u0)+∂2fh(t(u1),u1,u0)=∂2fh(t(u1),u1,u0).\begin{align*} \partial_{\u_1} g_h(\u_1, \u_0) &= \partial t(\u_1) \partial_1 f_h(t(\u_1), \u_1, \u_0) + \partial_2 f_h(t(\u_1), \u_1, \u_0) \\ &= \partial_2 f_h(t(\u_1), \u_1, \u_0). \end{align*} In other words, the derivatives of the predicate t(u1)t(\u_1) do not influence the derivatives of ghg_h.

5.6.3 Continuous relaxations

Fortunately, we recall that ifelse(π,v1,v0)=π⋅v1+(1−π)⋅v0. \mathrm{ifelse}(\pi, \v_1, \v_0) = \pi \cdot \v_1 + (1 - \pi) \cdot \v_0. This function is perfectly well-defined, even if π∈[0,1]\pi \in [0,1], instead of π∈{0,1}\pi \in \{0,1\}. That is, this definition is an extension of Eq. (5.3) from the discrete set {0,1}\{0,1\} to the continuous unit segment [0,1][0,1]. We saw that gt(a,b)≈gtσ(a,b)≔sigmoidσ(a−b)∈[0,1], \mathrm{gt}(a, b) \approx \mathrm{gt}_\sigma(a, b) \coloneqq \sigmoid_\sigma(a - b) \in [0,1], where we use sigmoidσ\sigmoid_\sigma to denote a differentiable S-shaped function mapping R\RR to [0,1][0,1]. For instance, we can use the logistic function or the standard Gaussian’s CDF. If we now define fs(p,u1,u0)≔ifelse(gtσ(p,0),g1(u1),g0(u0))=ifelse(sigmoidσ(p),g1(u1),g0(u0))=sigmoidσ(p)g1(u1)+(1−sigmoidσ(p))g0(u0),\begin{align*} f_s(p, \u_1, \u_0) &\coloneqq \mathrm{ifelse}(\mathrm{gt}_\sigma(p, 0), g_1(\u_1), g_0(\u_0)) \\ &= \mathrm{ifelse}(\sigmoid_\sigma(p), g_1(\u_1), g_0(\u_0)) \\ &= \sigmoid_\sigma(p) g_1(\u_1) + (1 - \sigmoid_\sigma(p)) g_0(\u_0), \tag{5.4}\end{align*} the Jacobian becomes ∂pfs(p,u1,u0)=sigmoidσ′(p)(g1(u1)−g0(u0)). \partial_p f_s(p, \u_1, \u_0) = \sigmoid'_\sigma(p)(g_1(\u_1) - g_0(\u_0)). If sigmoidσ=logistic(⋅/σ)\sigmoid_\sigma = \logistic(\cdot / \sigma) or sigmoidσ=Φ(⋅/σ)\sigmoid_\sigma = \Phi(\cdot/\sigma), the Jacobian is non-null everywhere, allowing gradients to backpropagate through the computational graph. This is an example of smoothing as studied in Part IV.

Figure 5.5: Computation graphs of programs using if-else statements with either hard or soft comparison operators. By using a hard comparison operator (step function, left panel) the predicate π\pi is a discrete variable (represented by a dashed line). Depending on the value (00 or 11) of the predicate π\pi, only one branch (red or blue) contributes to the output. Derivatives along a path of continuous variables (dense lines) can be computed. However, discrete variables such as the predicate prevent the propagation of meaningful derivatives. By using a soft comparison operator (sigmoid, right panel), the predicate is a continuous variable and derivatives with respect to the input pp can be taken. In this case both branches (corresponding to g0g_0 and g1g_1) contribute to the output and therefore need to be evaluated.

Probabilistic perspective

From a probabilistic perspective, we can view Eq. (5.4) as the expectation of gi(ui)g_i(\u_i), where i∈{0,1}i \in \{0,1\} is a binary random variable distributed according to a Bernoulli distribution with parameter π=sigmoidσ(p)\pi = \sigmoid_\sigma(p): fs(p,u1,u0)=Ei∼Bernoulli(sigmoidσ(p))[gi(ui)]. f_s(p, \u_1, \u_0) = \EE_{i \sim \mathrm{Bernoulli}(\sigmoid_\sigma(p))}\left[g_i(\u_i)\right]. Taking the expectation over the two possibles branches makes the function differentiable with respect to pp, since sigmoidσ(p)\sigmoid_\sigma(p) is differentiable. Of course, this comes at the cost of evaluating both branches, instead of a single one. The probabilistic perspective suggests that we can also compute the variance if needed as Vi∼Bernoulli(sigmoidσ(p))[gi(ui)]=Ei∼Bernoulli(sigmoidσ(p))[(fs(p,u1,u0)−gi(ui))2].\begin{align*} &\VV_{i \sim \mathrm{Bernoulli}(\sigmoid_\sigma(p))}\left[g_i(\u_i)\right] \\ =& \EE_{i \sim \mathrm{Bernoulli}(\sigmoid_\sigma(p))} \left[(f_s(p, \u_1, \u_0) - g_i(\u_i))^2 \right]. \end{align*} The probabilistic viewpoint also suggests different scales at which a smoothing can be defined as illustrated in Fig. 5.6.

Another perspective (Petersen et al., 2021) is based on the logistic distribution. Indeed, if PP is a random variable following a logistic distribution with mean pp and scale 11, we saw in Remark 3.1 that the CDF is P(P≤0)=logistic(−p)=1−logistic(p)\PP(P \le 0) = \logistic(-p) = 1 - \logistic(p) and therefore fs(p,u1,u0)=ifelse(logistic(p),g1(u1),g0(u0))=logistic(p)g1(u1)+(1−logistic(p))g0(u0)=P(P>0)⋅g1(u1)+P(P≤0)⋅g0(u0).\begin{align*} f_s(p, \u_1, \u_0) &= \mathrm{ifelse}(\logistic(p), g_1(\u_1), g_0(\u_0)) \\ &= \logistic(p) g_1(\u_1) + (1 - \logistic(p)) g_0(\u_0) \\ &= \PP(P > 0) \cdot g_1(\u_1) + \PP(P \le 0) \cdot g_0(\u_0). \end{align*}

Remark 5.1 (Global versus local smoothing)

Consider the function f(x,y,z)≔{yif a≤x≤bzotherwise.\begin{align*} f(x, y, z) \coloneqq \begin{cases} y & \mbox{if} \ a \leq x \leq b \\ z & \mbox{otherwise} \end{cases}. \end{align*} The derivatives w.r.t. yy and zz are well-defined. The derivative w.r.t. xx on the other hand is not well-defined since it involves comparison operators and the logical operator and\mathrm{and}. Using our notation, we can rewrite the function as f(x,y,z)=ifelse(and(gt(x,a),lt(x,b)),y,z).\begin{align*} f(x, y, z) & = \mathrm{ifelse}(\mathrm{and}(\mathrm{gt}(x, a), \mathrm{lt}(x, b)), y, z). \end{align*} A local smoothing approach consists in replacing gt\mathrm{gt} and lt\mathrm{lt} by gtσ\mathrm{gt}_\sigma and ltσ\mathrm{lt}_\sigma locally in the program: fσloc(x,y,z)≔ifelse(and(gtσ(x,a),ltσ(x,b)),y,z)=πaπby+(1−πaπb)z\begin{align*} f^{\mathrm{loc}}_\sigma(x, y, z) &\coloneqq \mathrm{ifelse}(\mathrm{and}(\mathrm{gt}_\sigma(x, a), \mathrm{lt}_\sigma(x, b)), y, z) \\ &= \pi_a \pi_b y + (1-\pi_a\pi_b)z \end{align*} where πa≔sigmoidσ(x−a)πb≔sigmoidσ(b−x),\begin{align*} \pi_a &\coloneqq \mathrm{sigmoid}_\sigma(x-a) \\ \pi_b &\coloneqq \mathrm{sigmoid}_\sigma(b-x), \end{align*} for any sigmoid function sigmoidσ\sigmoid_\sigma. A global smoothing approach instead uses the expectation of the entire program fσglob(x,y,z)≔EZ[ifelse(and(gt(x+σZ,a),lt(x+σZ,b)),y,z)]=ifelse(π,y,z)\begin{align*} f^{\mathrm{glob}}_\sigma(x, y, z) &\coloneqq \EE_Z[\mathrm{ifelse}(\mathrm{and}(\mathrm{gt}(x+\sigma Z, a), \mathrm{lt}(x + \sigma Z, b)), y, z)] \\ &=\mathrm{ifelse}(\pi, y, z) \end{align*} where π≔EZ[and(gt(x+σZ,a),lt(x+σZ,b))]=P(a≤x+σZ≤b)=sigmoidσ(b−x)−sigmoidσ(a−x)=πb−πa,\begin{align*} \pi &\coloneqq \EE_Z[\mathrm{and}(\mathrm{gt}(x + \sigma Z, a), \mathrm{lt}(x +\sigma Z, b))] \\ & = \PP(a\leq x+\sigma Z\leq b) \\ & = \sigmoid_\sigma(b - x) - \sigmoid_\sigma(a-x)\\ & = \pi_b - \pi_a, \end{align*} for sigmoidσ\sigmoid_\sigma the CDF of σZ\sigma Z. We therefore obtain fσglob(x,y,z)=(πb−πa)y+(1−(πb−πa))z. f^{\mathrm{glob}}_\sigma(x, y, z) =(\pi_b - \pi_a) y + (1 - (\pi_b - \pi_a)) z. The difference stems from the fact that the local approach smoothes out a≤xa \le x and x≤bx \le b independently (treating 1⁡X≥a\ones_{X \geq a} and 1⁡X≤b\ones_{X\leq b} as independent random variables), while the global approach smoothes out a≤x≤ba \le x \le b simultaneously. In practice, both approaches approximate the original function well as σ→0\sigma \rightarrow 0 and coincide for σ\sigma sufficiently small as illustrated in  Fig. 5.6.

Figure 5.6: Global versus local smoothing approaches on a gate function f(x)≔1f(x) \coloneqq 1 if x∈[−1,1]x \in [-1, 1], and f(x)≔0f(x) \coloneqq 0 otherwise. In our notation, we can write f(x)=ifelse(and(gt(x,−1),lt(x,1)),1,0)f(x) = \mathrm{ifelse}(\mathrm{and}(\mathrm{gt}(x, -1), \mathrm{lt}(x, 1)), 1, 0). A local approach smoothes out gt\mathrm{gt} and lt\mathrm{lt} separately. A global approach uses the expectation of the whole program, see Remark 5.1. We observe that, though the approaches differ for large σ\sigma, they quickly coincide for smaller σ\sigma.

5.7 Else-if statements

In the previous section, we focused on if-else statements: conditionals with only two branches. We now generalize our study to conditionals including else-if statements, that have KK branches.

5.7.1 Encoding KK branches

For conditionals with only 22 branches, we encoded the branch that the conditional needs to take using the binary variable π∈{0,1}\pi \in \{0,1\}. For conditionals with KK branches, we need a way to encode which of the KK branches the conditional needs to take. To do so, we can use a vector π∈{e1,…,eK}\piv \in \{\e_1, \dots, \e_K\}, where ei\e_i denotes the standard basis vector (a.k.a. one-hot vector) ei≔(0,…,1⏟i,…,0), \e_i \coloneqq (0, \dots, \underbrace{1}_i, \dots, 0), a vector with a single one in the coordinate ii and K−1K-1 zeros. The vector ei\e_i is the encoding of a categorical variable i∈[K]i \in [K].

Combining booleans

To form such a vector π∈{e1,…,eK}\piv \in \{\e_1,\dots,\e_K\}, we can combine the previously-defined comparison and logical operators to define π=(π1,…,πK)\piv = (\pi_1,\dots,\pi_K). However, we need to ensure that only one πi\pi_i is non-zero. We give an example in Example 5.1.

Argmax and argmin operators

Another way to form π\piv is to use the argmax and argmin operators argmax(p)≔arg max⁡π∈{e1,…,eK}⟨π,p⟩argmin(p)≔arg min⁡π∈{e1,…,eK}⟨π,p⟩=argmax(−p).\begin{align*} \mathrm{argmax}(\p) &\coloneqq \argmax_{\piv \in \{\e_1, \dots, \e_K\}} \langle \piv, \p \rangle \\ \mathrm{argmin}(\p) &\coloneqq \argmin_{\piv \in \{\e_1, \dots, \e_K\}} \langle \piv, \p \rangle = \mathrm{argmax}(-\p). \end{align*} They can be seen as a natural generalization of the greater than and less than operators. In case of ties, we break them arbitrarily.

5.7.2 Conditionals

We can now express a conditional statement as the function
cond ⁣:{e1,…,eK}×VK→V\mathrm{cond} \colon \{\e_1, \dots, \e_K\} \times \cV^K \to \cV defined by cond(π,v1,…,vK)≔{v1 if π=e1⋮vK if π=eK=∑i=1Kπivi.\begin{align*} \mathrm{cond}(\piv, \v_1, \dots, \v_K) &\coloneqq \begin{cases} \v_1 &\mbox{ if } \piv = \e_1 \\ \vdots & \\ \v_K &\mbox{ if } \piv = \e_K \end{cases} \tag{5.5}\\ &= \sum_{i=1}^K \pi_i \v_i . \end{align*} Similarly to the ifelse\mathrm{ifelse} function, the cond\mathrm{cond} function is discontinuous and nondifferentiable w.r.t. π∈{e1,…,eK}\piv \in \{\e_1,\dots,\e_K\}. However, given π=ei\piv = \e_i fixed for some ii, the function is linear in vi\v_i and constant in vj\v_j for j≠ij \neq i. We illustrate how to express a simple example, using this formalism.

Example 5.1 (Soft-thresholding operator)

The soft-thresholding operator (see also Section 16.4) is a commonly-used operator to promote sparsity. It is defined by SoftThreshold(u,λ)≔{0 if ∣u∣≤λu−λ if u≥λu+λ if u≤−λ. \mathrm{SoftThreshold}(u, \lambda) \coloneqq \begin{cases} 0 &\mbox{ if } |u| \le \lambda \\ u - \lambda &\mbox{ if } u \ge \lambda \\ u + \lambda &\mbox{ if } u \le -\lambda \end{cases}. To express it in our formalism, we can define π∈{e1,e2,e3}\piv \in \{\e_1, \e_2, \e_3\} using comparison operators as π≔(lt(∣u∣,λ),gt(u,λ),lt(u,−λ))=(step(λ−∣u∣),step(u−λ),step(−u−λ)).\begin{align*} \piv &\coloneqq (\mathrm{lt}(|u|, \lambda), \mathrm{gt}(u, \lambda), \mathrm{lt}(u, -\lambda)) \\ &= (\heavistep(\lambda - |u|), \heavistep(u - \lambda), \heavistep(-u - \lambda)). \end{align*} Equivalently, we can also define π\piv using an argmax operator as π≔argmax((λ−∣u∣,u−λ,−u−λ)). \piv \coloneqq \mathrm{argmax}((\lambda - |u|, u - \lambda, -u - \lambda)). In case of ties, which happens at ∣u∣=λ|u|=\lambda, we keep only one non-zero coordinate in π\piv. We can then rewrite the operator as SoftThreshold(u,λ)=cond(π,0,u−λ,u+λ). \mathrm{SoftThreshold}(u, \lambda) = \mathrm{cond}(\piv, 0, u - \lambda, u + \lambda). As we will see, replacing argmax\mathrm{argmax} with softargmax\mathrm{softargmax} induces a categorical distribution over the three possible branches. The mean value can be seen as a smoothed out version of the operator, and we can also compute the standard deviation, as illustrated in Fig. 5.7.

Figure 5.7: A conditional with three branches: the soft-thresholding operator (see Example 5.1). It is a piecewise linear function (dotted black line). Using a softargmax, we can induce a categorical probability distribution over the three branches. The expected value (blue line) can be seen as a smoothed out version of the operator. The induced distribution allows us to also compute the standard deviation.

5.7.3 Differentiating through branch variables

For π\piv fixed, cond(π,v1,…,vK)\mathrm{cond}(\piv, \v_1, \dots, \v_K) is a valid function w.r.t. vi\v_i, and can therefore again be used as a node in a computational graph. Due to the linearity w.r.t. vi\v_i, we obtain that the Jacobian w.r.t. vi\v_i is ∂vicond(π,v1,…,vK)≔{I if π=ei0 if π≠ei.\begin{align*} \partial_{\v_i} \mathrm{cond}(\piv, \v_1, \dots, \v_K) &\coloneqq \begin{cases} I &\mbox{ if } \piv = \e_i \\ \zeros &\mbox{ if } \piv \neq \e_i \end{cases}. \end{align*} Let gi ⁣:Ui→Vg_i \colon \cU_i \to \cV be a differentiable function and ui∈Ui\u_i \in \cU_i. If we define the composition f(π,u1,…,uK)≔cond(π,g1(u1),…,gK(uK)), f(\piv, \u_1, \dots, \u_K) \coloneqq \mathrm{cond}(\piv, g_1(\u_1), \dots, g_K(\u_K)), we then obtain that the Jacobian w.r.t. ui\u_i is ∂uif(π,u1,…,uK)≔{∂gi(ui) if π=ei0 if π≠ei.\begin{align*} \partial_{\u_i} f(\piv, \u_1, \dots, \u_K) &\coloneqq \begin{cases} \partial g_i(\u_i) &\mbox{ if } \piv = \e_i \\ \zeros &\mbox{ if } \piv \neq \e_i \end{cases}. \end{align*} As long as the gig_i functions are differentiable, we can therefore differentiate through the branch variables ui\u_i for π\piv fixed.

5.7.4 Differentiating through predicate variables

As we saw, π\piv can be obtained by combining comparison and logical operators, or it can be obtained by argmax and argmin operators. We illustrate here why these operators are problematic. For example, suppose we want to express the function fa(p,u1,…,uK)≔{v1 if p=e1⋮vK if p=eK. f_a(\p, \u_1, \dots, \u_K) \coloneqq \begin{cases} \v_1 &\mbox{ if } \p = \e_1 \\ \vdots & \\ \v_K &\mbox{ if } \p = \e_K \end{cases}. In our notation, this can be expressed as fa(p,u1,…,uK)≔cond(argmax(p),g1(u1),…,gK(uK)), f_a(\p, \u_1, \dots, \u_K) \coloneqq \mathrm{cond}(\mathrm{argmax}(\p), g_1(\u_1), \dots, g_K(\u_K)), As for the ifelse case, the Jacobian w.r.t. p\p is null almost everywhere, ∂pfa(p,u1,…,uK)=0. \partial_\p f_a(\p, \u_1, \dots, \u_K) = \zeros.

5.7.5 Continuous relaxations

Similarly to the Heaviside step function, the argmax and argmin functions are piecewise constant, with discontinuities in case of ties. Their Jacobians are zero almost everywhere, and undefined in case of ties. Therefore, while their Jacobian is well-defined almost everywhere, they are uninformative and prevent gradient backpropagation. We can replace the argmax with a softargmax softargmax(p)≔exp⁡(p)∑i=1Kexp⁡(pi)∈△K \mathrm{softargmax}(\p) \coloneqq \frac{\exp(\p)}{\sum_{i=1}^K \exp(p_i)} \in \triangle^K and similarly softargmin(p)≔softargmax(−p)∈△K. \mathrm{softargmin}(\p) \coloneqq \mathrm{softargmax}(-\p) \in \triangle^K. Other relaxations of the argmax are possible, as discussed in Section 13.7. See also Section 14.5.3 for the perturbation perspective.

Fortunately, the definition cond(π,v1,…,vK)=∑i=1Kπivi \mathrm{cond}(\piv, \v_1, \dots, \v_K) = \sum_{i=1}^K \pi_i \v_i is perfectly valid if we use π∈△K\piv \in \triangle^K instead of π∈{e1,…,eK}\piv \in \{\e_1,\dots,\e_K\}, and can therefore be seen as an extension of Eq. (5.5). If we now define fs(p,u1,…,uK)≔cond(softargmax(p),g1(u1),…,gK(uK))=∑i=1K[softargmax(p)]i⋅gi(ui),\begin{align*} f_s(\p, \u_1, \dots, \u_K) &\coloneqq \mathrm{cond}(\softargmax(\p), g_1(\u_1), \dots, g_K(\u_K)) \\ &= \sum_{i=1}^K [\softargmax(\p)]_i \cdot g_i(\u_i), \tag{5.6}\end{align*} the Jacobian becomes ∂pfs(p,u1,…,uK)=∂softargmax(p)(g1(u1),…,gK(uK)), \partial_\p f_s(\p, \u_1, \dots, \u_K) = \partial \softargmax(\p)(g_1(\u_1), \dots, g_K(\u_K)), which is non-null everywhere, allowing gradients to backpropagate through the computational graph.

Probabilistic perspective

From a probabilistic perspective, we can view Eq. (5.6) as the expectation of gi(ui)g_i(\u_i), where i∈[K]i \in [K] is a categorical random variable distributed according to a categorical distribution with parameter π=softargmax(p)\piv = \softargmax(\p): fs(p,u1,…,uK)=Ei∼Categorical(softargmax(p))[gi(ui)]. f_s(\p, \u_1, \dots, \u_K) = \EE_{i \sim \mathrm{Categorical}(\softargmax(\p))}\left[g_i(\u_i)\right]. Taking the expectation over the KK possible branches makes the function differentiable with respect to p\p, at the cost of evaluating all branches, instead of a single one. Similarly as for the if-else case, we can compute the variance if needed as Vi∼Categorical(softargmax(p))[gi(ui)]=Ei∼Categorical(softargmax(p))[(fs(p,u1,…,uK)−gi(ui))2].\begin{align*} & \VV_{i \sim \mathrm{Categorical}(\softargmax(\p))}\left[g_i(\u_i)\right] \\ =& \EE_{i \sim \mathrm{Categorical}(\softargmax(\p))} \left[(f_s(\p, \u_1, \dots, \u_K) - g_i(\u_i))^2 \right]. \end{align*} This is illustrated in Fig. 5.7.

5.8 For loops

For loops are a control flow for sequentially calling a fixed number KK of functions, reusing the output from the previous iteration. In full generality, a for loop can be written as follows.

Algorithm 5.1: r=forloop(s0)\r = \mathrm{forloop}(\s_0)

for k≔1,…,Kk \coloneqq 1, \ldots, K do

sk≔fk(sk−1)\s_k \coloneqq f_k(\s_{k-1})

r≔sK\r \coloneqq \s_K

As illustrated in Fig. 5.8, this defines a computation chain. Assuming the functions fkf_k are all differentiable, this defines a valid computation graph, we can therefore use automatic differentiation to differentiate forloop\mathrm{forloop} w.r.t. its input s0\s_0. Feedforward networks, reviewed in Section 4.2, can be seen as parameterized for loops, i.e., fk(sk−1)≔gk(sk−1,wk), f_k(\s_{k-1}) \coloneqq g_k(\s_{k-1}, \w_k), for some differentiable function gkg_k.

Example 5.2 (Unrolled gradient descent)

Suppose we want to minimize w.r.t. w\w the function L(w,λ)≔1N∑i=1Nℓ(h(xi,w),yi)+λ2∥w∥22. L(\w, \lambda) \coloneqq \frac{1}{N} \sum_{i=1}^N \ell(h(\x_i, \w), \y_i) + \frac{\lambda}{2} \|\w\|^2_2. Given an initialization w0\w_0, gradient descent (Section 16.1) performs iterations of the form wk=f(wk−1,γk,λ)≔wk−1−γk∇1L(wk−1,λ). \w_k = f(\w_{k-1}, \gamma_k, \lambda) \coloneqq \w_{k-1} - \gamma_k \nabla_1 L(\w_{k-1}, \lambda). Gradient descent can therefore be expressed as a for loop with fk(wk−1)≔f(wk−1,γk,λ). f_k(\w_{k-1}) \coloneqq f(\w_{k-1}, \gamma_k, \lambda). This means that we can differentiate through the iterations of gradient descent, as long as ff is differentiable, meaning that LL is twice differentiable. This is useful for instance to perform gradient-based optimization of the hyperparameters γk\gamma_k or λ\lambda. This is a special case of bilevel optimization; see also Chapter 11.

Example 5.3 (Bubble sort)

Bubble sort is a simple sorting algorithm that works by repeatedly swapping elements if necessary. Mathematically, swapping two elements ii and jj can be written as a function from RN×[N]×[N]\RR^N \times [N] \times [N] to RN\RR^N defined by swap(v,i,j)≔v+(vj−vi)ei+(vi−vj)ej. \mathrm{swap}(\v, i, j) \coloneqq \v + (v_j - v_i) \e_i + (v_i - v_j) \e_j. We can then write bubble sort as for i≔1,…,N dofor j≔1,…,N−i−1 dov′≔swap(v,j,j+1)π≔step(vj−vj+1)v←ifelse(π,v′,v)\begin{align*} &\text{\bf for} ~ i \coloneqq 1,\dots,N ~ \text{\bf do} \\ &\quad \text{\bf for} ~ j \coloneqq 1, \dots, N - i - 1 ~ \text{\bf do} \\ &\quad \quad \v' \coloneqq \mathrm{swap}(\v, j, j+1) \\ &\quad \quad \pi \coloneqq \heavistep(v_j - v_{j+1}) \\ &\quad \quad \v \leftarrow \mathrm{ifelse}(\pi, \v', \v) \end{align*} Replacing the Heaviside step function with the logistic function gives a smoothed version of the algorithm.

Figure 5.8: A for loop forms a computation chain. A feed forward network can be seen as a parameterized for loop, where each function fkf_k depends on some parameters wk\w_k.

 

Figure 5.9: Computation graph of the scan function. Sequence-to-sequence RNNs can be seen as a parameterized scan function.

5.9 Scan functions

Scan is a higher-order function (meaning a function of a function) originating from functional programming. It is useful to perform an operation ff on individual elements uk\u_k while carrying the result sk\s_k of that operation to the next iteration.

Algorithm 5.2: r=scan(s0,u1,…,uK)\r = \mathrm{scan}(\s_0, \u_1, \dots, \u_K)

for k≔1,…,Kk \coloneqq 1, \ldots, K do

sk,vk≔f(sk−1,uk)\s_k, \v_k \coloneqq f(\s_{k-1}, \u_k)

r≔(sK,v1,…,vK)\r \coloneqq (\s_K, \v_1, \dots, \v_K)

As illustrated in Fig. 5.9, this again defines a valid computational graph and can be differentiated through using autodiff, assuming the function ff is differentiable. Sequence-to-sequence RNNs, reviewed in Section 4.7, can be seen as a parameterized scan. An advantage of this abstraction is that parallel scan algorithms have been studied extensively in computer science (Blelloch, 1989; Sengupta et al., 2010).

Example 5.4 (Prefix sum)

Scan can be seen as a generalization of the prefix sum (a.k.a. cumulative sum) from the addition to any binary operation. Indeed, a prefix sum amounts to perform v1≔u1v2≔u1+u2v3≔u1+u2+u3⋮\begin{align*} \v_1 &\coloneqq \u_1 \\ \v_2 &\coloneqq \u_1 + \u_2 \\ \v_3 &\coloneqq \u_1 + \u_2 + \u_3 \\ &\vdots \end{align*} which can be expressed as a scan by defining vk≔sk−1+ukf(sk−1,uk)≔(vk,vk)\begin{align*} \v_k &\coloneqq \s_{k-1} + \u_k \\ f(\s_{k-1}, \u_k) &\coloneqq (\v_k, \v_k) \end{align*} starting from s0=0\s_0 = \zeros (sK\s_K and vK\v_K are redundant in this case).

5.10 While loops

5.10.1 While loops as cyclic graphs

A while loop is a control flow used to repeatedly perform an operation, reusing the output of the previous iteration, until a certain condition is met. Suppose f ⁣:S→{0,1}f \colon \cS \to \{0,1\} is a function to determine whether to stop (π=1\pi=1) or continue (π=0\pi=0) and g ⁣:S→Sg \colon \cS \to \cS is a function for performing an operation. Then, without loss of generality, a while loop can be written as follows.

Algorithm 5.3: r=whileloop(s)\r = \mathrm{whileloop}(\s)

π←f(s)\pi \leftarrow f(\s)

while π=0\pi = 0 do

s←g(s)\s \leftarrow g(\s)

π←f(s)\pi \leftarrow f(\s)

r≔s\r \coloneqq \s

This definition is somewhat cyclic, as we used the while keyword. However, we can equivalently rewrite the algorithm recursively.

Algorithm 5.4: r=whileloop(s)\r = \mathrm{whileloop}(\s)

π≔f(s)\pi \coloneqq f(\s)

if π=0\pi = 0 then

r≔s\r \coloneqq \s

else

r≔whileloop(g(s))\r \coloneqq \mathrm{whileloop}(g(\s))

Unlike for loops and scan, the number of iterations of while loops is not known ahead of time, and may even be infinite. In this respect, a while loop can be seen as a cyclic graph, as illustrated in Fig. 5.10.

Figure 5.10: A while loop can be represented as a cyclic graph. The while loop stops if π=1\pi = 1 and performs another iteration s←g(s)\s \leftarrow g(\s), π←f(s)\pi \leftarrow f(\s) if π=0\pi = 0.

Importance of lazy evaluation

We can also implement Algorithm 5.4 in terms of the ifelse\mathrm{ifelse} function defined in Section 5.6 as r≔ifelse(f(s),whileloop(g(s)),s)=f(s)⋅whileloop(g(s))+(1−f(s))⋅s.\begin{align*} \r &\coloneqq \mathrm{ifelse}(f(\s), \mathrm{whileloop}(g(\s)), \s) \\ &= f(\s) \cdot \mathrm{whileloop}(g(\s)) + (1 - f(\s)) \cdot \s. \end{align*} However, to avoid an infinite recursion, it is crucial that ifelse\mathrm{ifelse} supports lazy evaluation. That is, whileloop(g(s))\mathrm{whileloop}(g(\s)) in the definition above should be evaluated if and only if π=f(s)=1\pi = f(\s) = 1. In other words, the fact that f(s)∈{0,1}f(\s) \in \{0,1\} is crucial to ensure that the recursion is well-defined.

5.10.2 Unrolled while loops

To avoid the issues with unbounded while loops, we can enforce that a while loop stops after TT iterations, i.e., we can truncate the while loop. Unrolling Algorithm 5.4 gives (here with T=3T=3) π0≔f(s0)if π0=1 thenr≔s0elses1≔g(s0),π1≔f(s1)if π1=1 thenr≔s1elses2≔g(s1),π2≔f(s2)if π2=1 thenr≔s2elser≔s3≔g(s2)\begin{align*} &\pi_0 \coloneqq f(\s_0) \\ &\text{\bf{if}} ~ \pi_0 = 1 ~ \textbf{\bf{then}} \\ &\quad \r \coloneqq \s_0 \\ &\text{\bf{else}} \\ &\quad \s_1 \coloneqq g(\s_0), \pi_1 \coloneqq f(\s_1) \\ &\quad \text{\bf{if}} ~ \pi_1 = 1 ~ \textbf{\bf{then}} \\ &\quad \quad \r \coloneqq \s_1 \\ &\quad \text{\bf{else}} \\ &\quad \quad \s_2 \coloneqq g(\s_1), \pi_2 \coloneqq f(\s_2) \\ &\quad \quad \text{\bf{if}} ~ \pi_2 = 1 ~ \textbf{\bf{then}} \\ &\quad \quad \quad \r \coloneqq \s_2 \\ &\quad \quad \text{\bf{else}} \\ &\quad \quad \quad \r \coloneqq \s_3 \coloneqq g(\s_2) \\ \end{align*} Using the ifelse\mathrm{ifelse} function, we can rewrite it as r=ifelse(π0,s0,ifelse(π1,s1,ifelse(π2,s2,s3)))\begin{align*} \r = \mathrm{ifelse}(&\pi_0, \\ &\s_0, \\ &\mathrm{ifelse}(\pi_1, \\ & \hspace{1cm} \s_1, \\ & \hspace{1cm} \mathrm{ifelse}(\pi_2, \\ & \hspace{2cm} \s_2, \\ & \hspace{2cm} \s_3))) \end{align*} which is itself equivalent to r=π0s0+(1−π0)[π1s1+(1−π1)[π2s2+(1−π2)s3]]=π0s0+(1−π0)π1s1+(1−π0)(1−π1)π2s2+(1−π0)(1−π1)(1−π2)s3.\begin{align*} \r &= \pi_0 \s_0 + (1-\pi_0) \left[ \pi_1 \s_1 + (1-\pi_1) \left[ \pi_2 \s_2 + (1-\pi_2) \s_3 \right] \right] \\ &= \pi_0 \s_0 + (1-\pi_0) \pi_1 \s_1 + (1-\pi_0) (1- \pi_1) \pi_2 \s_2 + (1-\pi_0) (1- \pi_1) (1 - \pi_2) \s_3. \end{align*} More generally, for T∈NT \in \NN, the formula is r=∑i=0T((1−π0)…(1−πi−1))πisi=∑i=0T(∏j=0i−1(1−πj))πisi,\begin{align*} \r & = \sum_{i=0}^T \left((1-\pi_0) \dots (1-\pi_{i-1})\right) \pi_i \s_i \\ & = \sum_{i=0}^T \left(\prod_{j=0}^{i-1} (1 - \pi_j)\right) \pi_i \s_i, \end{align*} where we defined si≔g(si−1)≔gi(s0)≔g∘⋯∘g⏟i times(s0)∈Sπi≔f(si)∈{0,1}.\begin{align*} \s_i & \coloneqq g(\s_{i-1}) \coloneqq g^{i}(\s_0) \coloneqq \underbrace{g \circ \dots \circ g}_{i \text{ times}}(\s_0) \in \cS \\ \pi_i & \coloneqq f(\s_i) \in \{0,1\}. \end{align*} See also (Petersen et al., 2021). If we further define the shorthand notation π~0≔π0π~i≔(∏j=0i−1(1−πj))πii∈{1,…,T},\begin{align*} \tilde{\pi}_0 &\coloneqq \pi_0\\ \tilde{\pi}_i &\coloneqq \left(\prod_{j=0}^{i-1}(1 - \pi_j)\right)\pi_i \quad i \in \{1,\dots,T\}, \end{align*} so that π~≔(π~0,π~1,…,π~T)∈△T+1\tilde{\piv} \coloneqq (\tilde{\pi}_0, \tilde{\pi}_1,\dots,\tilde{\pi}_T) \in \triangle^{T+1} is a discrete probability distribution containing the probabilities to stop at each of the TT iterations, we can rewrite the output of a truncated while using a conditional, r=cond(π~,s0,s1,…,sT)=∑t=0Tπ~tst. \r = \mathrm{cond}(\tilde{\piv}, \s_0, \s_1, \dots, \s_T) = \sum_{t=0}^T \tilde{\pi}_t \s_t. This is illustrated in Fig. 5.11.

Figure 5.11: Computation graph of an unrolled truncated while loop. As in Fig. 5.5, we depict continuous variables in dense lines and discrete variables in dashed lines. The output of a while loop with at most TT iterations can be written as a conditional with T+1T+1 branches, cond(π~,s0,…,sT)=∑t=0Tπ~tst\mathrm{cond}(\tilde{\piv}, \s_0, \dots, \s_T) = \sum_{t=0}^T \tilde{\pi}_t \s_t.

Example 5.5 (Computing the square root using Newton’s method)

Computing the square root x\sqrt{x} of a real number x>0x > 0 can be cast as a root finding problem, which we can solve using Newton’s method. Starting from an initialization s0s_0, the iterations read si+1≔g(si)≔12(si+xsi). s_{i+1} \coloneqq g(\s_i) \coloneqq \frac{1}{2} \left(s_i + \frac{x}{s_i}\right). To measure the error on iteration ii, we can define ε(si)≔12(si2−x)2. \varepsilon(s_i) \coloneqq \frac{1}{2}(s_i^2 - x)^2. As a stopping criterion, we can then use πi≔{1 if ε(si)≤τ0 otherwise =step(τ−ε(si)),\begin{align*} \pi_i &\coloneqq \begin{cases} 1 &\mbox{ if } \varepsilon(s_i) \le \tau \\ 0 &\mbox{ otherwise } \end{cases} \\ &= \heavistep(\tau - \varepsilon(s_i)), \end{align*} where 0<τ≪10 < \tau \ll 1 is an error tolerance and step\heavistep is the Heaviside step function.

5.10.3 Markov chain perspective

Given the function g ⁣:S→Sg \colon \cS \to \cS and the initialization s0∈S\s_0 \in \cS, a while loop can only go through a discrete set of values s0,s1,s2,…\s_0, \s_1, \s_2, \ldots defined by si=g(si−1)\s_i = g(\s_{i-1}). This set is potentially countably infinite if the while loop is unbounded, and finite if the while loop is guaranteed to stop. Whether the loop moves from the state si\s_i to the state si+1\s_{i+1}, or stays at si\s_i, is determined by the stopping criterion πi∈{0,1}\pi_i\in\{0, 1\}. To model the state of the while loop, we can then consider a Markov chain with a discrete space {s0,s1,s2,… }\{\s_0, \s_1, \s_2,\dots \}, which we can always identify with {0,1,2,… }\{0,1,2,\dots \}, with transition probabilities P(St+1=si∣St=sj)=pi,j≔{πi if i=j(1−πi) if i=j+10 otherwise , \PP(S_{t+1} = \s_i | S_t = \s_j) = p_{i,j} \coloneqq \begin{cases} \pi_i &\mbox{ if } i = j \\ (1-\pi_i) &\mbox{ if } i = j + 1 \\ 0 &\mbox{ otherwise } \end{cases}, and initial state S0=s0S_0 = \s_0. Here, StS_t is the value at iteration tt of the loop. Note that since πi∈{0,1}\pi_i \in \{0, 1\}, the pi,jp_{i,j} values are “degenerate” probabilities. However, this framework lets us generalize to a smooth version of the while loop naturally. To illustrate the framework, if the while loop stops at T=3T=3, the transition probabilities can be cast as a matrix \begin{equation*}
\mathbf{P}
\coloneqq (p_{i,j})_{i,j=0}^T
\coloneqq
\begin{blockarray}{ccccc}
& \s_0 & \s_1 & \s_2 & \s_3 \\
\begin{block}{c(cccc)}
    \s_0 & 0 & 1 & 0 & 0 \\
    \s_1 & 0 & 0 & 1 & 0 \\
    \s_2 & 0 & 0 & 0 & 1 \\
    \s_3 & 0 & 0 & 0 & 1 \\
\end{block}
\end{blockarray}.
\end{equation*} The output r\r of the while-loop is determined by the time at which the state stays at the same value I=min⁡{i∈{1,2,…} s.t. Si=Si−1}. I = \min\{i \in \{1, 2, \ldots\} \ \mbox{s.t.} \ S_i = S_{i-1}\}. Note that II itself is a random variable, as it is defined by the SiS_i variables. It is called a stopping time. The output of the chain is then r=E[SI]=∑i=1+∞P(I=i)E[Si∣I=i]=∑i=1+∞P(I=i)si−1=∑i=1+∞∏j=0i−2(1−πj)πi−1si−1=∑i=0+∞∏j=0i−1(1−πj)πisi.\begin{align*} \r & = \EE[S_I] \\ & = \sum_{i=1}^{+\infty} \PP(I= i) \EE[S_i | I = i] \\ & = \sum_{i=1}^{+\infty} \PP(I= i) \s_{i-1} \\ & = \sum_{i=1}^{+\infty} \prod_{j=0}^{i-2}(1-\pi_j) \pi_{i-1}\s_{i-1} \\ & = \sum_{i=0}^{+\infty} \prod_{j=0}^{i-1}(1-\pi_j) \pi_i\s_i. \end{align*} Because the stopping time is not known ahead of time, the sum over ii goes from 00 to ∞\infty. However, if we enforce in the stopping criterion that the while loop runs no longer than TT iterations, by setting πi≔or(f(si),eq(i,T))∈{0,1}, \pi_i \coloneqq \mbox{or}(f(\s_i), \mathrm{eq}(i, T)) \in \{0,1\}, we then naturally recover the expression found by unrolling the while loop before, r=E[SI]=∑i=0T∏j=0i−1(1−πj)πisi.\begin{align*} \r & = \EE[S_I] = \sum_{i=0}^{T} \prod_{j=0}^{i-1}(1-\pi_j) \pi_i\s_i. \end{align*} For example, with T=3T=3, the transition probability matrix is \begin{equation*}
\mathbf{P} =
\begin{blockarray}{ccccc}
& \s_0 & \s_1 & \s_2 & \s_3 \\
\begin{block}{c(cccc)}
    \s_0 & \pi_0 & 1-\pi_0 & 0 & 0 \\
    \s_1 & 0 & \pi_1 & 1-\pi_1 & 0 \\
    \s_2 & 0 & 0 & \pi_2 & 1 - \pi_2 \\
    \s_3 & 0 & 0 & 0 & 1 \\
\end{block}
\end{blockarray}.
\end{equation*}

Smoothed while loops

With the help of this framework, we can backpropagate even through the while loop’s stopping criterion, provided that we smooth out the predicate. For example, we saw that the stopping criterion in Example 5.5 is f(si)=step(τ−ε(si))f(\s_i) = \heavistep(\tau - \varepsilon(\s_i)) and therefore πi≔or(f(si),eq(i,T))∈{0,1}. \pi_i \coloneqq \mbox{or}(f(\s_i), \mathrm{eq}(i, T)) \in \{0,1\}. Due to the step\heavistep function, the derivative of the while loop with respect to τ\tau will always be 00, just like it was the case for if-else statements. If we change the stopping criterion to f(si)=sigmoid(τ−ε(si))f(\s_i) = \sigmoid(\tau - \varepsilon(\s_i)), we then have (recall that or\mathrm{or} is well defined on [0,1]×[0,1][0,1] \times [0,1]) πi≔or(f(si),eq(i,T))∈[0,1]. \pi_i \coloneqq \mathrm{or}(f(\s_i), \mathrm{eq}(i, T)) \in [0,1]. With sigmoid\sigmoid, we obtain more informative derivatives. In particular, with sigmoid=logistic\sigmoid = \logistic, the derivatives w.r.t. τ\tau are always non-zero. The smoothed output is expressed as before as the expectation r=E[SI]=∑i=0T∏j=0i−1(1−πj)πisi \r = \EE[S_I] = \sum_{i=0}^{T} \prod_{j=0}^{i-1}(1-\pi_j) \pi_i\s_i where πi≔sigmoid(τ−ε(si)). \pi_i \coloneqq \sigmoid(\tau - \varepsilon(\s_i)). Instead of enforcing a number TT of iterations, it is also possible to stop when the probability of stopping becomes high enough (Petersen et al., 2021), assuming that the probability of stopping converges to 11.

5.11 Summary