Skip to content

← JAX Conceptual Deep-Dives step 14 of 15

Hard Primitives

JVP with Two Input Directions

Jump to the task

Change two inputs together

A Jacobian-vector product describes how a function responds along a chosen input direction. When the function has two arguments, provide a direction for each. JAX adds their contributions to the output tangent.

import jax
import jax.numpy as jnp

def f(a, b):
    return jnp.sum(a * b)

a = jnp.array([1.0, 2.0])
b = jnp.array([3.0, 4.0])
da = jnp.array([1.0, 0.0])
db = jnp.array([0.0, 1.0])
value, tangent = jax.jvp(f, (a, b), (da, db))
# value = 1*3 + 2*4 = 11
# tangent = sum(da*b + a*db) = 3 + 2 = 5

This differentiates the path f(a + epsilon*da, b + epsilon*db) at epsilon=0. The tangent is the rate of change along the whole path, not the exact difference between two evaluations a finite distance apart.

Match the input structure

The outer tuple holds one entry per positional argument. Matching lists also work. Each real floating-point input array needs a tangent with its shape and dtype. To hold an array fixed, supply jnp.zeros_like for its tangent; None is not a replacement for an array tangent.

The same rule extends to nested dictionaries and lists, called pytrees: every input array leaf needs a corresponding tangent leaf. This exercise uses two array arguments, so its structure is simply a pair of arrays. The separate diagram illustrates a more deeply nested tree. Its numbered leaves are placeholders, not the exercise's input values.

Loading visualization…

Problem

Implement jvp_split_tangent(x_first, x_second, v_first, v_second). All four inputs are one-dimensional real floating-point JAX arrays with the same shape and dtype. Define f(x_first, x_second) = sum(x_first**2 + 2*x_second).

Use jax.jvp with directions (v_first, v_second) and return a JAX array with shape (2,), containing [value, tangent] in that order. Do not normalize the directions.

The first argument contributes sum(2*x_first*v_first) to the tangent; the second contributes 2*sum(v_second). Notice that the second contribution does not depend on x_second, since that term is linear.

For x_first=[1.0, 2.0], x_second=[3.0, 4.0], v_first=[-1.0, 0.0], and v_second=[0.0, 2.0], the value is 19. The tangent is -2 + 4 = 2, so return [19.0, 2.0].