home

Convexity and Jensen’s Inequality

Curvature tells us how a function compares with its tangents, chords, and averages. Convex bends upward; concave bends downward.


Convexity and Jensen’s Inequality

Download

PNG PNG (HD) PDF SVG

Code

convexity-and-jensens-inequality.typ (216 lines)

#import "@preview/cetz:0.5.2": canvas, draw
#import "@preview/cetz-plot:0.1.4": plot

#set page(width: 780pt, height: auto, margin: 22pt, fill: none)
#set text(font: "Avenir Next", size: 10.5pt, fill: rgb("#19324f"))
#set par(leading: 0.55em)

#let card-grid(columns: 2, ..cards) = layout(size => {
  let rows = cards
    .pos()
    .chunks(columns)
    .map(row => {
      let ratios = row.map(card => {
        let bounds = measure(card.at(1))
        bounds.width / bounds.height
      })
      let available = size.width - 12pt * (row.len() - 1) - 24pt * row.len()
      grid(
        columns: ratios.map(ratio => 24pt + available * ratio / ratios.sum()),
        gutter: 12pt,
        ..row.map(((title, body, caption)) => block(
          width: 100%,
          inset: 12pt,
          radius: 8pt,
          fill: rgb("#cdd3da"),
          breakable: false,
        )[
          #text(size: 13pt, weight: "bold", title)
          #v(8pt)
          // Fill the available width; each drawing keeps its own aspect ratio.
          #layout(size => std.scale(
            size.width / measure(body).width * 100%,
            reflow: true,
            body,
          ))
          #v(7pt)
          #caption
        ]),
      )
    })
  stack(dir: ttb, spacing: 12pt, ..rows)
})
#let takeaway = block.with(
  width: 100%,
  inset: 12pt,
  radius: 6pt,
  fill: rgb("#c6d8d2"),
  breakable: false,
)

// === 1  Convex: above a tangent ===
#let figure-0 = canvas({
  draw.set-style(legend: (fill: rgb("#cdd3da")))
  let axis-mark = (end: "stealth", fill: black)
  draw.set-style(axes: (
    x: (mark: axis-mark, label: (anchor: "north", offset: 0.1)),
    y: (mark: axis-mark, label: (anchor: "north-west", offset: -0.2)),
  ))
  plot.plot(
    size: (8, 5),
    x-label: $x$,
    y-tick-step: 1,
    x-tick-step: 1,
    x-grid: true,
    y-grid: true,
    legend: "inner-north-west",
    // Compact legend with a thin border.
    legend-style: (item: (spacing: 0.15), padding: 0.15, stroke: 0.5pt),
    axis-style: "left",
    {
      // x ln(x) function
      plot.add(
        style: (stroke: blue + 1.5pt),
        domain: (0.01, 2.7), // avoid x=0 since ln(0) is undefined
        samples: 100,
        label: $x ln(x)$,
        x => x * calc.ln(x),
      )

      // x-1 function
      plot.add(
        style: (stroke: red + 1.5pt),
        domain: (0, 2.7),
        label: $x-1$,
        x => x - 1,
      )
    },
  )
})

// === 2  Concave: reverse the inequality ===
#let figure-1 = canvas({
  draw.set-style(legend: (fill: rgb("#cdd3da")))
  let axis-mark = (end: "stealth", fill: black)
  draw.set-style(axes: (
    x: (mark: axis-mark),
    y: (mark: axis-mark, label: (anchor: "north-west", offset: -0.2)),
  ))
  plot.plot(
    size: (8, 5),
    x-min: 0,
    x-max: 1,
    x-label: $x$,
    y-tick-step: 0.2,
    x-tick-step: 0.2,
    x-grid: true,
    y-grid: true,
    legend: "inner-north-west",
    // Compact legend with a thin border.
    legend-style: (item: (spacing: 0.15), padding: 0.15, stroke: 0.5pt),
    axis-style: "left",
    {
      // x function
      plot.add(style: (stroke: blue + 1.5pt), domain: (0, 1), label: $x$, x => { x })
      // -x ln(x) function
      plot.add(
        style: (stroke: red + 1.5pt),
        domain: (0.01, 1), // avoid x=0 since ln(0) is undefined
        samples: 100,
        label: $-x ln(x)$,
        x => -x * calc.ln(x),
      )
    },
  )
})

// === 3  The local picture for log ===
#let figure-2 = canvas({
  draw.set-style(legend: (fill: rgb("#cdd3da")))
  let axis-mark = (end: "stealth", fill: black, scale: 0.7)
  draw.set-style(axes: (
    x: (mark: axis-mark, label: (anchor: "south-east", offset: -0.25)),
    y: (mark: axis-mark, label: (anchor: "north-west", offset: -0.2)),
  ))

  plot.plot(
    size: (8, 6),
    x-label: $x$,
    y-label: $log x$,
    y-min: -1,
    x-tick-step: none,
    y-tick-step: none,
    axis-style: "school-book",
    {
      // Main logarithmic curve
      plot.add(
        style: (stroke: rgb(0%, 0%, 80%) + 1.5pt),
        domain: (11, 150),
        samples: 150,
        x => calc.ln(x - 10) - 2,
      )

      // Dashed line
      plot.add(
        style: (
          stroke: (paint: orange, thickness: 1.5pt, dash: "dashed"),
        ),
        domain: (8, 120),
        x => 0.2 + (3 - 0.2) * (x - 8) / (120 - 8),
      )
    },
  )
})

// === 4  Average first, or apply f first? ===
#let figure-3 = canvas({
  draw.set-style(legend: (fill: rgb("#cdd3da")))
  let curve(x) = 0.3 * x * x
  draw.line((0, 0), (4.5, 0), mark: (end: "stealth"))
  draw.line((0, 0), (0, 5.3), mark: (end: "stealth"))
  draw.line(
    ..range(0, 81).map(idx => {
      let x = idx / 20
      (x, curve(x))
    }),
    stroke: blue + 1.5pt,
  )
  draw.line((1, curve(1)), (4, curve(4)), stroke: rgb("#c45a31") + 1.3pt)
  draw.line((2.5, 0), (2.5, 2.55), stroke: (dash: "dashed", paint: gray))
  draw.circle((2.5, curve(2.5)), radius: 0.07, fill: blue)
  draw.circle((2.5, 2.55), radius: 0.07, fill: rgb("#c45a31"))
  draw.content((2.5, -0.25), $bar(x)$, anchor: "north")
  draw.content((2.35, curve(2.5)), $f(bar(x))$, anchor: "east", padding: 4pt)
  draw.content((1.6, 3.15), [average of $f$], anchor: "south")
})

#text(size: 27pt, weight: "bold")[Convexity and Jensen’s Inequality]
#v(5pt)
Curvature tells us how a function compares with its tangents, chords, and averages. Convex bends upward; concave bends downward.
#v(14pt)
#card-grid(
  (
    [1  Convex: above a tangent],
    figure-0,
    [For $f(x)=x ln x$ ($x>0$), the tangent at $x=1$ is $x-1$. Thus $x ln x >= x-1$, with equality at the contact point.],
  ),
  (
    [2  Concave: reverse the inequality],
    figure-1,
    [Negating $x ln x$ reverses its curvature. A straight line is both convex and concave. Curvature statements apply on the specified domain.],
  ),

  (
    [3  The local picture for log],
    figure-2,
    [The concave logarithm lies below its tangent. To understand Jensen’s inequality, compare a point on the curve with the chord between two sampled values.],
  ),
  (
    [4  Average first, or apply f first?],
    figure-3,
    [For convex $f$, $f(sum_i w_i x_i) <= sum_i w_i f(x_i)$ when $w_i >= 0$ and $sum_i w_i=1$. For concave $f$, reverse the sign.],
  ),
)
#v(12pt)
#takeaway[*Tangent = local slope; chord = interpolation between two points.* Jensen compares the function of an average with the average of the function.]